fix: fix hot loader page reuse for overlapping init segments
This commit is contained in:
@@ -94,6 +94,28 @@ static UInt64* sVMVirtualMemoryMapPageInternal(UInt64* pml4, UInt64 phys, UInt64
|
||||
return (UInt64*)virt;
|
||||
}
|
||||
|
||||
static void* sVMVirtualMemoryGetMappedPageInternal(UInt64* pml4, UInt64 virt) {
|
||||
UInt64 pt_idx = VMM_PT_INDEX(virt);
|
||||
UInt64 pd_idx = VMM_PD_INDEX(virt);
|
||||
UInt64 pdpt_idx = VMM_PDPT_INDEX(virt);
|
||||
UInt64 pml4_idx = VMM_PML4_INDEX(virt);
|
||||
|
||||
UInt64* pml4_virt = pml4;
|
||||
if (isInitialized) pml4_virt = (UInt64*)PHYS_TO_HHDM((UInt64)pml4);
|
||||
|
||||
if (!(pml4_virt[pml4_idx] & PTE_PRESENT)) return nullptr;
|
||||
UInt64* pdpt_virt = sVMGetVirtualTable(PTE_GET_ADDR(pml4_virt[pml4_idx]));
|
||||
|
||||
if (!(pdpt_virt[pdpt_idx] & PTE_PRESENT)) return nullptr;
|
||||
UInt64* pd_virt = sVMGetVirtualTable(PTE_GET_ADDR(pdpt_virt[pdpt_idx]));
|
||||
|
||||
if (!(pd_virt[pd_idx] & PTE_PRESENT)) return nullptr;
|
||||
UInt64* pt_virt = sVMGetVirtualTable(PTE_GET_ADDR(pd_virt[pd_idx]));
|
||||
|
||||
if (!(pt_virt[pt_idx] & PTE_PRESENT)) return nullptr;
|
||||
return (void*)PHYS_TO_HHDM(PTE_GET_ADDR(pt_virt[pt_idx]));
|
||||
}
|
||||
|
||||
static void sVMVirtualMemoryUnmapPageInternal(UInt64* pml4, UInt64 virt) {
|
||||
UInt64 pt_idx = VMM_PT_INDEX(virt);
|
||||
UInt64 pd_idx = VMM_PD_INDEX(virt);
|
||||
@@ -128,6 +150,35 @@ UInt64* VMVirtualMemoryMapPage(UInt64* pml4, UInt64 phys, UInt64 virt, UInt64 fl
|
||||
return result;
|
||||
}
|
||||
|
||||
void* VMVirtualMemoryGetOrAllocatePage(UInt64* pml4, UInt64 virt, UInt64 flags) {
|
||||
OSSpinlockState state;
|
||||
OSSpinlockLockIRQ(&sVMVMMlock, &state);
|
||||
|
||||
void* mappedPage = sVMVirtualMemoryGetMappedPageInternal(pml4, virt);
|
||||
if (mappedPage) {
|
||||
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
|
||||
return mappedPage;
|
||||
}
|
||||
|
||||
void* physicalPage = VMPhysicalMemoryAllocatePage();
|
||||
if (!physicalPage) {
|
||||
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UInt64* result = sVMVirtualMemoryMapPageInternal(pml4, (UInt64)physicalPage, virt, flags);
|
||||
if (!result) {
|
||||
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* kernelVirtualAddress = (void*)PHYS_TO_HHDM((UInt64)physicalPage);
|
||||
MemorySet(kernelVirtualAddress, 0, kVMPageSize);
|
||||
|
||||
OSSpinlockUnlockIRQ(&sVMVMMlock, &state);
|
||||
return kernelVirtualAddress;
|
||||
}
|
||||
|
||||
void VMVirtualMemoryUnmapPage(UInt64* pml4, UInt64 virt) {
|
||||
OSSpinlockState state;
|
||||
OSSpinlockLockIRQ(&sVMVMMlock, &state);
|
||||
|
||||
Reference in New Issue
Block a user