fix: various kernel bug fixes
This commit is contained in:
@@ -363,6 +363,53 @@ namespace Memory::VMM {
|
||||
}
|
||||
}
|
||||
|
||||
bool Paging::IsUserRangeAccessible(std::uint64_t pml4Phys, std::uint64_t virtualAddress,
|
||||
std::uint64_t size, bool requireWrite) {
|
||||
static constexpr uint64_t USER_SPACE_END = 0x0000800000000000ULL;
|
||||
|
||||
if (size == 0) return true;
|
||||
if (virtualAddress >= USER_SPACE_END) return false;
|
||||
if (virtualAddress + size < virtualAddress) return false;
|
||||
if (virtualAddress + size > USER_SPACE_END) return false;
|
||||
|
||||
auto pageAccessible = [&](uint64_t pageVa) -> bool {
|
||||
VirtualAddress va(pageVa);
|
||||
PageTable* pml4 = (PageTable*)pml4Phys;
|
||||
|
||||
PageTableEntry* pml4e = (PageTableEntry*)Memory::HHDM(&pml4->entries[va.GetL4Index()]);
|
||||
if (!pml4e->Present || !pml4e->Supervisor) return false;
|
||||
if (requireWrite && !pml4e->Writable) return false;
|
||||
|
||||
PageTable* pml3 = (PageTable*)(pml4e->Address << 12);
|
||||
PageTableEntry* pml3e = (PageTableEntry*)Memory::HHDM(&pml3->entries[va.GetL3Index()]);
|
||||
if (!pml3e->Present || !pml3e->Supervisor) return false;
|
||||
if (requireWrite && !pml3e->Writable) return false;
|
||||
if (pml3e->LargerPages) return true;
|
||||
|
||||
PageTable* pml2 = (PageTable*)(pml3e->Address << 12);
|
||||
PageTableEntry* pml2e = (PageTableEntry*)Memory::HHDM(&pml2->entries[va.GetL2Index()]);
|
||||
if (!pml2e->Present || !pml2e->Supervisor) return false;
|
||||
if (requireWrite && !pml2e->Writable) return false;
|
||||
if (pml2e->LargerPages) return true;
|
||||
|
||||
PageTable* pml1 = (PageTable*)(pml2e->Address << 12);
|
||||
PageTableEntry* pte = (PageTableEntry*)Memory::HHDM(&pml1->entries[va.GetPageIndex()]);
|
||||
if (!pte->Present || !pte->Supervisor) return false;
|
||||
if (requireWrite && !pte->Writable) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
uint64_t page = virtualAddress & ~0xFFFULL;
|
||||
uint64_t lastPage = (virtualAddress + size - 1) & ~0xFFFULL;
|
||||
for (;;) {
|
||||
if (!pageAccessible(page)) return false;
|
||||
if (page == lastPage) break;
|
||||
page += 0x1000;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Mask to extract only the 40-bit physical address from a PTE Address field
|
||||
// (bits 12-51 of the PTE). The PageTableEntry::Address field is 52 bits wide
|
||||
// and includes NX, PK, and software-available bits that must be stripped.
|
||||
|
||||
@@ -117,6 +117,12 @@ public:
|
||||
// Skips MMIO/WC pages (WriteThrough or CacheDisabled set in PTE).
|
||||
static void FreeUserHalf(std::uint64_t pml4Phys);
|
||||
|
||||
// Validate that every page in the given user range is mapped with
|
||||
// user permissions. If requireWrite is true, all pages must also be
|
||||
// writable.
|
||||
static bool IsUserRangeAccessible(std::uint64_t pml4Phys, std::uint64_t virtualAddress,
|
||||
std::uint64_t size, bool requireWrite = false);
|
||||
|
||||
// Identity-map EFI runtime service regions so firmware code can
|
||||
// reference its own data at physical addresses.
|
||||
void MapEfiRuntime(limine_efi_memmap_response* efiMemmap);
|
||||
|
||||
Reference in New Issue
Block a user