kernel/x86_64: LA57 aka 5-level paging
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 <[email protected]> Reviewed-by: Axel Dörfler <[email protected]>
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,16 @@
|
||||
#include <OS.h>
|
||||
|
||||
|
||||
// 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)
|
||||
|
||||
Reference in New Issue
Block a user