]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
OvfmPkg/VmgExitLib: Validate #VC MMIO is to un-encrypted memory
[mirror_edk2.git] / OvmfPkg / Library / VmgExitLib / VmgExitVcHandler.c
index ce577e4677ebb93c9be62b58af7487d5626b757f..24259060fd652460103698fbbe92205f03420a49 100644 (file)
@@ -9,6 +9,7 @@
 #include <Base.h>\r
 #include <Uefi.h>\r
 #include <Library/BaseMemoryLib.h>\r
+#include <Library/LocalApicLib.h>\r
 #include <Library/MemEncryptSevLib.h>\r
 #include <Library/VmgExitLib.h>\r
 #include <Register/Amd/Msr.h>\r
@@ -595,6 +596,61 @@ UnsupportedExit (
   return Status;\r
 }\r
 \r
+/**\r
+  Validate that the MMIO memory access is not to encrypted memory.\r
+\r
+  Examine the pagetable entry for the memory specified. MMIO should not be\r
+  performed against encrypted memory. MMIO to the APIC page is always allowed.\r
+\r
+  @param[in] Ghcb           Pointer to the Guest-Hypervisor Communication Block\r
+  @param[in] MemoryAddress  Memory address to validate\r
+  @param[in] MemoryLength   Memory length to validate\r
+\r
+  @retval 0          Memory is not encrypted\r
+  @return            New exception value to propogate\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+ValidateMmioMemory (\r
+  IN GHCB   *Ghcb,\r
+  IN UINTN  MemoryAddress,\r
+  IN UINTN  MemoryLength\r
+  )\r
+{\r
+  MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE  State;\r
+  GHCB_EVENT_INJECTION                 GpEvent;\r
+  UINTN                                Address;\r
+\r
+  //\r
+  // Allow APIC accesses (which will have the encryption bit set during\r
+  // SEC and PEI phases).\r
+  //\r
+  Address = MemoryAddress & ~(SIZE_4KB - 1);\r
+  if (Address == GetLocalApicBaseAddress ()) {\r
+    return 0;\r
+  }\r
+\r
+  State = MemEncryptSevGetAddressRangeState (\r
+            0,\r
+            MemoryAddress,\r
+            MemoryLength\r
+            );\r
+  if (State == MemEncryptSevAddressRangeUnencrypted) {\r
+    return 0;\r
+  }\r
+\r
+  //\r
+  // Any state other than unencrypted is an error, issue a #GP.\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
+  return GpEvent.Uint64;\r
+}\r
+\r
 /**\r
   Handle an MMIO event.\r
 \r
@@ -653,6 +709,11 @@ MmioExit (
       return UnsupportedExit (Ghcb, Regs, InstructionData);\r
     }\r
 \r
+    Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
+    if (Status != 0) {\r
+      return Status;\r
+    }\r
+\r
     ExitInfo1 = InstructionData->Ext.RmData;\r
     ExitInfo2 = Bytes;\r
     CopyMem (Ghcb->SharedBuffer, &InstructionData->Ext.RegData, Bytes);\r
@@ -683,6 +744,11 @@ MmioExit (
     InstructionData->ImmediateSize = Bytes;\r
     InstructionData->End += Bytes;\r
 \r
+    Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
+    if (Status != 0) {\r
+      return Status;\r
+    }\r
+\r
     ExitInfo1 = InstructionData->Ext.RmData;\r
     ExitInfo2 = Bytes;\r
     CopyMem (Ghcb->SharedBuffer, InstructionData->Immediate, Bytes);\r
@@ -717,6 +783,11 @@ MmioExit (
       return UnsupportedExit (Ghcb, Regs, InstructionData);\r
     }\r
 \r
+    Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
+    if (Status != 0) {\r
+      return Status;\r
+    }\r
+\r
     ExitInfo1 = InstructionData->Ext.RmData;\r
     ExitInfo2 = Bytes;\r
 \r
@@ -748,6 +819,11 @@ MmioExit (
   case 0xB7:\r
     Bytes = (Bytes != 0) ? Bytes : 2;\r
 \r
+    Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
+    if (Status != 0) {\r
+      return Status;\r
+    }\r
+\r
     ExitInfo1 = InstructionData->Ext.RmData;\r
     ExitInfo2 = Bytes;\r
 \r
@@ -774,6 +850,11 @@ MmioExit (
   case 0xBF:\r
     Bytes = (Bytes != 0) ? Bytes : 2;\r
 \r
+    Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);\r
+    if (Status != 0) {\r
+      return Status;\r
+    }\r
+\r
     ExitInfo1 = InstructionData->Ext.RmData;\r
     ExitInfo2 = Bytes;\r
 \r