]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/VmgExitLib: Add support for CPUID NAE events
authorTom Lendacky <thomas.lendacky@amd.com>
Wed, 12 Aug 2020 20:21:37 +0000 (15:21 -0500)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 17 Aug 2020 02:46:39 +0000 (02:46 +0000)
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198

Under SEV-ES, a CPUID intercept generates a #VC exception. VMGEXIT must be
used to allow the hypervisor to handle this intercept.

Add support to construct the required GHCB values to support a CPUID NAE
event. Additionally, CPUID 0x0000_000d (CPUID_EXTENDED_STATE) requires
XCR0 to be supplied in the GHCB, so add support to issue the XGETBV
instruction.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c

index bc2e270a7ce87da42297ab4c3f3bde10e18cc879..476e94ce5fb7af9968cf771966dbd1de093276e7 100644 (file)
@@ -11,6 +11,7 @@
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/VmgExitLib.h>\r
 #include <Register/Amd/Msr.h>\r
+#include <Register/Intel/Cpuid.h>\r
 #include <IndustryStandard/InstructionParsing.h>\r
 \r
 //\r
@@ -597,6 +598,61 @@ IoioExit (
   return 0;\r
 }\r
 \r
+/**\r
+  Handle a CPUID event.\r
+\r
+  Use the VMGEXIT instruction to handle a CPUID event.\r
+\r
+  @param[in, out] Ghcb             Pointer to the Guest-Hypervisor Communication\r
+                                   Block\r
+  @param[in, out] Regs             x64 processor context\r
+  @param[in]      InstructionData  Instruction parsing context\r
+\r
+  @retval 0                        Event handled successfully\r
+  @return                          New exception value to propagate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+CpuidExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  UINT64  Status;\r
+\r
+  Ghcb->SaveArea.Rax = Regs->Rax;\r
+  GhcbSetRegValid (Ghcb, GhcbRax);\r
+  Ghcb->SaveArea.Rcx = Regs->Rcx;\r
+  GhcbSetRegValid (Ghcb, GhcbRcx);\r
+  if (Regs->Rax == CPUID_EXTENDED_STATE) {\r
+    IA32_CR4  Cr4;\r
+\r
+    Cr4.UintN = AsmReadCr4 ();\r
+    Ghcb->SaveArea.XCr0 = (Cr4.Bits.OSXSAVE == 1) ? AsmXGetBv (0) : 1;\r
+    GhcbSetRegValid (Ghcb, GhcbXCr0);\r
+  }\r
+\r
+  Status = VmgExit (Ghcb, SVM_EXIT_CPUID, 0, 0);\r
+  if (Status != 0) {\r
+    return Status;\r
+  }\r
+\r
+  if (!GhcbIsRegValid (Ghcb, GhcbRax) ||\r
+      !GhcbIsRegValid (Ghcb, GhcbRbx) ||\r
+      !GhcbIsRegValid (Ghcb, GhcbRcx) ||\r
+      !GhcbIsRegValid (Ghcb, GhcbRdx)) {\r
+    return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+  }\r
+  Regs->Rax = Ghcb->SaveArea.Rax;\r
+  Regs->Rbx = Ghcb->SaveArea.Rbx;\r
+  Regs->Rcx = Ghcb->SaveArea.Rcx;\r
+  Regs->Rdx = Ghcb->SaveArea.Rdx;\r
+\r
+  return 0;\r
+}\r
+\r
 /**\r
   Handle a #VC exception.\r
 \r
@@ -641,6 +697,10 @@ VmgExitHandleVc (
 \r
   ExitCode = Regs->ExceptionData;\r
   switch (ExitCode) {\r
+  case SVM_EXIT_CPUID:\r
+    NaeExit = CpuidExit;\r
+    break;\r
+\r
   case SVM_EXIT_IOIO_PROT:\r
     NaeExit = IoioExit;\r
     break;\r