[haiku-commits] Change in haiku[master]: boot/bios_ia32: basic support la57 aka 5-level paging for x86_64 kernels

  • From: Gerrit <review@xxxxxxxxxxxxxxxxxxx>
  • To: waddlesplash <waddlesplash@xxxxxxxxx>, haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 26 Dec 2020 17:53:04 +0000

From Jérôme Duval <jerome.duval@xxxxxxxxx>:

Jérôme Duval has uploaded this change for review. ( 
https://review.haiku-os.org/c/haiku/+/3552 ;)


Change subject: boot/bios_ia32: basic support la57 aka 5-level paging for 
x86_64 kernels
......................................................................

boot/bios_ia32: basic support la57 aka 5-level paging for x86_64 kernels

la57 kernel support is required. we simply add a 5th level and enable the cr4
feature. the safemode option "256tb_memory_limit" is named after the 4gb one,
but the current support is limited to 512GB as before (this can be later 
extended).
---
M headers/private/system/safemode_defs.h
M src/system/boot/platform/bios_ia32/long.cpp
M src/system/boot/platform/bios_ia32/long_asm.S
M src/system/boot/platform/bios_ia32/smp.cpp
4 files changed, 69 insertions(+), 26 deletions(-)



  git pull ssh://git.haiku-os.org:22/haiku refs/changes/52/3552/1

diff --git a/headers/private/system/safemode_defs.h 
b/headers/private/system/safemode_defs.h
index 41292dd..8b92e32 100644
--- a/headers/private/system/safemode_defs.h
+++ b/headers/private/system/safemode_defs.h
@@ -18,6 +18,7 @@
 #define B_SAFEMODE_DISABLE_HYPER_THREADING     "disable_hyperthreading"
 #define B_SAFEMODE_FAIL_SAFE_VIDEO_MODE                "fail_safe_video_mode"
 #define B_SAFEMODE_4_GB_MEMORY_LIMIT           "4gb_memory_limit"
+#define B_SAFEMODE_256_TB_MEMORY_LIMIT         "256tb_memory_limit"

 #if DEBUG_SPINLOCK_LATENCIES
 #      define B_SAFEMODE_DISABLE_LATENCY_CHECK "disable_latency_check"
diff --git a/src/system/boot/platform/bios_ia32/long.cpp 
b/src/system/boot/platform/bios_ia32/long.cpp
index c784422..539e91e 100644
--- a/src/system/boot/platform/bios_ia32/long.cpp
+++ b/src/system/boot/platform/bios_ia32/long.cpp
@@ -21,6 +21,7 @@
 #include <boot/stage2.h>
 #include <boot/stdio.h>
 #include <kernel.h>
+#include <safemode.h>

 #include "debug.h"
 #include "mmu.h"
@@ -35,7 +36,8 @@
 extern "C" void long_enter_kernel(int currentCPU, uint64 stackTop);

 extern uint64 gLongGDT;
-extern uint32 gLongPhysicalPML4;
+extern uint32 gLongPhysicalPMLTop;
+extern bool gLongLA57;
 extern uint64 gLongKernelEntry;


@@ -88,16 +90,11 @@
 static void
 long_mmu_init()
 {
-       uint64* pml4;
-       uint64* pdpt;
-       uint64* pageDir;
-       uint64* pageTable;
-       addr_t physicalAddress;
-
-       // Allocate the top level PML4.
-       pml4 = (uint64*)mmu_allocate_page(&gKernelArgs.arch_args.phys_pgdir);
-       memset(pml4, 0, B_PAGE_SIZE);
-       gKernelArgs.arch_args.vir_pgdir = fix_address((uint64)(addr_t)pml4);
+       uint64* pmlTop;
+       // Allocate the top level PMLTop.
+       pmlTop = (uint64*)mmu_allocate_page(&gKernelArgs.arch_args.phys_pgdir);
+       memset(pmlTop, 0, B_PAGE_SIZE);
+       gKernelArgs.arch_args.vir_pgdir = fix_address((uint64)(addr_t)pmlTop);

        // Store the virtual memory usage information.
        gKernelArgs.virtual_allocated_range[0].start = KERNEL_LOAD_BASE_64_BIT;
@@ -127,6 +124,29 @@
        if (maxAddress / 0x40000000 > 512)
                panic("Can't currently support more than 512GB of RAM!");

+       uint64* pml4 = pmlTop;
+       addr_t physicalAddress;
+       cpuid_info info;
+       if (get_current_cpuid(&info, 7, 0) == B_OK
+               && (info.regs.ecx & IA32_FEATURE_LA57) != 0) {
+
+               if (get_safemode_boolean(B_SAFEMODE_256_TB_MEMORY_LIMIT, 
false)) {
+                       // LA57 has been disabled!
+                       dprintf("la57 disabled per safemode setting\n");
+               } else {
+                       dprintf("la57 enabled\n");
+                       gLongLA57 = true;
+                       pml4 = (uint64*)mmu_allocate_page(&physicalAddress);
+                       memset(pml4, 0, B_PAGE_SIZE);
+                       pmlTop[511] = physicalAddress | kTableMappingFlags;
+                       pmlTop[0] = physicalAddress | kTableMappingFlags;
+               }
+       }
+
+       uint64* pdpt;
+       uint64* pageDir;
+       uint64* pageTable;
+
        // Create page tables for the physical map area. Also map this PDPT
        // temporarily at the bottom of the address space so that we are 
identity
        // mapped.
@@ -151,7 +171,6 @@
        mmu_free(pdpt, B_PAGE_SIZE);

        // Allocate tables for the kernel mappings.
-
        pdpt = (uint64*)mmu_allocate_page(&physicalAddress);
        memset(pdpt, 0, B_PAGE_SIZE);
        pml4[511] = physicalAddress | kTableMappingFlags;
@@ -186,6 +205,8 @@
                mmu_free(pageTable, B_PAGE_SIZE);
        mmu_free(pageDir, B_PAGE_SIZE);
        mmu_free(pdpt, B_PAGE_SIZE);
+       if (pml4 != pmlTop)
+               mmu_free(pml4, B_PAGE_SIZE);

        // Sort the address ranges.
        sort_address_ranges(gKernelArgs.physical_memory_range,
@@ -216,7 +237,7 @@
                        gKernelArgs.virtual_allocated_range[i].size);
        }

-       gLongPhysicalPML4 = gKernelArgs.arch_args.phys_pgdir;
+       gLongPhysicalPMLTop = gKernelArgs.arch_args.phys_pgdir;
 }


diff --git a/src/system/boot/platform/bios_ia32/long_asm.S 
b/src/system/boot/platform/bios_ia32/long_asm.S
index 4556c68..c7eec5c 100644
--- a/src/system/boot/platform/bios_ia32/long_asm.S
+++ b/src/system/boot/platform/bios_ia32/long_asm.S
@@ -27,6 +27,9 @@
        movl    8(%esp), %edi
        movl    12(%esp), %esi

+       movl    gLongLA57, %ecx
+       shl             $12, %ecx
+
        // Currently running with 32-bit paging tables at an identity mapped
        // address. To switch to 64-bit paging we must first disable 32-bit 
paging,
        // otherwise loading the new CR3 will fault.
@@ -34,13 +37,14 @@
        andl    $~(1 << 31), %eax
        movl    %eax, %cr0

-       // Enable PAE and PGE
+       // Enable PAE and PGE, and optionally LA57
        movl    %cr4, %eax
        orl             $(1 << 5) | (1 << 7), %eax
+       orl             %ecx, %eax
        movl    %eax, %cr4

-       // Point CR3 to the kernel's PML4.
-       movl    gLongPhysicalPML4, %eax
+       // Point CR3 to the kernel's PMLTop.
+       movl    gLongPhysicalPMLTop, %eax
        movl    %eax, %cr3

        // Enable long mode by setting EFER.LME.
@@ -97,7 +101,10 @@
 SYMBOL(gLongGDT):
        .long   0

-SYMBOL(gLongPhysicalPML4):
+SYMBOL(gLongPhysicalPMLTop):
+       .long   0
+
+SYMBOL(gLongLA57):
        .long   0

 SYMBOL(gLongKernelEntry):
diff --git a/src/system/boot/platform/bios_ia32/smp.cpp 
b/src/system/boot/platform/bios_ia32/smp.cpp
index 277cb6f..0356bb9 100644
--- a/src/system/boot/platform/bios_ia32/smp.cpp
+++ b/src/system/boot/platform/bios_ia32/smp.cpp
@@ -589,16 +589,30 @@
                        item->SetHelpText("Disables using X2APIC.");
                }

-               if (get_current_cpuid(&info, 7, 0) == B_OK
-                               && (info.regs.ebx & (IA32_FEATURE_SMEP
-                                       | IA32_FEATURE_SMAP)) != 0) {
-                       menu->AddItem(item = new(nothrow) MenuItem(
-                               "Disable SMEP and SMAP"));
-                       item->SetType(MENU_ITEM_MARKABLE);
-                       item->SetData(B_SAFEMODE_DISABLE_SMEP_SMAP);
-                       item->SetHelpText("Disables using SMEP and SMAP.");
-               }
+               get_current_cpuid(&info, 0, 0);
+               uint32 maxBasicLeaf = info.eax_0.max_eax;
+               if (maxBasicLeaf >= 7) {
+                       if (get_current_cpuid(&info, 7, 0) == B_OK
+                                       && (info.regs.ebx & (IA32_FEATURE_SMEP
+                                               | IA32_FEATURE_SMAP)) != 0) {
+                               menu->AddItem(item = new(nothrow) MenuItem(
+                                       "Disable SMEP and SMAP"));
+                               item->SetType(MENU_ITEM_MARKABLE);
+                               item->SetData(B_SAFEMODE_DISABLE_SMEP_SMAP);
+                               item->SetHelpText("Disables using SMEP and 
SMAP.");
+                       }

+                       if (get_current_cpuid(&info, 7, 0) == B_OK
+                                       && (info.regs.ecx & IA32_FEATURE_LA57) 
!= 0) {
+                               menu->AddItem(item = new(nothrow) MenuItem(
+                                       "Ignore memory beyond 256 TiB"));
+                               item->SetType(MENU_ITEM_MARKABLE);
+                               item->SetData(B_SAFEMODE_256_TB_MEMORY_LIMIT);
+                               item->SetHelpText("Ignores all memory beyond 
the 256 TiB "
+                                       "address limit, overriding the setting 
in the kernel "
+                                       "settings file.");
+                       }
+               }
        }

        if (gKernelArgs.num_cpus < 2)

--
To view, visit https://review.haiku-os.org/c/haiku/+/3552
To unsubscribe, or for help writing mail filters, visit 
https://review.haiku-os.org/settings

Gerrit-Project: haiku
Gerrit-Branch: master
Gerrit-Change-Id: I922774473c4a6112a0e4ff74162285ad58aa53af
Gerrit-Change-Number: 3552
Gerrit-PatchSet: 1
Gerrit-Owner: Jérôme Duval <jerome.duval@xxxxxxxxx>
Gerrit-MessageType: newchange

Other related posts:

  • » [haiku-commits] Change in haiku[master]: boot/bios_ia32: basic support la57 aka 5-level paging for x86_64 kernels - Gerrit