void map_pages(uint32_t physical_address, uint32_t virtual_address, uint32_t size, uint32_t protect = PT_PRESENT | PT_WRITABLE | PT_USER) { int pages = SIZE_TO_PAGES(size); for (int i = 0; i < pages; i++) { UINT32 pde_index = PDE_INDEX(virtual_address); UINT32 pte_index = PTE_INDEX(virtual_address); UINT32* page_table = (UINT32*)(PAGE_TABLE_PHYSICAL_ADDR + pde_index*PAGE_SIZE); page_table[pte_index] = physical_address | protect; physical_address += PAGE_SIZE; virtual_address += PAGE_SIZE; } }
static void pt_map(pmap_t *pmap, vm_addr_t vaddr, pm_addr_t paddr, uint8_t flags) { pde_map(pmap, vaddr); pte_t entry = flags; uint32_t pt_index = PTE_INDEX(vaddr); ENTRYLO_SET_PADDR(entry , paddr); pmap->pte[pt_index] = entry; /* invalidate proper entry in tlb */ tlbhi_t entryhi = 0; ENTRYHI_SET_VADDR(entryhi, vaddr); ENTRYHI_SET_ASID(entryhi, pmap->asid); tlb_invalidate(entryhi); }
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); }
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); }
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 HalpReleaseReservedVirtualSpace( PVOID VirtualAddress, ULONG LengthInPages ) /*++ Routine Description: This function will release the virtual address range previously allocated with HalpAssignReservedVirtualSpace and should be called with a virtual address previously allocated by a call to HalpAssignReservedVirtualSpace the number of pages to release. Arguments: VirtualAddress of a previously allocated page in the HAL reserved space. Length (in pages) to be released. Return Value: None. --*/ { PHARDWARE_PTE PPte; // // Sanity Checks // if ( (LengthInPages > MAX_LENGTH) || (!LengthInPages) || ((ULONG)VirtualAddress < MIN_VA) || ((ULONG)VirtualAddress > MAX_VA) ) { KeBugCheck(HAL_INITIALIZATION_FAILED); return; } if ( !HalpReservedPtes ) { KeBugCheck(HAL_INITIALIZATION_FAILED); return; } PPte = HalpReservedPtes + PTE_INDEX(VirtualAddress); do { if ( !PPte->Valid ) { break; } PPte->Valid = FALSE; PPte++; } while ( --LengthInPages ); if ( LengthInPages ) { KeBugCheck(HAL_INITIALIZATION_FAILED); } KeFlushCurrentTb(); return; }
PVOID HalpAssignReservedVirtualSpace( ULONG BasePage, ULONG LengthInPages ) /*++ Routine Description: This function will attempt to allocate a contiguous range of virtual address to provide access to memory at the requested physical address. Arguments: Physical page number for which a Virtual Address assignment is needed. Length (in pages) of the region to be mapped. Return Value: Virtual Address in the range HAL_BASE thru HAL_TOP + fff, -or- NULL if the assignment couldn't be made. --*/ { ULONG Length; HARDWARE_PTE TempPte; HARDWARE_PTE ZeroPte; PHARDWARE_PTE PPte; PHARDWARE_PTE StartingPte; // // Sanity Checks // if ( (LengthInPages > MAX_LENGTH) || (!LengthInPages) || (BasePage & ~PAGE_MASK) ) { KeBugCheck(HAL_INITIALIZATION_FAILED); return NULL; } if ( !HalpReservedPtes ) { // // Not initialized yet,... fix it. // HalpLocateReservedPtes(); } PPte = HalpReservedPtes + PTE_INDEX(MIN_VA); Length = LengthInPages; while ( PPte <= (HalpReservedPtes + PTE_INDEX(MIN_VA)) || Length ) { if ( PPte->Valid ) { Length = LengthInPages; } else { Length--; } PPte++; } if ( Length ) { return NULL; } // // Found a range of pages. PPte is pointing to the entry // beyond the end of the range. // StartingPte = PPte - LengthInPages; PPte = StartingPte; *(PULONG)&ZeroPte = 0; TempPte = ZeroPte; TempPte.Write = TRUE; TempPte.CacheDisable = TRUE; TempPte.MemoryCoherence = TRUE; TempPte.GuardedStorage = TRUE; TempPte.Dirty = 0x00; // PP bits KM read/write, UM no access. TempPte.Valid = TRUE; while ( LengthInPages-- ) { // // The following is done in a Temp so the actual write // to the page table is done in a single write. // TempPte.PageFrameNumber = BasePage++; *PPte++ = TempPte; } return (PVOID)(BASE_VA | ((ULONG)(StartingPte - HalpReservedPtes) << PAGE_SHIFT)); }