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