I’m reading the sel4test source code, and the there is a function called map_kernel_window when system is booting. After called map_kernel_window function, the system will enable the pagetable mode.
When I read the map_kernel_window function and found that just two-level page tables are populated, but using the SV39, so I think the page table is not fully populated, and when enable the pagetable mode, I thought the kernel execution would go wrong, but it didn’t. The map_kernel_window function was followed:
BOOT_CODE VISIBLE void map_kernel_window(void)
{
/* mapping of KERNEL_ELF_BASE (virtual address) to kernel's
* KERNEL_ELF_PHYS_BASE */
assert(CONFIG_PT_LEVELS > 1 && CONFIG_PT_LEVELS <= 4);
/* kernel window starts at PPTR_BASE */
word_t pptr = PPTR_BASE;
/* first we map in memory from PADDR_BASE */
word_t paddr = PADDR_BASE;
while (pptr < PPTR_TOP) {
assert(IS_ALIGNED(pptr, RISCV_GET_LVL_PGSIZE_BITS(0)));
assert(IS_ALIGNED(paddr, RISCV_GET_LVL_PGSIZE_BITS(0)));
// printf("RISCV_GET_PT_INDEX(pptr, 0): %llx\n", (long long unsigned int)(RISCV_GET_PT_INDEX(pptr, 0)));
kernel_root_pageTable[RISCV_GET_PT_INDEX(pptr, 0)] = pte_next(paddr, true);
pptr += RISCV_GET_LVL_PGSIZE(0);
paddr += RISCV_GET_LVL_PGSIZE(0);
}
/* now we should be mapping the 1GiB kernel base */
assert(pptr == PPTR_TOP);
pptr = ROUND_DOWN(KERNEL_ELF_BASE, RISCV_GET_LVL_PGSIZE_BITS(0));
paddr = ROUND_DOWN(KERNEL_ELF_PADDR_BASE, RISCV_GET_LVL_PGSIZE_BITS(0));
#if __riscv_xlen == 32
kernel_root_pageTable[RISCV_GET_PT_INDEX(pptr, 0)] = pte_next(paddr, true);
pptr += RISCV_GET_LVL_PGSIZE(0);
paddr += RISCV_GET_LVL_PGSIZE(0);
#ifdef CONFIG_KERNEL_LOG_BUFFER
kernel_root_pageTable[RISCV_GET_PT_INDEX(KS_LOG_PPTR, 0)] =
pte_next(kpptr_to_paddr(kernel_image_level2_log_buffer_pt), false);
#endif
#else
word_t index = 0;
/* The kernel image is mapped twice, locating the two indexes in the
* root page table, pointing them to the same second level page table.
*/
kernel_root_pageTable[RISCV_GET_PT_INDEX(KERNEL_ELF_PADDR_BASE + PPTR_BASE_OFFSET, 0)] =
pte_next(kpptr_to_paddr(kernel_image_level2_pt), false);
kernel_root_pageTable[RISCV_GET_PT_INDEX(pptr, 0)] =
pte_next(kpptr_to_paddr(kernel_image_level2_pt), false);
while (pptr < PPTR_TOP + RISCV_GET_LVL_PGSIZE(0)) {
kernel_image_level2_pt[index] = pte_next(paddr, true);
index++;
pptr += RISCV_GET_LVL_PGSIZE(1);
paddr += RISCV_GET_LVL_PGSIZE(1);
}
/* Map kernel device page table */
kernel_root_pageTable[RISCV_GET_PT_INDEX(KDEV_BASE, 0)] =
pte_next(kpptr_to_paddr(kernel_image_level2_dev_pt), false);
#endif
/* There should be 1GiB free where we put device mapping */
assert(pptr == UINTPTR_MAX - RISCV_GET_LVL_PGSIZE(0) + 1);
map_kernel_devices();
}
Can someone tell me what’s going on?