int kernel_start() { int i; // point to low address (0GB ~ ...) pgd_tmp[PGD_INDEX(0)] = (uint32_t)pte_low | PAGE_PRESENT | PAGE_WRITE; // point to high address (3GB ~ 4GB) pgd_tmp[PGD_INDEX(PAGE_OFFSET)] = (uint32_t)pte_hig | PAGE_PRESENT | PAGE_WRITE; for (i = 0; i < 1024; i++) { pte_low[i] = (i << 12) | PAGE_PRESENT | PAGE_WRITE; } for (i = 0; i < 1024; i++) { pte_hig[i] = (i << 12) | PAGE_PRESENT | PAGE_WRITE; } // set page directory set_cr3(pgd_tmp); page_on(); kernel_stack_top = ((uint32_t)kernel_stack + STACK_SIZE) & 0xFFFFFFF0; set_esp(kernel_stack_top); global_mboot_ptr = (multiboot_t *)((uint32_t)global_mboot_tmp + PAGE_OFFSET); kernel_init(); return 0; }
void map(pgd_t *pgd_now, uint32_t va, uint32_t pa, uint32_t flags) { uint32_t pgd_idx = PGD_INDEX(va); uint32_t pte_idx = PTE_INDEX(va); pte_t *pte = (pte_t *)(pgd_now[pgd_idx] & PAGE_MASK); if (!pte) { pte = (pte_t *)alloc_pages(1); pgd_now[pgd_idx] = (uint32_t)pte | PAGE_PRESENT | PAGE_WRITE; pte = (pte_t *)pa_to_ka(pte); } else { pte = (pte_t *)pa_to_ka(pte); } pte[pte_idx] = (pa & PAGE_MASK) | flags; tlb_reload_page(va); }
void unmap(pgd_t *pgd_now, uint32_t va) { uint32_t pgd_idx = PGD_INDEX(va); uint32_t pte_idx = PTE_INDEX(va); pte_t *pte = (pte_t *)(pgd_now[pgd_idx] & PAGE_MASK); if (!pte) { return; } // 转换到内核线性地址 pte = (pte_t *)(pa_to_ka(pte)); pte[pte_idx] = 0; tlb_reload_page(va); }
uint32_t get_mapping(pgd_t *pgd_now, uint32_t va, uint32_t *pa) { uint32_t pgd_idx = PGD_INDEX(va); uint32_t pte_idx = PTE_INDEX(va); pte_t *pte = (pte_t *)(pgd_now[pgd_idx] & PAGE_MASK); if (!pte) { return 0; } // 转换到内核线性地址 pte = (pte_t *)(pa_to_ka(pte)); // 如果地址有效而且指针不为NULL,则返回地址 if (pte[pte_idx] != 0 && pa) { *pa = pte[pte_idx] & PAGE_MASK; return 1; } return 0; }
void vmm_init(void) { // 注册页错误中断的处理函数 register_interrupt_handler(INT_PAGE_FAULT, &do_page_fault); // 页表数组指针 pte_t (*pte_kern)[PTE_SIZE] = (pte_t (*)[PTE_SIZE])pte_addr; // 构造页目录(MMU需要的是物理地址,此处需要减去偏移) uint32_t pgd_idx = PGD_INDEX(PAGE_OFFSET); for (uint32_t i = pgd_idx; i < pgd_idx + PTE_COUNT; ++i) { pgd_kern[i] = ((uint32_t)ka_to_pa(pte_kern[i])) | PAGE_PRESENT | PAGE_WRITE; } // 构造页表映射,内核 0xC0000000~0xF8000000 映射到 物理 0x00000000~0x38000000 (物理内存前896MB) uint32_t *pte_start = (uint32_t *)(pte_addr + PTE_SIZE * pgd_idx); for (uint32_t i = 0; i < PTE_SIZE * PTE_COUNT; ++i) { pte_start[i] = (i << 12) | PAGE_PRESENT | PAGE_WRITE; } switch_pgd((uint32_t)ka_to_pa(pgd_kern)); }