]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/VmgExitLib: Implement library support for VmgExitLib in OVMF
authorTom Lendacky <thomas.lendacky@amd.com>
Wed, 12 Aug 2020 20:21:36 +0000 (15:21 -0500)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 17 Aug 2020 02:46:39 +0000 (02:46 +0000)
The base VmgExitLib library provides a default limited interface. As it
does not provide full support, create an OVMF version of this library to
begin the process of providing full support of SEV-ES within OVMF.

SEV-ES support is only provided for X64 builds, so only OvmfPkgX64.dsc is
updated to make use of the OvmfPkg version of the library.

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/VmgExitLib.c [new file with mode: 0644]
OvmfPkg/Library/VmgExitLib/VmgExitLib.inf [new file with mode: 0644]
OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c [new file with mode: 0644]
OvmfPkg/OvmfPkgX64.dsc

diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitLib.c b/OvmfPkg/Library/VmgExitLib/VmgExitLib.c
new file mode 100644 (file)
index 0000000..53040cc
--- /dev/null
@@ -0,0 +1,159 @@
+/** @file\r
+  VMGEXIT Support Library.\r
+\r
+  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Base.h>\r
+#include <Uefi.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/VmgExitLib.h>\r
+#include <Register/Amd/Msr.h>\r
+\r
+/**\r
+  Check for VMGEXIT error\r
+\r
+  Check if the hypervisor has returned an error after completion of the VMGEXIT\r
+  by examining the SwExitInfo1 field of the GHCB.\r
+\r
+  @param[in]  Ghcb       A pointer to the GHCB\r
+\r
+  @retval  0             VMGEXIT succeeded.\r
+  @return                Exception number to be propagated, VMGEXIT processing\r
+                         did not succeed.\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+VmgExitErrorCheck (\r
+  IN GHCB                *Ghcb\r
+  )\r
+{\r
+  GHCB_EVENT_INJECTION  Event;\r
+  GHCB_EXIT_INFO        ExitInfo;\r
+  UINT64                Status;\r
+\r
+  ExitInfo.Uint64 = Ghcb->SaveArea.SwExitInfo1;\r
+  ASSERT ((ExitInfo.Elements.Lower32Bits == 0) ||\r
+          (ExitInfo.Elements.Lower32Bits == 1));\r
+\r
+  Status = 0;\r
+  if (ExitInfo.Elements.Lower32Bits == 0) {\r
+    return Status;\r
+  }\r
+\r
+  if (ExitInfo.Elements.Lower32Bits == 1) {\r
+    ASSERT (Ghcb->SaveArea.SwExitInfo2 != 0);\r
+\r
+    //\r
+    // Check that the return event is valid\r
+    //\r
+    Event.Uint64 = Ghcb->SaveArea.SwExitInfo2;\r
+    if (Event.Elements.Valid &&\r
+        Event.Elements.Type == GHCB_EVENT_INJECTION_TYPE_EXCEPTION) {\r
+      switch (Event.Elements.Vector) {\r
+      case GP_EXCEPTION:\r
+      case UD_EXCEPTION:\r
+        //\r
+        // Use returned event as return code\r
+        //\r
+        Status = Event.Uint64;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (Status == 0) {\r
+    GHCB_EVENT_INJECTION  GpEvent;\r
+\r
+    GpEvent.Uint64 = 0;\r
+    GpEvent.Elements.Vector = GP_EXCEPTION;\r
+    GpEvent.Elements.Type   = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;\r
+    GpEvent.Elements.Valid  = 1;\r
+\r
+    Status = GpEvent.Uint64;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Perform VMGEXIT.\r
+\r
+  Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and\r
+  then handles the return actions.\r
+\r
+  @param[in, out]  Ghcb       A pointer to the GHCB\r
+  @param[in]       ExitCode   VMGEXIT code to be assigned to the SwExitCode\r
+                              field of the GHCB.\r
+  @param[in]       ExitInfo1  VMGEXIT information to be assigned to the\r
+                              SwExitInfo1 field of the GHCB.\r
+  @param[in]       ExitInfo2  VMGEXIT information to be assigned to the\r
+                              SwExitInfo2 field of the GHCB.\r
+\r
+  @retval  0                  VMGEXIT succeeded.\r
+  @return                     Exception number to be propagated, VMGEXIT\r
+                              processing did not succeed.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+VmgExit (\r
+  IN OUT GHCB                *Ghcb,\r
+  IN     UINT64              ExitCode,\r
+  IN     UINT64              ExitInfo1,\r
+  IN     UINT64              ExitInfo2\r
+  )\r
+{\r
+  Ghcb->SaveArea.SwExitCode = ExitCode;\r
+  Ghcb->SaveArea.SwExitInfo1 = ExitInfo1;\r
+  Ghcb->SaveArea.SwExitInfo2 = ExitInfo2;\r
+\r
+  //\r
+  // Guest memory is used for the guest-hypervisor communication, so fence\r
+  // the invocation of the VMGEXIT instruction to ensure GHCB accesses are\r
+  // synchronized properly.\r
+  //\r
+  MemoryFence ();\r
+  AsmVmgExit ();\r
+  MemoryFence ();\r
+\r
+  return VmgExitErrorCheck (Ghcb);\r
+}\r
+\r
+/**\r
+  Perform pre-VMGEXIT initialization/preparation.\r
+\r
+  Performs the necessary steps in preparation for invoking VMGEXIT. Must be\r
+  called before setting any fields within the GHCB.\r
+\r
+  @param[in, out]  Ghcb       A pointer to the GHCB\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VmgInit (\r
+  IN OUT GHCB                *Ghcb\r
+  )\r
+{\r
+  SetMem (&Ghcb->SaveArea, sizeof (Ghcb->SaveArea), 0);\r
+}\r
+\r
+/**\r
+  Perform post-VMGEXIT cleanup.\r
+\r
+  Performs the necessary steps to cleanup after invoking VMGEXIT. Must be\r
+  called after obtaining needed fields within the GHCB.\r
+\r
+  @param[in, out]  Ghcb       A pointer to the GHCB\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+VmgDone (\r
+  IN OUT GHCB                *Ghcb\r
+  )\r
+{\r
+}\r
+\r
diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf b/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
new file mode 100644 (file)
index 0000000..d003ac6
--- /dev/null
@@ -0,0 +1,36 @@
+## @file\r
+#  VMGEXIT Support Library.\r
+#\r
+#  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
+#  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = VmgExitLib\r
+  FILE_GUID                      = 0e923c25-13cd-430b-8714-ffe85652a97b\r
+  MODULE_TYPE                    = BASE\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = VmgExitLib\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = X64\r
+#\r
+\r
+[Sources.common]\r
+  VmgExitLib.c\r
+  VmgExitVcHandler.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  OvmfPkg/OvmfPkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+\r
+[LibraryClasses]\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+\r
diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
new file mode 100644 (file)
index 0000000..b6a955e
--- /dev/null
@@ -0,0 +1,81 @@
+/** @file\r
+  X64 #VC Exception Handler functon.\r
+\r
+  Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Base.h>\r
+#include <Uefi.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/VmgExitLib.h>\r
+#include <Register/Amd/Msr.h>\r
+\r
+/**\r
+  Handle a #VC exception.\r
+\r
+  Performs the necessary processing to handle a #VC exception.\r
+\r
+  @param[in, out]  ExceptionType  Pointer to an EFI_EXCEPTION_TYPE to be set\r
+                                  as value to use on error.\r
+  @param[in, out]  SystemContext  Pointer to EFI_SYSTEM_CONTEXT\r
+\r
+  @retval  EFI_SUCCESS            Exception handled\r
+  @retval  EFI_UNSUPPORTED        #VC not supported, (new) exception value to\r
+                                  propagate provided\r
+  @retval  EFI_PROTOCOL_ERROR     #VC handling failed, (new) exception value to\r
+                                  propagate provided\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VmgExitHandleVc (\r
+  IN OUT EFI_EXCEPTION_TYPE  *ExceptionType,\r
+  IN OUT EFI_SYSTEM_CONTEXT  SystemContext\r
+  )\r
+{\r
+  MSR_SEV_ES_GHCB_REGISTER  Msr;\r
+  EFI_SYSTEM_CONTEXT_X64    *Regs;\r
+  GHCB                      *Ghcb;\r
+  UINT64                    ExitCode, Status;\r
+  EFI_STATUS                VcRet;\r
+\r
+  VcRet = EFI_SUCCESS;\r
+\r
+  Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);\r
+  ASSERT (Msr.GhcbInfo.Function == 0);\r
+  ASSERT (Msr.Ghcb != 0);\r
+\r
+  Regs = SystemContext.SystemContextX64;\r
+  Ghcb = Msr.Ghcb;\r
+\r
+  VmgInit (Ghcb);\r
+\r
+  ExitCode = Regs->ExceptionData;\r
+  switch (ExitCode) {\r
+  default:\r
+    Status = VmgExit (Ghcb, SVM_EXIT_UNSUPPORTED, ExitCode, 0);\r
+    if (Status == 0) {\r
+      Regs->ExceptionData = 0;\r
+      *ExceptionType = GP_EXCEPTION;\r
+    } else {\r
+      GHCB_EVENT_INJECTION  Event;\r
+\r
+      Event.Uint64 = Status;\r
+      if (Event.Elements.ErrorCodeValid != 0) {\r
+        Regs->ExceptionData = Event.Elements.ErrorCode;\r
+      } else {\r
+        Regs->ExceptionData = 0;\r
+      }\r
+\r
+      *ExceptionType = Event.Elements.Vector;\r
+    }\r
+\r
+    VcRet = EFI_PROTOCOL_ERROR;\r
+  }\r
+\r
+  VmgDone (Ghcb);\r
+\r
+  return VcRet;\r
+}\r
index 27f5225fc2812df0f427f13269e54e15de19d00b..60be5eae3d2b9375e67c5f182701fc146063e323 100644 (file)
 \r
 [LibraryClasses.common]\r
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf\r
-  VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf\r
+  VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf\r
 \r
 [LibraryClasses.common.SEC]\r
   TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf\r