map_lowmem()

lowmem 영역을 페이지 테이블에 매핑하는데 각 영역에 따라 MT_MEMORY_RW 또는 MT_MEMORY_RWX 타입으로 매핑한다.

map_lowmem()

map_lowmem-1a

 

arch/arm/mm/mmu.c

static void __init map_lowmem(void)
{
        struct memblock_region *reg;
        phys_addr_t kernel_x_start = round_down(__pa(_stext), SECTION_SIZE);
        phys_addr_t kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE);

        /* Map all the lowmem memory banks. */
        for_each_memblock(memory, reg) {
                phys_addr_t start = reg->base;
                phys_addr_t end = start + reg->size;
                struct map_desc map; 

                if (end > arm_lowmem_limit)
                        end = arm_lowmem_limit;
                if (start >= end) 
                        break;
  • phys_addr_t kernel_x_start = round_down(__pa(_stext), SECTION_SIZE);
    • 커널의 물리 시작 주소를 1M round down
  • phys_addr_t kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE);
    • 커널의 __init_end 주소를 1M round up
      • __init_end
        • 커널의 코드 영역 끝나고 .data 섹션 안에 위치한 init data 종료 주소

 

                if (end < kernel_x_start) {
                        map.pfn = __phys_to_pfn(start);
                        map.virtual = __phys_to_virt(start);
                        map.length = end - start;
                        map.type = MT_MEMORY_RWX;

                        create_mapping(&map);
  • 다음 그림과 같이 비교할 memblock이 커널보다 아래에 위치하는 경우 이 memblock을 MT_MEMORY_RWX 타입으로 매핑한다.

map_lowmem-2b

 

                } else if (start >= kernel_x_end) {
                        map.pfn = __phys_to_pfn(start);
                        map.virtual = __phys_to_virt(start);
                        map.length = end - start;
                        map.type = MT_MEMORY_RW;

                        create_mapping(&map);
  • 다음 그림과 같이 비교할 memblock이 커널보다 위에 위치하는 경우 이 memblock을 MT_MEMORY_RW 타입으로 매핑한다.

map_lowmem-3b

 

                } else {
                        /* This better cover the entire kernel */
                        if (start < kernel_x_start) {
                                map.pfn = __phys_to_pfn(start);
                                map.virtual = __phys_to_virt(start);
                                map.length = kernel_x_start - start;
                                map.type = MT_MEMORY_RW;

                                create_mapping(&map);
                        }

                        map.pfn = __phys_to_pfn(kernel_x_start);
                        map.virtual = __phys_to_virt(kernel_x_start);
                        map.length = kernel_x_end - kernel_x_start;
                        map.type = MT_MEMORY_RWX;

                        create_mapping(&map);

                        if (kernel_x_end < end) {
                                map.pfn = __phys_to_pfn(kernel_x_end);
                                map.virtual = __phys_to_virt(kernel_x_end);
                                map.length = end - kernel_x_end;
                                map.type = MT_MEMORY_RW;

                                create_mapping(&map);
                        }
                }
        }
}
  • 다음 그림과 같이 비교할 memblock이 커널을 포함하는 경우 이 memblock을 3등분 하여 각각의 영역을 아래와 같은 타입으로 매핑한다.

map_lowmem-4a

 

참고

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.