/* * Maps a page (PAE). * uint64_t VirtAddr -> the virtual address where to map the frame to. * uint64_t PhysAddr -> the physical address of the frame to map to the page. */ void PAEPagingMap(uint64_t VirtAddr, uint64_t PhysAddr) { char _CONST *ErrorFrameAlloc = "ERROR: Unable to allocate pages for the VMM."; PageDirEntry_t *PageDir; PageTableEntry_t *PageTable; PageDir = (PageDirEntry_t*)(uint32_t)(PDPT[PDPT_INDEX(VirtAddr)] & PAGE_MASK); // If page table isn't present, make one. if(!(PageDir[PD_INDEX(VirtAddr)] & PRESENT_BIT)) { PageTable = (PageTableEntry_t*)AllocFrameFunc(POOL_BITMAP); if(!PageTable) { // Switch to text mode. VideoAPIFunc(VIDEO_VGA_SWITCH_MODE, MODE_80_25_TEXT); AbortBootFunc(ErrorFrameAlloc); } memset(PageTable, 0x00000000, PAGE_SIZE); PageDir[PD_INDEX(VirtAddr)] = (PageDirEntry_t)PageTable | PRESENT_BIT; } else { PageTable = (PageTableEntry_t*)(uint32_t)(PageDir[PD_INDEX(VirtAddr)] & PAGE_MASK); } PageTable[PT_INDEX(VirtAddr)] = PhysAddr | PRESENT_BIT; }
bool arch_mm_context_read(struct vmm_context *ctx, void *output, addr_t address, size_t length) { int pml4idx = PML4_INDEX(address); int pdptidx = PDPT_INDEX(address); int pdidx = PD_INDEX(address); addr_t destp; addr_t offset; addr_t *pml4v = (addr_t *)ctx->root_virtual; if(!pml4v[pml4idx]) { return false; } addr_t *pdptv = (addr_t *)((pml4v[pml4idx] & PAGE_MASK_PHYSICAL) + PHYS_PAGE_MAP); if(!pdptv[pdptidx]) { return false; } addr_t *pdv = (addr_t *)((pdptv[pdptidx] & PAGE_MASK_PHYSICAL) + PHYS_PAGE_MAP); if(!(pdv[pdidx] & PAGE_LARGE)) { int ptidx = PT_INDEX(address); offset = address & (0x1000 - 1); if(offset + length > 0x1000) PANIC(0, "mm_context_read crossed page boundary", EFAULT); if(!pdv[pdidx]) { return false; } addr_t *ptv = (addr_t *)((pdv[pdidx] & PAGE_MASK_PHYSICAL) + PHYS_PAGE_MAP); if(!ptv[ptidx]) { return false; } destp = ptv[ptidx] & PAGE_MASK_PHYSICAL; } else { offset = address & (0x200000 - 1); if(offset + length > 0x200000) PANIC(0, "mm_context_read crossed page boundary", EFAULT); if(!pdv[pdidx]) { return false; } destp = pdv[pdidx] & PAGE_MASK_PHYSICAL; } memcpy(output, (void *)(destp + PHYS_PAGE_MAP + offset), length); return true; }
bool arch_mm_context_virtual_getmap(struct vmm_context *ctx, addr_t address, addr_t *phys, int *flags) { int pml4idx = PML4_INDEX(address); int pdptidx = PDPT_INDEX(address); int pdidx = PD_INDEX(address); addr_t destp; addr_t *pml4v = (addr_t *)ctx->root_virtual; if(!pml4v[pml4idx]) { return false; } addr_t *pdptv = (addr_t *)((pml4v[pml4idx] & PAGE_MASK_PHYSICAL) + PHYS_PAGE_MAP); if(!pdptv[pdptidx]) { return false; } addr_t *pdv = (addr_t *)((pdptv[pdptidx] & PAGE_MASK_PHYSICAL) + PHYS_PAGE_MAP); if(!(pdv[pdidx] & PAGE_LARGE)) { int ptidx = PT_INDEX(address); if(!pdv[pdidx]) { return false; } addr_t *ptv = (addr_t *)((pdv[pdidx] & PAGE_MASK_PHYSICAL) + PHYS_PAGE_MAP); if(!ptv[ptidx]) { return false; } destp = ptv[ptidx]; } else { if(!pdv[pdidx]) { return false; } destp = pdv[pdidx]; } if(phys) *phys = destp & PAGE_MASK_PHYSICAL; if(flags) *flags = destp & ATTRIB_MASK; return true; }