]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/VmgExitLib: Add support for MSR_PROT 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 MSR_PROT 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 an MSR_PROT
NAE event. Parse the instruction that generated the #VC exception to
determine whether it is RDMSR or WRMSR, setting the required register
register values in the GHCB and creating the proper SW_EXIT_INFO1 value in
the GHCB.

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 476e94ce5fb7af9968cf771966dbd1de093276e7..f6cfd7fa29930e7d8430ecbcbcb7a5c3ec73e9a8 100644 (file)
@@ -374,6 +374,67 @@ UnsupportedExit (
   return Status;\r
 }\r
 \r
+/**\r
+  Handle an MSR event.\r
+\r
+  Use the VMGEXIT instruction to handle either a RDMSR or WRMSR 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
+MsrExit (\r
+  IN OUT GHCB                     *Ghcb,\r
+  IN OUT EFI_SYSTEM_CONTEXT_X64   *Regs,\r
+  IN     SEV_ES_INSTRUCTION_DATA  *InstructionData\r
+  )\r
+{\r
+  UINT64  ExitInfo1, Status;\r
+\r
+  ExitInfo1 = 0;\r
+\r
+  switch (*(InstructionData->OpCodes + 1)) {\r
+  case 0x30: // WRMSR\r
+    ExitInfo1 = 1;\r
+    Ghcb->SaveArea.Rax = Regs->Rax;\r
+    GhcbSetRegValid (Ghcb, GhcbRax);\r
+    Ghcb->SaveArea.Rdx = Regs->Rdx;\r
+    GhcbSetRegValid (Ghcb, GhcbRdx);\r
+    //\r
+    // fall through\r
+    //\r
+  case 0x32: // RDMSR\r
+    Ghcb->SaveArea.Rcx = Regs->Rcx;\r
+    GhcbSetRegValid (Ghcb, GhcbRcx);\r
+    break;\r
+  default:\r
+    return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+  }\r
+\r
+  Status = VmgExit (Ghcb, SVM_EXIT_MSR, ExitInfo1, 0);\r
+  if (Status != 0) {\r
+    return Status;\r
+  }\r
+\r
+  if (ExitInfo1 == 0) {\r
+    if (!GhcbIsRegValid (Ghcb, GhcbRax) ||\r
+        !GhcbIsRegValid (Ghcb, GhcbRdx)) {\r
+      return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+    }\r
+    Regs->Rax = Ghcb->SaveArea.Rax;\r
+    Regs->Rdx = Ghcb->SaveArea.Rdx;\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
 /**\r
   Build the IOIO event information.\r
 \r
@@ -705,6 +766,10 @@ VmgExitHandleVc (
     NaeExit = IoioExit;\r
     break;\r
 \r
+  case SVM_EXIT_MSR:\r
+    NaeExit = MsrExit;\r
+    break;\r
+\r
   default:\r
     NaeExit = UnsupportedExit;\r
   }\r