kernel/x86_64: Handle LA57 paging in VMTranslationMap page table walks.
Without this, we will fail to free the last level of page tables. This bug has apparently been present since LA57 was originally introduced years ago, however it was likely not a problem before now because only the BIOS bootloader has support for it, while systems that support LA57 are more likely to be booted via EFI. While at it, fix the address mask for non-LA57 in DebugGetReverseMappingInfo. Should fix #19460.
This commit is contained in:
@@ -51,14 +51,34 @@ X86VMTranslationMap64Bit::~X86VMTranslationMap64Bit()
|
|||||||
if (fPagingStructures == NULL)
|
if (fPagingStructures == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fPageMapper != NULL) {
|
if (fPageMapper == NULL) {
|
||||||
|
fPagingStructures->RemoveReference();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
vm_page_reservation reservation = {};
|
vm_page_reservation reservation = {};
|
||||||
phys_addr_t address;
|
phys_addr_t address;
|
||||||
vm_page* page;
|
vm_page* page;
|
||||||
|
|
||||||
// Free all structures in the bottom half of the PMLTop (user memory).
|
// Free all structures in the bottom half of the PMLTop (user memory).
|
||||||
uint64* virtualPML4 = fPagingStructures->VirtualPMLTop();
|
uint64* virtualPML5 = NULL;
|
||||||
for (uint32 i = 0; i < 256; i++) {
|
if (fLA57)
|
||||||
|
virtualPML5 = fPagingStructures->VirtualPMLTop();
|
||||||
|
for (uint32 p = 0; p < 256; p++) {
|
||||||
|
uint64* virtualPML4 = NULL;
|
||||||
|
uint32 limitPML4 = 256;
|
||||||
|
if (fLA57) {
|
||||||
|
if ((virtualPML5[p] & X86_64_PML5E_PRESENT) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
virtualPML4 = (uint64*)fPageMapper->GetPageTableAt(
|
||||||
|
virtualPML5[p] & X86_64_PML5E_ADDRESS_MASK);
|
||||||
|
limitPML4 = 512;
|
||||||
|
} else {
|
||||||
|
virtualPML4 = fPagingStructures->VirtualPMLTop();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < limitPML4; i++) {
|
||||||
if ((virtualPML4[i] & X86_64_PML4E_PRESENT) == 0)
|
if ((virtualPML4[i] & X86_64_PML4E_PRESENT) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -107,10 +127,24 @@ X86VMTranslationMap64Bit::~X86VMTranslationMap64Bit()
|
|||||||
vm_page_free_etc(NULL, page, &reservation);
|
vm_page_free_etc(NULL, page, &reservation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fLA57) {
|
||||||
|
address = virtualPML5[p] & X86_64_PML5E_ADDRESS_MASK;
|
||||||
|
page = vm_lookup_page(address / B_PAGE_SIZE);
|
||||||
|
if (page == NULL) {
|
||||||
|
panic("PML4 %u on invalid page %#" B_PRIxPHYSADDR "\n", p,
|
||||||
|
address);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_PAGE_ACCESS_START(page);
|
||||||
|
vm_page_free_etc(NULL, page, &reservation);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vm_page_unreserve_pages(&reservation);
|
vm_page_unreserve_pages(&reservation);
|
||||||
|
|
||||||
fPageMapper->Delete();
|
fPageMapper->Delete();
|
||||||
}
|
|
||||||
|
|
||||||
fPagingStructures->RemoveReference();
|
fPagingStructures->RemoveReference();
|
||||||
}
|
}
|
||||||
@@ -731,16 +765,29 @@ bool
|
|||||||
X86VMTranslationMap64Bit::DebugGetReverseMappingInfo(phys_addr_t physicalAddress,
|
X86VMTranslationMap64Bit::DebugGetReverseMappingInfo(phys_addr_t physicalAddress,
|
||||||
ReverseMappingInfoCallback& callback)
|
ReverseMappingInfoCallback& callback)
|
||||||
{
|
{
|
||||||
|
uint64* virtualPML5 = NULL;
|
||||||
|
if (fLA57)
|
||||||
|
virtualPML5 = fPagingStructures->VirtualPMLTop();
|
||||||
|
for (uint32 p = 0; p < (fIsKernelMap ? 512 : 256); p++) {
|
||||||
|
uint64* virtualPML4 = NULL;
|
||||||
|
uint32 limitPML4 = (fIsKernelMap ? 512 : 256);
|
||||||
if (fLA57) {
|
if (fLA57) {
|
||||||
kprintf("X86VMTranslationMap64Bit::DebugGetReverseMappingInfo not implemented for LA57\n");
|
if ((virtualPML5[p] & X86_64_PML5E_PRESENT) == 0)
|
||||||
return false;
|
continue;
|
||||||
|
|
||||||
|
virtualPML4 = (uint64*)fPageMapper->GetPageTableAt(
|
||||||
|
virtualPML5[p] & X86_64_PML5E_ADDRESS_MASK);
|
||||||
|
limitPML4 = 512;
|
||||||
|
} else {
|
||||||
|
virtualPML4 = fPagingStructures->VirtualPMLTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint64* virtualPML4 = fPagingStructures->VirtualPMLTop();
|
for (uint32 i = 0; i < limitPML4; i++) {
|
||||||
for (uint32 i = 0; i < (fIsKernelMap ? 512 : 256); i++) {
|
|
||||||
if ((virtualPML4[i] & X86_64_PML4E_PRESENT) == 0)
|
if ((virtualPML4[i] & X86_64_PML4E_PRESENT) == 0)
|
||||||
continue;
|
continue;
|
||||||
const uint64 addressMask = (i >= 256) ? 0xffffff0000000000LL : 0;
|
uint64 addressMask = 0;
|
||||||
|
if (i >= 256)
|
||||||
|
addressMask = fLA57 ? 0xff00000000000000LL : 0xfffff00000000000LL;
|
||||||
|
|
||||||
const uint64* virtualPDPT = (uint64*)fPageMapper->GetPageTableAt(
|
const uint64* virtualPDPT = (uint64*)fPageMapper->GetPageTableAt(
|
||||||
virtualPML4[i] & X86_64_PML4E_ADDRESS_MASK);
|
virtualPML4[i] & X86_64_PML4E_ADDRESS_MASK);
|
||||||
@@ -759,7 +806,8 @@ X86VMTranslationMap64Bit::DebugGetReverseMappingInfo(phys_addr_t physicalAddress
|
|||||||
if (physicalAddress >= largeAddress
|
if (physicalAddress >= largeAddress
|
||||||
&& physicalAddress < (largeAddress + k64BitPageTableRange)) {
|
&& physicalAddress < (largeAddress + k64BitPageTableRange)) {
|
||||||
off_t offset = physicalAddress - largeAddress;
|
off_t offset = physicalAddress - largeAddress;
|
||||||
addr_t virtualAddress = i * k64BitPDPTRange
|
addr_t virtualAddress = p * k64BitPML4TRange
|
||||||
|
+ i * k64BitPDPTRange
|
||||||
+ j * k64BitPageDirectoryRange
|
+ j * k64BitPageDirectoryRange
|
||||||
+ k * k64BitPageTableRange
|
+ k * k64BitPageTableRange
|
||||||
+ offset;
|
+ offset;
|
||||||
@@ -777,7 +825,8 @@ X86VMTranslationMap64Bit::DebugGetReverseMappingInfo(phys_addr_t physicalAddress
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((virtualPageTable[l] & X86_64_PTE_ADDRESS_MASK) == physicalAddress) {
|
if ((virtualPageTable[l] & X86_64_PTE_ADDRESS_MASK) == physicalAddress) {
|
||||||
addr_t virtualAddress = i * k64BitPDPTRange
|
addr_t virtualAddress = p * k64BitPML4TRange
|
||||||
|
+ i * k64BitPDPTRange
|
||||||
+ j * k64BitPageDirectoryRange
|
+ j * k64BitPageDirectoryRange
|
||||||
+ k * k64BitPageTableRange
|
+ k * k64BitPageTableRange
|
||||||
+ l * B_PAGE_SIZE;
|
+ l * B_PAGE_SIZE;
|
||||||
@@ -790,6 +839,10 @@ X86VMTranslationMap64Bit::DebugGetReverseMappingInfo(phys_addr_t physicalAddress
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!fLA57)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user