From: Tom Lendacky <thomas.lenda...@amd.com> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198
A GHCB page is needed during the Sec phase, so this new page must be created. Since the GHCB must be marked as an un-encrypted, or shared, page, an additional pagetable page is required to break down the 2MB region where the GHCB page lives into 4K pagetable entries. Create a new entry in the OVMF memory layout for the new page table page and for the SEC GHCB page. After breaking down the 2MB page, update the GHCB page table entry to remove the encryption mask. Cc: Jordan Justen <jordan.l.jus...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Cc: Ard Biesheuvel <ard.biesheu...@linaro.org> Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com> --- OvmfPkg/OvmfPkg.dec | 10 +++ OvmfPkg/OvmfPkgX64.fdf | 6 ++ OvmfPkg/ResetVector/ResetVector.inf | 4 ++ OvmfPkg/ResetVector/Ia32/PageTables64.asm | 79 +++++++++++++++++++++++ OvmfPkg/ResetVector/ResetVector.nasmb | 12 ++++ 5 files changed, 111 insertions(+) diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec index 9640360f6245..b9287a023c94 100644 --- a/OvmfPkg/OvmfPkg.dec +++ b/OvmfPkg/OvmfPkg.dec @@ -218,6 +218,16 @@ [PcdsFixedAtBuild] # The value should be a multiple of 4KB. gUefiOvmfPkgTokenSpaceGuid.PcdHighPmmMemorySize|0x400000|UINT32|0x31 + ## Specify the extra page table needed to mark the GHCB as unencrypted. + # The value should be a multiple of 4KB for each. + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase|0x0|UINT32|0x32 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableSize|0x0|UINT32|0x33 + + ## Specify the GHCB base address and size. + # The value should be a multiple of 4KB for each. + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase|0x0|UINT32|0x34 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize|0x0|UINT32|0x35 + [PcdsDynamic, PcdsDynamicEx] gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10 diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index 74407072563b..a567131a0591 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -76,6 +76,12 @@ [FD.MEMFD] 0x007000|0x001000 gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress|gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize +0x008000|0x001000 +gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableSize + +0x009000|0x001000 +gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize + 0x010000|0x010000 gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize diff --git a/OvmfPkg/ResetVector/ResetVector.inf b/OvmfPkg/ResetVector/ResetVector.inf index 960b47cd0797..80c971354176 100644 --- a/OvmfPkg/ResetVector/ResetVector.inf +++ b/OvmfPkg/ResetVector/ResetVector.inf @@ -37,3 +37,7 @@ [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableSize + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm index 40f7814c1134..7e346661f2c8 100644 --- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm +++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm @@ -21,6 +21,11 @@ BITS 32 %define PAGE_2M_MBO 0x080 %define PAGE_2M_PAT 0x01000 +%define PAGE_4K_PDE_ATTR (PAGE_ACCESSED + \ + PAGE_DIRTY + \ + PAGE_READ_WRITE + \ + PAGE_PRESENT) + %define PAGE_2M_PDE_ATTR (PAGE_2M_MBO + \ PAGE_ACCESSED + \ PAGE_DIRTY + \ @@ -95,6 +100,37 @@ SevExit: OneTimeCallRet CheckSevFeature +; Check if Secure Encrypted Virtualization - Encrypted State (SEV-ES) feature +; is enabled. +; +; Modified: EAX, EBX, ECX, EDX +; +; If SEV-ES is enabled then EAX will be non-zero. +; If SEV-ES is disabled then EAX will be zero. +; +CheckSevEsFeature: + xor eax, eax + + ; SEV-ES can't be enabled if SEV isn't, so first check the encryption + ; mask. + test edx, edx + jz NoSevEs + + ; Save current value of encryption mask + mov ebx, edx + + ; Check if SEV-ES is enabled + ; MSR_0xC0010131 - Bit 1 (SEV-ES enabled) + mov ecx, 0xc0010131 + rdmsr + and eax, 2 + + ; Restore encryption mask + mov edx, ebx + +NoSevEs: + OneTimeCallRet CheckSevEsFeature + ; ; Modified: EAX, EBX, ECX, EDX ; @@ -159,6 +195,49 @@ pageTableEntriesLoop: mov [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx loop pageTableEntriesLoop + OneTimeCall CheckSevEsFeature + test eax, eax + jz SetCr3 + + ; + ; The initial GHCB will live at 0x809000 and needs to be un-encrypted. + ; This requires the 2MB page (index 4 in the first 1GB page) for this + ; range be broken down into 512 4KB pages. All will be marked encrypted, + ; except for the GHCB. + ; + mov ecx, 4 + mov eax, GHCB_PT_ADDR + PAGE_PDP_ATTR + mov [ecx * 8 + PT_ADDR (0x2000)], eax + + ; + ; Page Table Entries (512 * 4KB entries => 2MB) + ; + mov ecx, 512 +pageTableEntries4kLoop: + mov eax, ecx + dec eax + shl eax, 12 + add eax, 0x800000 + add eax, PAGE_4K_PDE_ATTR + mov [ecx * 8 + GHCB_PT_ADDR - 8], eax + mov [ecx * 8 + GHCB_PT_ADDR - 4], edx + loop pageTableEntries4kLoop + + ; + ; Clear the encryption bit from the GHCB entry (index 9 in the + ; new PTE table: (0x809000 - 0x800000) >> 12)). + ; + mov ecx, 9 + xor edx, edx + mov [ecx * 8 + GHCB_PT_ADDR + 4], edx + + mov ecx, GHCB_SIZE / 4 + xor eax, eax +clearGhcbMemoryLoop: + mov dword[ecx * 4 + GHCB_BASE - 4], eax + loop clearGhcbMemoryLoop + +SetCr3: ; ; Set CR3 now that the paging structures are available ; diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/ResetVector.nasmb index 3b213cd05ab2..8909fc9313f4 100644 --- a/OvmfPkg/ResetVector/ResetVector.nasmb +++ b/OvmfPkg/ResetVector/ResetVector.nasmb @@ -53,7 +53,19 @@ %error "This implementation inherently depends on PcdOvmfSecPageTablesSize" %endif + %if (FixedPcdGet32 (PcdOvmfSecGhcbPageTableSize) != 0x1000) + %error "This implementation inherently depends on PcdOvmfSecGhcbPageTableSize" + %endif + + %if (FixedPcdGet32 (PcdOvmfSecGhcbSize) != 0x1000) + %error "This implementation inherently depends on PcdOvmfSecGhcbSize" + %endif + %define PT_ADDR(Offset) (FixedPcdGet32 (PcdOvmfSecPageTablesBase) + (Offset)) + + %define GHCB_PT_ADDR (FixedPcdGet32 (PcdOvmfSecGhcbPageTableBase)) + %define GHCB_BASE (FixedPcdGet32 (PcdOvmfSecGhcbBase)) + %define GHCB_SIZE (FixedPcdGet32 (PcdOvmfSecGhcbSize)) %include "Ia32/Flat32ToFlat64.asm" %define SEV_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize)) %include "Ia32/PageTables64.asm" -- 2.17.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#47640): https://edk2.groups.io/g/devel/message/47640 Mute This Topic: https://groups.io/mt/34203541/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-