summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2024-03-01 08:43:58 +0100
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2024-03-01 18:47:27 +0000
commit49b7faba1d6e29bd6238d6b85de22b2c3fca4d12 (patch)
tree9100cb040cb8cf7a81529a8377d6af837a5ec73d
parente3bd782373d87872c359939462a66d9bc2f2a252 (diff)
downloadedk2-49b7faba1d6e29bd6238d6b85de22b2c3fca4d12.tar.gz
edk2-49b7faba1d6e29bd6238d6b85de22b2c3fca4d12.tar.bz2
edk2-49b7faba1d6e29bd6238d6b85de22b2c3fca4d12.zip
OvmfPkg/ResetVector: add 5-level paging support
Add macros to check for 5-level paging and gigabyte page support. Enable 5-level paging for the non-confidential-computing case. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Message-Id: <20240301074402.98625-7-kraxel@redhat.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Oliver Steffen <osteffen@redhat.com> Cc: Michael Roth <michael.roth@amd.com> Cc: Erdem Aktas <erdemaktas@google.com> Cc: Min Xu <min.m.xu@intel.com> Cc: Ard Biesheuvel <ardb+tianocore@kernel.org> Cc: Tom Lendacky <thomas.lendacky@amd.com> [lersek@redhat.com: turn the "Cc:" message headers from Gerd's on-list posting into "Cc:" tags in the commit message, in order to pacify "PatchCheck.py"]
-rw-r--r--OvmfPkg/ResetVector/Ia32/PageTables64.asm100
-rw-r--r--OvmfPkg/ResetVector/ResetVector.inf1
-rw-r--r--OvmfPkg/ResetVector/ResetVector.nasmb1
3 files changed, 102 insertions, 0 deletions
diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
index 84a7b4efc0..2d7fd523e4 100644
--- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
+++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
@@ -102,6 +102,97 @@ BITS 32
%endmacro
;
+; Check whenever 5-level paging can be used
+;
+; Argument: jump label for 4-level paging
+;
+%macro Check5LevelPaging 1
+ ; check for cpuid leaf 0x07
+ mov eax, 0x00
+ cpuid
+ cmp eax, 0x07
+ jb %1
+
+ ; check for la57 (aka 5-level paging)
+ mov eax, 0x07
+ mov ecx, 0x00
+ cpuid
+ bt ecx, 16
+ jnc %1
+
+ ; check for cpuid leaf 0x80000001
+ mov eax, 0x80000000
+ cpuid
+ cmp eax, 0x80000001
+ jb %1
+
+ ; check for 1g pages
+ mov eax, 0x80000001
+ cpuid
+ bt edx, 26
+ jnc %1
+%endmacro
+
+;
+; Create page tables for 5-level paging with gigabyte pages
+;
+; Argument: upper 32 bits of the page table entries
+;
+; We have 6 pages available for the early page tables,
+; we use four of them:
+; PT_ADDR(0) - level 5 directory
+; PT_ADDR(0x1000) - level 4 directory
+; PT_ADDR(0x2000) - level 2 directory (0 -> 1GB)
+; PT_ADDR(0x3000) - level 3 directory
+;
+; The level 2 directory for the first gigabyte has the same
+; physical address in both 4-level and 5-level paging mode,
+; SevClearPageEncMaskForGhcbPage depends on this.
+;
+; The 1 GB -> 4 GB range is mapped using 1G pages in the
+; level 3 directory.
+;
+%macro CreatePageTables5Level 1
+ ; level 5
+ mov dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDE_DIRECTORY_ATTR
+ mov dword[PT_ADDR (4)], %1
+
+ ; level 4
+ mov dword[PT_ADDR (0x1000)], PT_ADDR (0x3000) + PAGE_PDE_DIRECTORY_ATTR
+ mov dword[PT_ADDR (0x1004)], %1
+
+ ; level 3 (1x -> level 2, 3x 1GB)
+ mov dword[PT_ADDR (0x3000)], PT_ADDR (0x2000) + PAGE_PDE_DIRECTORY_ATTR
+ mov dword[PT_ADDR (0x3004)], %1
+ mov dword[PT_ADDR (0x3008)], (1 << 30) + PAGE_PDE_LARGEPAGE_ATTR
+ mov dword[PT_ADDR (0x300c)], %1
+ mov dword[PT_ADDR (0x3010)], (2 << 30) + PAGE_PDE_LARGEPAGE_ATTR
+ mov dword[PT_ADDR (0x3014)], %1
+ mov dword[PT_ADDR (0x3018)], (3 << 30) + PAGE_PDE_LARGEPAGE_ATTR
+ mov dword[PT_ADDR (0x301c)], %1
+
+ ;
+ ; level 2 (512 * 2MB entries => 1GB)
+ ;
+ mov ecx, 0x200
+.pageTableEntriesLoop5Level:
+ mov eax, ecx
+ dec eax
+ shl eax, 21
+ add eax, PAGE_PDE_LARGEPAGE_ATTR
+ mov dword[ecx * 8 + PT_ADDR (0x2000 - 8)], eax
+ mov dword[(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], %1
+ loop .pageTableEntriesLoop5Level
+%endmacro
+
+%macro Enable5LevelPaging 0
+ ; set la57 bit in cr4
+ mov eax, cr4
+ bts eax, 12
+ mov cr4, eax
+%endmacro
+
+;
; Modified: EAX, EBX, ECX, EDX
;
SetCr3ForPageTables64:
@@ -125,6 +216,13 @@ SetCr3ForPageTables64:
; normal (non-CoCo) workflow
;
ClearOvmfPageTables
+%if PG_5_LEVEL
+ Check5LevelPaging Paging4Level
+ CreatePageTables5Level 0
+ Enable5LevelPaging
+ jmp SetCr3
+Paging4Level:
+%endif
CreatePageTables4Level 0
jmp SetCr3
@@ -153,6 +251,8 @@ TdxBspInit:
SetCr3:
;
+ ; common workflow
+ ;
; Set CR3 now that the paging structures are available
;
mov eax, PT_ADDR (0)
diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf
index a4154ca90c..65f71b05a0 100644
--- a/OvmfPkg/ResetVector/ResetVector.inf
+++ b/OvmfPkg/ResetVector/ResetVector.inf
@@ -64,3 +64,4 @@
gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse5LevelPageTable
diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb
index 366a70fb99..2bd80149e5 100644
--- a/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -53,6 +53,7 @@
%define WORK_AREA_GUEST_TYPE (FixedPcdGet32 (PcdOvmfWorkAreaBase))
%define PT_ADDR(Offset) (FixedPcdGet32 (PcdOvmfSecPageTablesBase) + (Offset))
+%define PG_5_LEVEL (FixedPcdGetBool (PcdUse5LevelPageTable))
%define GHCB_PT_ADDR (FixedPcdGet32 (PcdOvmfSecGhcbPageTableBase))
%define GHCB_BASE (FixedPcdGet32 (PcdOvmfSecGhcbBase))