From: Tom Lendacky <thomas.lenda...@amd.com> An SEV-ES guest will generate a #VC exception when it encounters a non-automatic exit (NAE) event. It is expected that the #VC exception handler will communicate with the hypervisor using the GHCB to handle the NAE event.
NAE events can occur during the Sec phase, so initialize exception handling early in the OVMF Sec support. Add to the basic #VC exception handler to set the GHCB MSR to a pre-allocated GHCB and call a common #VC handler. Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com> --- OvmfPkg/Sec/SecMain.inf | 1 + .../SecPeiCpuExceptionHandlerLib.inf | 2 ++ .../CpuExceptionHandlerLib/AMDSevVcCommon.h | 7 ++++ MdePkg/Library/BaseLib/Ia32/GccInline.c | 17 +++++++++ OvmfPkg/Sec/SecMain.c | 29 ++++++++------- .../Ia32/AMDSevVcCommon.c | 13 +++++++ .../SecAMDSevVcHandler.c | 36 ++++++++++++++++++- .../X64/AMDSevVcCommon.c | 27 ++++++++++++++ 8 files changed, 118 insertions(+), 14 deletions(-) create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/AMDSevVcCommon.c create mode 100644 UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf index 63ba4cb555fb..7f53845f5436 100644 --- a/OvmfPkg/Sec/SecMain.inf +++ b/OvmfPkg/Sec/SecMain.inf @@ -50,6 +50,7 @@ [LibraryClasses] PeCoffExtraActionLib ExtractGuidedSectionLib LocalApicLib + CpuExceptionHandlerLib [Ppis] gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf index 5e5ab6244b11..1b3605af5ca4 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf @@ -26,11 +26,13 @@ [Sources.Ia32] Ia32/ExceptionTssEntryAsm.nasm Ia32/ArchExceptionHandler.c Ia32/ArchInterruptDefs.h + Ia32/AMDSevVcCommon.c [Sources.X64] X64/ExceptionHandlerAsm.nasm X64/ArchExceptionHandler.c X64/ArchInterruptDefs.h + X64/AMDSevVcCommon.c [Sources.common] CpuExceptionCommon.h diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/AMDSevVcCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/AMDSevVcCommon.h index ee52f3b5220d..94f9e6e5122d 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/AMDSevVcCommon.h +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/AMDSevVcCommon.h @@ -3,10 +3,17 @@ #define _AMD_SEV_VC_COMMON_H_ #include <Protocol/DebugSupport.h> +#include <Register/Amd/Ghcb.h> UINTN DoVcException( EFI_SYSTEM_CONTEXT Context ); +UINTN +DoVcCommon( + GHCB *Ghcb, + EFI_SYSTEM_CONTEXT Context + ); + #endif diff --git a/MdePkg/Library/BaseLib/Ia32/GccInline.c b/MdePkg/Library/BaseLib/Ia32/GccInline.c index 5287200f8754..55d2e12bcdc9 100644 --- a/MdePkg/Library/BaseLib/Ia32/GccInline.c +++ b/MdePkg/Library/BaseLib/Ia32/GccInline.c @@ -1763,3 +1763,20 @@ AsmFlushCacheLine ( } +/** + Executes a VMGEXIT instruction. + + Executes a VMGEXIT instruction. This function is only available on IA-32 and + X64. + +**/ +VOID +EFIAPI +AsmVmgExit ( + VOID + ) +{ + __asm__ __volatile__ ("rep; vmmcall":::"memory"); +} + + diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c index 2448be0cd408..021c1bd30711 100644 --- a/OvmfPkg/Sec/SecMain.c +++ b/OvmfPkg/Sec/SecMain.c @@ -24,6 +24,7 @@ #include <Library/PeCoffExtraActionLib.h> #include <Library/ExtractGuidedSectionLib.h> #include <Library/LocalApicLib.h> +#include <Library/CpuExceptionHandlerLib.h> #include <Ppi/TemporaryRamSupport.h> @@ -737,6 +738,21 @@ SecCoreStartupWithStack ( Table[Index] = 0; } + // + // Initialize IDT + // + IdtTableInStack.PeiService = NULL; + for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) { + CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate)); + } + + IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable; + IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1); + + AsmWriteIdtr (&IdtDescriptor); + + InitializeCpuExceptionHandlers (NULL); + ProcessLibraryConstructorList (NULL, NULL); // @@ -756,19 +772,6 @@ SecCoreStartupWithStack ( // InitializeFloatingPointUnits (); - // - // Initialize IDT - // - IdtTableInStack.PeiService = NULL; - for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) { - CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate)); - } - - IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable; - IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1); - - AsmWriteIdtr (&IdtDescriptor); - #if defined (MDE_CPU_X64) // // ASSERT that the Page Tables were set by the reset vector code to diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/AMDSevVcCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/AMDSevVcCommon.c new file mode 100644 index 000000000000..1b0c44bd6a61 --- /dev/null +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/AMDSevVcCommon.c @@ -0,0 +1,13 @@ + +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include "AMDSevVcCommon.h" + +UINTN +DoVcCommon ( + GHCB *Ghcb, + EFI_SYSTEM_CONTEXT Context + ) +{ + return GP_EXCEPTION; +} diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecAMDSevVcHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecAMDSevVcHandler.c index 1e027b3f2964..a32025d3481b 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecAMDSevVcHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecAMDSevVcHandler.c @@ -1,11 +1,45 @@ +#include <Library/BaseLib.h> +#include <Register/Amd/Msr.h> #include "CpuExceptionCommon.h" #include "AMDSevVcCommon.h" + +#define GHCB_INIT 0x807000 + UINTN DoVcException( EFI_SYSTEM_CONTEXT Context ) { - return 0; + MSR_SEV_ES_GHCB_REGISTER Msr; + GHCB *Ghcb; + + Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB); + Ghcb = Msr.Ghcb; + + if (Msr.Bits.GhcbNegotiateBit) { + if (Msr.GhcbProtocol.SevEsProtocolMin > Msr.GhcbProtocol.SevEsProtocolMax) { + ASSERT (0); + return GP_EXCEPTION; + } + + if ((Msr.GhcbProtocol.SevEsProtocolMin > GHCB_VERSION_MAX) || + (Msr.GhcbProtocol.SevEsProtocolMax < GHCB_VERSION_MIN)) { + ASSERT (0); + return GP_EXCEPTION; + } + + Msr.GhcbPhysicalAddress = GHCB_INIT; + AsmWriteMsr64(MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress); + + Ghcb = Msr.Ghcb; + SetMem (Ghcb, sizeof (*Ghcb), 0); + + /* Set the version to the maximum that can be supported */ + Ghcb->ProtocolVersion = MIN (Msr.GhcbProtocol.SevEsProtocolMax, GHCB_VERSION_MAX); + Ghcb->GhcbUsage = GHCB_STANDARD_USAGE; + } + + return DoVcCommon(Ghcb, Context); } diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c new file mode 100644 index 000000000000..18e462ce80a2 --- /dev/null +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c @@ -0,0 +1,27 @@ + +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include "AMDSevVcCommon.h" + +UINTN +DoVcCommon ( + GHCB *Ghcb, + EFI_SYSTEM_CONTEXT Context + ) +{ + EFI_SYSTEM_CONTEXT_X64 *Regs = Context.SystemContextX64; + UINTN ExitCode; + UINTN Status; + + VmgInit (Ghcb); + + ExitCode = Regs->ExceptionData; + switch (ExitCode) { + default: + Status = VmgExit (Ghcb, SvmExitUnsupported, ExitCode, 0); + } + + VmgDone (Ghcb); + + return Status; +} -- 2.17.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#46105): https://edk2.groups.io/g/devel/message/46105 Mute This Topic: https://groups.io/mt/32966277/21656 Mute #vc: https://groups.io/mk?hashtag=vc&subid=3846945 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-