]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
OvmfPkg/VmgExitLib: Add support for new MMIO MOV opcodes
[mirror_edk2.git] / OvmfPkg / Library / VmgExitLib / VmgExitVcHandler.c
index b716541ad170380c2d0869f23a1b990d471196fa..41b0c8cc531235baac1affda30444cfefc82b00a 100644 (file)
@@ -680,6 +680,7 @@ MmioExit (
   UINTN   Bytes;\r
   UINT64  *Register;\r
   UINT8   OpCode, SignByte;\r
+  UINTN   Address;\r
 \r
   Bytes = 0;\r
 \r
@@ -729,6 +730,57 @@ MmioExit (
     }\r
     break;\r
 \r
+  //\r
+  // MMIO write (MOV moffsetX, aX)\r
+  //\r
+  case 0xA2:\r
+    Bytes = 1;\r
+    //\r
+    // fall through\r
+    //\r
+  case 0xA3:\r
+    Bytes = ((Bytes != 0) ? Bytes :\r
+             (InstructionData->DataSize == Size16Bits) ? 2 :\r
+             (InstructionData->DataSize == Size32Bits) ? 4 :\r
+             (InstructionData->DataSize == Size64Bits) ? 8 :\r
+             0);\r
+\r
+    InstructionData->ImmediateSize = (UINTN) (1 << InstructionData->AddrSize);\r
+    InstructionData->End += InstructionData->ImmediateSize;\r
+\r
+    //\r
+    // This code is X64 only, so a possible 8-byte copy to a UINTN is ok.\r
+    // Use a STATIC_ASSERT to be certain the code is being built as X64.\r
+    //\r
+    STATIC_ASSERT (\r
+      sizeof (UINTN) == sizeof (UINT64),\r
+      "sizeof (UINTN) != sizeof (UINT64), this file must be built as X64"\r
+      );\r
+\r
+    Address = 0;\r
+    CopyMem (\r
+      &Address,\r
+      InstructionData->Immediate,\r
+      InstructionData->ImmediateSize\r
+      );\r
+\r
+    Status = ValidateMmioMemory (Ghcb, Address, Bytes);\r
+    if (Status != 0) {\r
+      return Status;\r
+    }\r
+\r
+    ExitInfo1 = Address;\r
+    ExitInfo2 = Bytes;\r
+    CopyMem (Ghcb->SharedBuffer, &Regs->Rax, Bytes);\r
+\r
+    Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer;\r
+    VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
+    Status = VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);\r
+    if (Status != 0) {\r
+      return Status;\r
+    }\r
+    break;\r
+\r
   //\r
   // MMIO write (MOV reg/memX, immX)\r
   //\r
@@ -811,6 +863,64 @@ MmioExit (
     CopyMem (Register, Ghcb->SharedBuffer, Bytes);\r
     break;\r
 \r
+  //\r
+  // MMIO read (MOV aX, moffsetX)\r
+  //\r
+  case 0xA0:\r
+    Bytes = 1;\r
+    //\r
+    // fall through\r
+    //\r
+  case 0xA1:\r
+    Bytes = ((Bytes != 0) ? Bytes :\r
+             (InstructionData->DataSize == Size16Bits) ? 2 :\r
+             (InstructionData->DataSize == Size32Bits) ? 4 :\r
+             (InstructionData->DataSize == Size64Bits) ? 8 :\r
+             0);\r
+\r
+    InstructionData->ImmediateSize = (UINTN) (1 << InstructionData->AddrSize);\r
+    InstructionData->End += InstructionData->ImmediateSize;\r
+\r
+    //\r
+    // This code is X64 only, so a possible 8-byte copy to a UINTN is ok.\r
+    // Use a STATIC_ASSERT to be certain the code is being built as X64.\r
+    //\r
+    STATIC_ASSERT (\r
+      sizeof (UINTN) == sizeof (UINT64),\r
+      "sizeof (UINTN) != sizeof (UINT64), this file must be built as X64"\r
+      );\r
+\r
+    Address = 0;\r
+    CopyMem (\r
+      &Address,\r
+      InstructionData->Immediate,\r
+      InstructionData->ImmediateSize\r
+      );\r
+\r
+    Status = ValidateMmioMemory (Ghcb, Address, Bytes);\r
+    if (Status != 0) {\r
+      return Status;\r
+    }\r
+\r
+    ExitInfo1 = Address;\r
+    ExitInfo2 = Bytes;\r
+\r
+    Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer;\r
+    VmgSetOffsetValid (Ghcb, GhcbSwScratch);\r
+    Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);\r
+    if (Status != 0) {\r
+      return Status;\r
+    }\r
+\r
+    if (Bytes == 4) {\r
+      //\r
+      // Zero-extend for 32-bit operation\r
+      //\r
+      Regs->Rax = 0;\r
+    }\r
+    CopyMem (&Regs->Rax, Ghcb->SharedBuffer, Bytes);\r
+    break;\r
+\r
   //\r
   // MMIO read w/ zero-extension ((MOVZX regX, reg/memX)\r
   //\r
@@ -888,6 +998,7 @@ MmioExit (
     break;\r
 \r
   default:\r
+    DEBUG ((DEBUG_ERROR, "Invalid MMIO opcode (%x)\n", OpCode));\r
     Status = GP_EXCEPTION;\r
     ASSERT (FALSE);\r
   }\r