void map_page(uint32_t *page_dir, uint32_t virt_page_num, uint32_t phy_page_num, bool global, bool user, bool read_write) { uint16_t pd_idx = PD_IDX(virt_page_num), pt_idx = PT_IDX(virt_page_num); uint32_t *page_table; if(!(page_dir[pd_idx] & 0x1)) { uint32_t pt_page_num = alloc_phy_page(0, 1023); map_kernel_page(pt_page_num, pt_page_num, true, false, true); memset((void *)(pt_page_num << 12), 0, 4096); page_dir[pd_idx] = make_pde(pt_page_num, user, read_write); } page_table = (uint32_t *)(page_dir[pd_idx] & 0xfffff000); page_table[pt_idx] = make_pte(phy_page_num, global, user, read_write); ++phy_mem_rc[phy_page_num]; __asm__ volatile( ".intel_syntax noprefix;" "mov eax, cr3;" "mov cr3, eax;" ".att_syntax;" :::"eax" ); }
pte_t *mmap_lookup(pml4e_t *pml4, uint64_t va, bool create) { struct page *page4pdp = NULL, *page4pd = NULL, *page4pt = NULL; pdpe_t pml4e = pml4[PML4_IDX(va)]; if ((pml4e & PML4E_P) != 0) goto pml4e_found; if (create == false) return NULL; // Prepare new page directory pointer if ((page4pdp = page_alloc()) == NULL) return NULL; memset(page2kva(page4pdp), 0, PAGE_SIZE); page4pdp->ref = 1; // Insert new pdp into PML4 pml4e = pml4[PML4_IDX(va)] = page2pa(page4pdp) | PML4E_P | PML4E_W | PML4E_U; pml4e_found: assert((pml4e & PML4E_P) != 0); pdpe_t *pdp = VADDR(PML4E_ADDR(pml4e)); pdpe_t pdpe = pdp[PDP_IDX(va)]; if ((pdpe & PDPE_P) != 0) goto pdpe_found; if (create == false) return NULL; // Prepare new page directory if ((page4pd = page_alloc()) == NULL) return NULL; memset(page2kva(page4pd), 0, PAGE_SIZE); page4pd->ref = 1; // Insert new page directory into page directory pointer table pdpe = pdp[PDP_IDX(va)] = page2pa(page4pd) | PDPE_P | PDPE_W | PDPE_U; pdpe_found: assert((pdpe & PDPE_P) != 0); pde_t *pd = VADDR(PDPE_ADDR(pdpe)); pde_t pde = pd[PD_IDX(va)]; if ((pde & PDE_P) != 0) goto pde_found; if (create == false) return NULL; // Prepare new page table if ((page4pt = page_alloc()) == NULL) return NULL; memset(page2kva(page4pt), 0, PAGE_SIZE); page4pt->ref = 1; // Insert new page table into page directory pde = pd[PD_IDX(va)] = page2pa(page4pt) | PDE_P | PTE_W | PDE_U; pde_found: assert((pde & PDE_P) != 0); pte_t *pt = VADDR(PDE_ADDR(pde)); return &pt[PT_IDX(va)]; }