다음의 영역들을 1차 페이지 테이블에서 초기화 하고 해당 영역에 대한 1차 및 2차 TLB 엔트리를 제거(invalidate)한다.
- 0x0 ~ MODULES_VADDR 영역
- 모듈 시작 영역은 커널 시작 가상 주소(PAGE_OFFSET) – 16M이다.
- MODULES_VADDR ~ PAGE_OFFSET 영역
- lowmem 남은 공간 부터 VMALLOC_START 영역
- VMALLOC 영역이 가장 작아졌을 때 VMALLOC_START 값은 0xf000_0000(ef80_0000 + 0x80_0000)이다.
- arm_lowmem_limit 주소를 가상주소로 변환한 주소가 high_memory이며 VMALLOC_START는 여기에 VMALLOC_OFFSET(8M)를 더한 후 8M round up한 주소이다.
prepare_page_table()
arch/arm/mm/mmu.c
static inline void prepare_page_table(void) { unsigned long addr; phys_addr_t end; /* * Clear out all the mappings below the kernel image. */ for (addr = 0; addr < MODULES_VADDR; addr += PMD_SIZE) pmd_clear(pmd_off_k(addr)); #ifdef CONFIG_XIP_KERNEL /* The XIP kernel is mapped in the module area -- skip over it */ addr = ((unsigned long)_etext + PMD_SIZE - 1) & PMD_MASK; #endif for ( ; addr < PAGE_OFFSET; addr += PMD_SIZE) pmd_clear(pmd_off_k(addr)); /* * Find the end of the first block of lowmem. */ end = memblock.memory.regions[0].base + memblock.memory.regions[0].size; if (end >= arm_lowmem_limit) end = arm_lowmem_limit; /* * Clear out all the kernel space mappings, except for the first * memory bank, up to the vmalloc region. */ for (addr = __phys_to_virt(end); addr < VMALLOC_START; addr += PMD_SIZE) pmd_clear(pmd_off_k(addr)); }
- for (addr = 0; addr < MODULES_VADDR; addr += PMD_SIZE)
- 페이지 테이블의 0x0000_0000 ~ MODULES_VADDR 가상 주소까지에 대응하는 2M 단위의 엔트리를 clear한다.
- MODULES_VADDR
- PAGE_OFFSET – 16M
- rpi2: 0x7f00_0000
- pmd_clear(pmd_off_k(addr));
- 가상주소에 해당하는 pmd 엔트리 주소를 알아온 후 그 주소의 pmd 엔트리를 clear 한다.
- 가상주소에 해당하는 TLB 캐시 엔트리도 clean 한다.
- 참고: TLB Cache (API) | 문c
- addr = ((unsigned long)_etext + PMD_SIZE – 1) & PMD_MASK;
- XIP 커널의 경우 시작 주소에 따라 모듈 영역에 대한 페이지 테이블 초기화는 다음과 같이 처리된다.
- _etext는 PAGE_OFFSET 하단에 위치 즉, 모듈 영역에 위치하므로 addr 주소를 _etext의 2M round up한 주소로 한다.
- XIP 커널의 경우 시작 주소에 따라 모듈 영역에 대한 페이지 테이블 초기화는 다음과 같이 처리된다.
- for ( ; addr < PAGE_OFFSET; addr += PMD_SIZE)
- XIP 커널이 아닌 경우 모듈 시작 주소부터 PAGE_OFFSET 까지의 가상 주소까지에 대응하는 2M 단위의 엔트리를 clear 한다.
- 만일 XIP 커널인 경우는 재 산정된 addr 주소 부터 PAGE_OFFSET 까지의 가상 주소까지에 대응하는 2M 단위의 pmd 엔트리를 clear 한다.
- end = memblock.memory.regions[0].base + memblock.memory.regions[0].size;
- end = 물리 메모리의 끝 주소
- if (end >= arm_lowmem_limit) end = arm_lowmem_limit;
- 물리 메모리가 lowmem 영역 한계치(arm_lowmem_limit)를 초과하는 경우 끝 주소를 lowmem 영역의 한계치로 대입한다.
- for (addr = __phys_to_virt(end); addr < VMALLOC_START; addr += PMD_SIZE)
- lowmem 영역 내에서의 끝 주소를 가상주소로 바꾼 주소부터 VMALLOC_START 주소까지 2M 단위로 증가시키며 이에 대응하는 2M 단위의 pmd 엔트리를 clear 한다.