From 58353b3809402871992f09a75122c5f590487249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Fri, 2 Oct 2020 11:15:08 +0200 Subject: [PATCH] kernel/x86_64: LA57 aka 5-level paging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this enables the kernel to correctly take over when the bootloader prepares the paging in 4-level or 5-level. Change-Id: I0444486d8e17aade574e2afe255a3c2cfc49f21f Reviewed-on: https://review.haiku-os.org/c/haiku/+/3551 Reviewed-by: Adrien Destugues Reviewed-by: Axel Dörfler --- .../arch/x86/arch_vm_translation_map.cpp | 6 +- .../x86/paging/64bit/X86PagingMethod64Bit.cpp | 80 +++++++++++++++---- .../x86/paging/64bit/X86PagingMethod64Bit.h | 16 ++-- .../paging/64bit/X86PagingStructures64Bit.cpp | 13 +-- .../paging/64bit/X86PagingStructures64Bit.h | 10 +-- .../paging/64bit/X86VMTranslationMap64Bit.cpp | 73 +++++++++-------- .../paging/64bit/X86VMTranslationMap64Bit.h | 3 +- .../kernel/arch/x86/paging/64bit/paging.h | 14 +++- 8 files changed, 144 insertions(+), 71 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_vm_translation_map.cpp b/src/system/kernel/arch/x86/arch_vm_translation_map.cpp index 728dbd811b..3fbf66a397 100644 --- a/src/system/kernel/arch/x86/arch_vm_translation_map.cpp +++ b/src/system/kernel/arch/x86/arch_vm_translation_map.cpp @@ -84,7 +84,11 @@ arch_vm_translation_map_init(kernel_args *args, #endif #ifdef __x86_64__ - gX86PagingMethod = new(&sPagingMethodBuffer) X86PagingMethod64Bit; + bool la57Available = x86_check_feature(IA32_FEATURE_LA57, FEATURE_7_ECX); + bool enabled = la57Available && (x86_read_cr4() & IA32_CR4_LA57) != 0; + if (enabled) + dprintf("using LA57 paging\n"); + gX86PagingMethod = new(&sPagingMethodBuffer) X86PagingMethod64Bit(enabled); #elif B_HAIKU_PHYSICAL_BITS == 64 bool paeAvailable = x86_check_feature(IA32_FEATURE_PAE, FEATURE_COMMON); bool paeNeeded = x86_check_feature(IA32_FEATURE_AMD_EXT_NX, diff --git a/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp index cf43091abd..66fc4f84be 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp +++ b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp @@ -34,16 +34,20 @@ #endif +bool X86PagingMethod64Bit::la57 = false; + + // #pragma mark - X86PagingMethod64Bit -X86PagingMethod64Bit::X86PagingMethod64Bit() +X86PagingMethod64Bit::X86PagingMethod64Bit(bool la57) : - fKernelPhysicalPML4(0), - fKernelVirtualPML4(NULL), + fKernelPhysicalPMLTop(0), + fKernelVirtualPMLTop(NULL), fPhysicalPageMapper(NULL), fKernelPhysicalPageMapper(NULL) { + X86PagingMethod64Bit::la57 = la57; } @@ -56,8 +60,8 @@ status_t X86PagingMethod64Bit::Init(kernel_args* args, VMPhysicalPageMapper** _physicalPageMapper) { - fKernelPhysicalPML4 = args->arch_args.phys_pgdir; - fKernelVirtualPML4 = (uint64*)(addr_t)args->arch_args.vir_pgdir; + fKernelPhysicalPMLTop = args->arch_args.phys_pgdir; + fKernelVirtualPMLTop = (uint64*)(addr_t)args->arch_args.vir_pgdir; // if available enable NX-bit (No eXecute) if (x86_check_feature(IA32_FEATURE_AMD_EXT_NX, FEATURE_EXT_AMD)) @@ -65,7 +69,7 @@ X86PagingMethod64Bit::Init(kernel_args* args, // Ensure that the user half of the address space is clear. This removes // the temporary identity mapping made by the boot loader. - memset(fKernelVirtualPML4, 0, sizeof(uint64) * 256); + memset(fKernelVirtualPMLTop, 0, sizeof(uint64) * 256); arch_cpu_global_TLB_invalidate(); // Create the physical page mapper. @@ -88,8 +92,8 @@ X86PagingMethod64Bit::InitPostArea(kernel_args* args) if (area < B_OK) return area; - // Create an area to represent the kernel PML4. - area = create_area("kernel pml4", (void**)&fKernelVirtualPML4, + // Create an area to represent the kernel PMLTop. + area = create_area("kernel pmltop", (void**)&fKernelVirtualPMLTop, B_EXACT_ADDRESS, B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); if (area < B_OK) @@ -102,7 +106,7 @@ X86PagingMethod64Bit::InitPostArea(kernel_args* args) status_t X86PagingMethod64Bit::CreateTranslationMap(bool kernel, VMTranslationMap** _map) { - X86VMTranslationMap64Bit* map = new(std::nothrow) X86VMTranslationMap64Bit; + X86VMTranslationMap64Bit* map = new(std::nothrow) X86VMTranslationMap64Bit(la57); if (map == NULL) return B_NO_MEMORY; @@ -125,8 +129,17 @@ X86PagingMethod64Bit::MapEarly(kernel_args* args, addr_t virtualAddress, TRACE("X86PagingMethod64Bit::MapEarly(%#" B_PRIxADDR ", %#" B_PRIxPHYSADDR ", %#" B_PRIx8 ")\n", virtualAddress, physicalAddress, attributes); + uint64* virtualPML4 = fKernelVirtualPMLTop; + if (la57) { + // Get the PML4. We should be mapping on an existing PML4 at this stage. + uint64* pml5e = &fKernelVirtualPMLTop[VADDR_TO_PML5E(virtualAddress)]; + ASSERT((*pml5e & X86_64_PML5E_PRESENT) != 0); + virtualPML4 = (uint64*)fKernelPhysicalPageMapper->GetPageTableAt( + *pml5e & X86_64_PML5E_ADDRESS_MASK); + } + // Get the PDPT. We should be mapping on an existing PDPT at this stage. - uint64* pml4e = &fKernelVirtualPML4[VADDR_TO_PML4E(virtualAddress)]; + uint64* pml4e = &virtualPML4[VADDR_TO_PML4E(virtualAddress)]; ASSERT((*pml4e & X86_64_PML4E_PRESENT) != 0); uint64* virtualPDPT = (uint64*)fKernelPhysicalPageMapper->GetPageTableAt( *pml4e & X86_64_PML4E_ADDRESS_MASK); @@ -206,11 +219,44 @@ X86PagingMethod64Bit::IsKernelPageAccessible(addr_t virtualAddress, for a virtual address, allocating new tables if required. */ /*static*/ uint64* -X86PagingMethod64Bit::PageDirectoryForAddress(uint64* virtualPML4, +X86PagingMethod64Bit::PageDirectoryForAddress(uint64* virtualPMLTop, addr_t virtualAddress, bool isKernel, bool allocateTables, vm_page_reservation* reservation, TranslationMapPhysicalPageMapper* pageMapper, int32& mapCount) { + uint64* virtualPML4 = virtualPMLTop; + if (la57) { + // Get the PDPT. + uint64* pml5e = &virtualPMLTop[VADDR_TO_PML5E(virtualAddress)]; + if ((*pml5e & X86_64_PML5E_PRESENT) == 0) { + if (!allocateTables) + return NULL; + + // Allocate a new PDPT. + vm_page* page = vm_page_allocate_page(reservation, + PAGE_STATE_WIRED | VM_PAGE_ALLOC_CLEAR); + + DEBUG_PAGE_ACCESS_END(page); + + phys_addr_t physicalPDPT + = (phys_addr_t)page->physical_page_number * B_PAGE_SIZE; + + TRACE("X86PagingMethod64Bit::PageTableForAddress(): creating PML4T" + " for va %#" B_PRIxADDR " at %#" B_PRIxPHYSADDR "\n", + virtualAddress, physicalPDPT); + + SetTableEntry(pml5e, (physicalPDPT & X86_64_PML5E_ADDRESS_MASK) + | X86_64_PML5E_PRESENT + | X86_64_PML5E_WRITABLE + | X86_64_PML5E_USER); + + mapCount++; + } + + virtualPML4 = (uint64*)pageMapper->GetPageTableAt( + *pml5e & X86_64_PML5E_ADDRESS_MASK); + } + // Get the PDPT. uint64* pml4e = &virtualPML4[VADDR_TO_PML4E(virtualAddress)]; if ((*pml4e & X86_64_PML4E_PRESENT) == 0) { @@ -274,12 +320,12 @@ X86PagingMethod64Bit::PageDirectoryForAddress(uint64* virtualPML4, /*static*/ uint64* -X86PagingMethod64Bit::PageDirectoryEntryForAddress(uint64* virtualPML4, +X86PagingMethod64Bit::PageDirectoryEntryForAddress(uint64* virtualPMLTop, addr_t virtualAddress, bool isKernel, bool allocateTables, vm_page_reservation* reservation, TranslationMapPhysicalPageMapper* pageMapper, int32& mapCount) { - uint64* virtualPageDirectory = PageDirectoryForAddress(virtualPML4, + uint64* virtualPageDirectory = PageDirectoryForAddress(virtualPMLTop, virtualAddress, isKernel, allocateTables, reservation, pageMapper, mapCount); if (virtualPageDirectory == NULL) @@ -293,7 +339,7 @@ X86PagingMethod64Bit::PageDirectoryEntryForAddress(uint64* virtualPML4, virtual address, allocating new tables if required. */ /*static*/ uint64* -X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPML4, +X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPMLTop, addr_t virtualAddress, bool isKernel, bool allocateTables, vm_page_reservation* reservation, TranslationMapPhysicalPageMapper* pageMapper, int32& mapCount) @@ -301,7 +347,7 @@ X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPML4, TRACE("X86PagingMethod64Bit::PageTableForAddress(%#" B_PRIxADDR ", " "%d)\n", virtualAddress, allocateTables); - uint64* pde = PageDirectoryEntryForAddress(virtualPML4, virtualAddress, + uint64* pde = PageDirectoryEntryForAddress(virtualPMLTop, virtualAddress, isKernel, allocateTables, reservation, pageMapper, mapCount); if (pde == NULL) return NULL; @@ -341,12 +387,12 @@ X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPML4, /*static*/ uint64* -X86PagingMethod64Bit::PageTableEntryForAddress(uint64* virtualPML4, +X86PagingMethod64Bit::PageTableEntryForAddress(uint64* virtualPMLTop, addr_t virtualAddress, bool isKernel, bool allocateTables, vm_page_reservation* reservation, TranslationMapPhysicalPageMapper* pageMapper, int32& mapCount) { - uint64* virtualPageTable = PageTableForAddress(virtualPML4, virtualAddress, + uint64* virtualPageTable = PageTableForAddress(virtualPMLTop, virtualAddress, isKernel, allocateTables, reservation, pageMapper, mapCount); if (virtualPageTable == NULL) return NULL; diff --git a/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.h b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.h index 694b5befd9..e1e4a9c6d2 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.h +++ b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.h @@ -27,7 +27,7 @@ struct vm_page_reservation; class X86PagingMethod64Bit final : public X86PagingMethod { public: - X86PagingMethod64Bit(); + X86PagingMethod64Bit(bool la57); virtual ~X86PagingMethod64Bit(); virtual status_t Init(kernel_args* args, @@ -51,10 +51,10 @@ public: inline TranslationMapPhysicalPageMapper* KernelPhysicalPageMapper() const { return fKernelPhysicalPageMapper; } - inline uint64* KernelVirtualPML4() const - { return fKernelVirtualPML4; } - inline phys_addr_t KernelPhysicalPML4() const - { return fKernelPhysicalPML4; } + inline uint64* KernelVirtualPMLTop() const + { return fKernelVirtualPMLTop; } + inline phys_addr_t KernelPhysicalPMLTop() const + { return fKernelPhysicalPMLTop; } static X86PagingMethod64Bit* Method(); @@ -103,11 +103,13 @@ public: private: static void _EnableExecutionDisable(void* dummy, int cpu); - phys_addr_t fKernelPhysicalPML4; - uint64* fKernelVirtualPML4; + phys_addr_t fKernelPhysicalPMLTop; + uint64* fKernelVirtualPMLTop; X86PhysicalPageMapper* fPhysicalPageMapper; TranslationMapPhysicalPageMapper* fKernelPhysicalPageMapper; + + static bool la57; }; diff --git a/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.cpp b/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.cpp index aeecb239e7..fd66356a5d 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.cpp +++ b/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.cpp @@ -18,23 +18,24 @@ X86PagingStructures64Bit::X86PagingStructures64Bit() : - fVirtualPML4(NULL) + fVirtualPMLTop(NULL) { } X86PagingStructures64Bit::~X86PagingStructures64Bit() { - // Free the PML4. - free(fVirtualPML4); + // Free the PMLTop. + free(fVirtualPMLTop); } void -X86PagingStructures64Bit::Init(uint64* virtualPML4, phys_addr_t physicalPML4) +X86PagingStructures64Bit::Init(uint64* virtualPMLTop, + phys_addr_t physicalPMLTop) { - fVirtualPML4 = virtualPML4; - pgdir_phys = physicalPML4; + fVirtualPMLTop = virtualPMLTop; + pgdir_phys = physicalPMLTop; } diff --git a/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.h b/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.h index edb3e44e8a..b0555edbd8 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.h +++ b/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.h @@ -14,16 +14,16 @@ struct X86PagingStructures64Bit final : X86PagingStructures { X86PagingStructures64Bit(); virtual ~X86PagingStructures64Bit(); - void Init(uint64* virtualPML4, - phys_addr_t physicalPML4); + void Init(uint64* virtualPMLTop, + phys_addr_t physicalPMLTop); virtual void Delete(); - uint64* VirtualPML4() - { return fVirtualPML4; } + uint64* VirtualPMLTop() + { return fVirtualPMLTop; } private: - uint64* fVirtualPML4; + uint64* fVirtualPMLTop; }; diff --git a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp index 64eb688172..12d320befa 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp +++ b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp @@ -35,9 +35,10 @@ // #pragma mark - X86VMTranslationMap64Bit -X86VMTranslationMap64Bit::X86VMTranslationMap64Bit() +X86VMTranslationMap64Bit::X86VMTranslationMap64Bit(bool la57) : - fPagingStructures(NULL) + fPagingStructures(NULL), + fLA57(la57) { } @@ -53,8 +54,8 @@ X86VMTranslationMap64Bit::~X86VMTranslationMap64Bit() phys_addr_t address; vm_page* page; - // Free all structures in the bottom half of the PML4 (user memory). - uint64* virtualPML4 = fPagingStructures->VirtualPML4(); + // Free all structures in the bottom half of the PMLTop (user memory). + uint64* virtualPML4 = fPagingStructures->VirtualPMLTop(); for (uint32 i = 0; i < 256; i++) { if ((virtualPML4[i] & X86_64_PML4E_PRESENT) == 0) continue; @@ -128,9 +129,9 @@ X86VMTranslationMap64Bit::Init(bool kernel) // Get the page mapper. fPageMapper = method->KernelPhysicalPageMapper(); - // Kernel PML4 is already mapped. - fPagingStructures->Init(method->KernelVirtualPML4(), - method->KernelPhysicalPML4()); + // Kernel PMLTop is already mapped. + fPagingStructures->Init(method->KernelVirtualPMLTop(), + method->KernelPhysicalPMLTop()); } else { // Allocate a physical page mapper. status_t error = method->PhysicalPageMapper() @@ -138,28 +139,28 @@ X86VMTranslationMap64Bit::Init(bool kernel) if (error != B_OK) return error; - // Assuming that only the top 2 PML4 entries are occupied for the + // Assuming that only the top 2 PMLTop entries are occupied for the // kernel. STATIC_ASSERT(KERNEL_PMAP_BASE == 0xffffff0000000000); STATIC_ASSERT(KERNEL_BASE == 0xffffff0000000000); - // Allocate and clear the PML4. - uint64* virtualPML4 = (uint64*)memalign(B_PAGE_SIZE, B_PAGE_SIZE); - if (virtualPML4 == NULL) + // Allocate and clear the PMLTop. + uint64* virtualPMLTop = (uint64*)memalign(B_PAGE_SIZE, B_PAGE_SIZE); + if (virtualPMLTop == NULL) return B_NO_MEMORY; - memset(virtualPML4, 0, B_PAGE_SIZE); + memset(virtualPMLTop, 0, B_PAGE_SIZE); - // Copy the top 2 PML4 entries. - virtualPML4[510] = method->KernelVirtualPML4()[510]; - virtualPML4[511] = method->KernelVirtualPML4()[511]; + // Copy the top 2 PMLTop entries. + virtualPMLTop[510] = method->KernelVirtualPMLTop()[510]; + virtualPMLTop[511] = method->KernelVirtualPMLTop()[511]; - // Look up the PML4 physical address. - phys_addr_t physicalPML4; - vm_get_page_mapping(VMAddressSpace::KernelID(), (addr_t)virtualPML4, - &physicalPML4); + // Look up the PMLTop physical address. + phys_addr_t physicalPMLTop; + vm_get_page_mapping(VMAddressSpace::KernelID(), (addr_t)virtualPMLTop, + &physicalPMLTop); // Initialize the paging structures. - fPagingStructures->Init(virtualPML4, physicalPML4); + fPagingStructures->Init(virtualPMLTop, physicalPMLTop); } return B_OK; @@ -171,12 +172,17 @@ X86VMTranslationMap64Bit::MaxPagesNeededToMap(addr_t start, addr_t end) const { // If start == 0, the actual base address is not yet known to the caller and // we shall assume the worst case, which is where the start address is the - // last page covered by a PDPT. + // last page covered by a PDPT or PML4. if (start == 0) { - start = k64BitPDPTRange - B_PAGE_SIZE; + start = (fLA57 ? k64BitPML4TRange : k64BitPDPTRange) - B_PAGE_SIZE; end += start; } + size_t requiredPML4s = 0; + if (fLA57) { + requiredPML4s = end / k64BitPML4TRange + 1 + - start / k64BitPML4TRange; + } size_t requiredPDPTs = end / k64BitPDPTRange + 1 - start / k64BitPDPTRange; size_t requiredPageDirs = end / k64BitPageDirectoryRange + 1 @@ -184,7 +190,8 @@ X86VMTranslationMap64Bit::MaxPagesNeededToMap(addr_t start, addr_t end) const size_t requiredPageTables = end / k64BitPageTableRange + 1 - start / k64BitPageTableRange; - return requiredPDPTs + requiredPageDirs + requiredPageTables; + return requiredPML4s + requiredPDPTs + requiredPageDirs + + requiredPageTables; } @@ -200,7 +207,7 @@ X86VMTranslationMap64Bit::Map(addr_t virtualAddress, phys_addr_t physicalAddress // Look up the page table for the virtual address, allocating new tables // if required. Shouldn't fail. uint64* entry = X86PagingMethod64Bit::PageTableEntryForAddress( - fPagingStructures->VirtualPML4(), virtualAddress, fIsKernelMap, + fPagingStructures->VirtualPMLTop(), virtualAddress, fIsKernelMap, true, reservation, fPageMapper, fMapCount); ASSERT(entry != NULL); @@ -236,7 +243,7 @@ X86VMTranslationMap64Bit::Unmap(addr_t start, addr_t end) do { uint64* pageTable = X86PagingMethod64Bit::PageTableForAddress( - fPagingStructures->VirtualPML4(), start, fIsKernelMap, false, + fPagingStructures->VirtualPMLTop(), start, fIsKernelMap, false, NULL, fPageMapper, fMapCount); if (pageTable == NULL) { // Move on to the next page table. @@ -286,7 +293,7 @@ X86VMTranslationMap64Bit::DebugMarkRangePresent(addr_t start, addr_t end, do { uint64* pageTable = X86PagingMethod64Bit::PageTableForAddress( - fPagingStructures->VirtualPML4(), start, fIsKernelMap, false, + fPagingStructures->VirtualPMLTop(), start, fIsKernelMap, false, NULL, fPageMapper, fMapCount); if (pageTable == NULL) { // Move on to the next page table. @@ -336,7 +343,7 @@ X86VMTranslationMap64Bit::UnmapPage(VMArea* area, addr_t address, // Look up the page table for the virtual address. uint64* entry = X86PagingMethod64Bit::PageTableEntryForAddress( - fPagingStructures->VirtualPML4(), address, fIsKernelMap, + fPagingStructures->VirtualPMLTop(), address, fIsKernelMap, false, NULL, fPageMapper, fMapCount); if (entry == NULL) return B_ENTRY_NOT_FOUND; @@ -403,7 +410,7 @@ X86VMTranslationMap64Bit::UnmapPages(VMArea* area, addr_t base, size_t size, do { uint64* pageTable = X86PagingMethod64Bit::PageTableForAddress( - fPagingStructures->VirtualPML4(), start, fIsKernelMap, false, + fPagingStructures->VirtualPMLTop(), start, fIsKernelMap, false, NULL, fPageMapper, fMapCount); if (pageTable == NULL) { // Move on to the next page table. @@ -536,7 +543,7 @@ X86VMTranslationMap64Bit::UnmapArea(VMArea* area, bool deletingAddressSpace, + ((page->cache_offset * B_PAGE_SIZE) - area->cache_offset); uint64* entry = X86PagingMethod64Bit::PageTableEntryForAddress( - fPagingStructures->VirtualPML4(), address, fIsKernelMap, + fPagingStructures->VirtualPMLTop(), address, fIsKernelMap, false, NULL, fPageMapper, fMapCount); if (entry == NULL) { panic("page %p has mapping for area %p (%#" B_PRIxADDR "), but " @@ -607,7 +614,7 @@ X86VMTranslationMap64Bit::Query(addr_t virtualAddress, // large pages here. Look up the page directory entry for the virtual // address. uint64* pde = X86PagingMethod64Bit::PageDirectoryEntryForAddress( - fPagingStructures->VirtualPML4(), virtualAddress, fIsKernelMap, + fPagingStructures->VirtualPMLTop(), virtualAddress, fIsKernelMap, false, NULL, fPageMapper, fMapCount); if (pde == NULL || (*pde & X86_64_PDE_PRESENT) == 0) return B_OK; @@ -684,7 +691,7 @@ X86VMTranslationMap64Bit::Protect(addr_t start, addr_t end, uint32 attributes, do { uint64* pageTable = X86PagingMethod64Bit::PageTableForAddress( - fPagingStructures->VirtualPML4(), start, fIsKernelMap, false, + fPagingStructures->VirtualPMLTop(), start, fIsKernelMap, false, NULL, fPageMapper, fMapCount); if (pageTable == NULL) { // Move on to the next page table. @@ -741,7 +748,7 @@ X86VMTranslationMap64Bit::ClearFlags(addr_t address, uint32 flags) ThreadCPUPinner pinner(thread_get_current_thread()); uint64* entry = X86PagingMethod64Bit::PageTableEntryForAddress( - fPagingStructures->VirtualPML4(), address, fIsKernelMap, + fPagingStructures->VirtualPMLTop(), address, fIsKernelMap, false, NULL, fPageMapper, fMapCount); if (entry == NULL) return B_OK; @@ -772,7 +779,7 @@ X86VMTranslationMap64Bit::ClearAccessedAndModified(VMArea* area, addr_t address, ThreadCPUPinner pinner(thread_get_current_thread()); uint64* entry = X86PagingMethod64Bit::PageTableEntryForAddress( - fPagingStructures->VirtualPML4(), address, fIsKernelMap, + fPagingStructures->VirtualPMLTop(), address, fIsKernelMap, false, NULL, fPageMapper, fMapCount); if (entry == NULL) return false; diff --git a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.h b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.h index aa62a29155..b0b8405638 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.h +++ b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.h @@ -14,7 +14,7 @@ struct X86PagingStructures64Bit; struct X86VMTranslationMap64Bit final : X86VMTranslationMap { - X86VMTranslationMap64Bit(); + X86VMTranslationMap64Bit(bool la57); virtual ~X86VMTranslationMap64Bit(); status_t Init(bool kernel); @@ -63,6 +63,7 @@ struct X86VMTranslationMap64Bit final : X86VMTranslationMap { private: X86PagingStructures64Bit* fPagingStructures; + bool fLA57; }; diff --git a/src/system/kernel/arch/x86/paging/64bit/paging.h b/src/system/kernel/arch/x86/paging/64bit/paging.h index a99afaa44c..a20b517fc0 100644 --- a/src/system/kernel/arch/x86/paging/64bit/paging.h +++ b/src/system/kernel/arch/x86/paging/64bit/paging.h @@ -9,6 +9,16 @@ #include +// PML5 entry bits. +#define X86_64_PML5E_PRESENT (1LL << 0) +#define X86_64_PML5E_WRITABLE (1LL << 1) +#define X86_64_PML5E_USER (1LL << 2) +#define X86_64_PML5E_WRITE_THROUGH (1LL << 3) +#define X86_64_PML5E_CACHING_DISABLED (1LL << 4) +#define X86_64_PML5E_ACCESSED (1LL << 5) +#define X86_64_PML5E_NOT_EXECUTABLE (1LL << 63) +#define X86_64_PML5E_ADDRESS_MASK 0x000ffffffffff000L + // PML4 entry bits. #define X86_64_PML4E_PRESENT (1LL << 0) #define X86_64_PML4E_WRITABLE (1LL << 1) @@ -69,11 +79,13 @@ static const size_t k64BitPageTableRange = 0x200000L; static const size_t k64BitPageDirectoryRange = 0x40000000L; static const size_t k64BitPDPTRange = 0x8000000000L; +static const size_t k64BitPML4TRange = 0x1000000000000L; static const size_t k64BitTableEntryCount = 512; -#define VADDR_TO_PML4E(va) (((va) & 0x0000fffffffff000L) / k64BitPDPTRange) +#define VADDR_TO_PML5E(va) (((va) & 0x01fffffffffff000L) / k64BitPML4TRange) +#define VADDR_TO_PML4E(va) (((va) % k64BitPML4TRange) / k64BitPDPTRange) #define VADDR_TO_PDPTE(va) (((va) % k64BitPDPTRange) / k64BitPageDirectoryRange) #define VADDR_TO_PDE(va) (((va) % k64BitPageDirectoryRange) / k64BitPageTableRange) #define VADDR_TO_PTE(va) (((va) % k64BitPageTableRange) / B_PAGE_SIZE)