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"]
This commit is contained in:
Gerd Hoffmann 2024-03-01 08:43:58 +01:00 committed by mergify[bot]
parent e3bd782373
commit 49b7faba1d
3 changed files with 102 additions and 0 deletions

View File

@ -101,6 +101,97 @@ BITS 32
loop .pageTableEntriesLoop4Level
%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
;
@ -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
@ -152,6 +250,8 @@ TdxBspInit:
jmp SetCr3
SetCr3:
;
; common workflow
;
; Set CR3 now that the paging structures are available
;

View File

@ -64,3 +64,4 @@
gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsSize
gEfiMdeModulePkgTokenSpaceGuid.PcdUse5LevelPageTable

View File

@ -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))