ExitInfo = 0;\r
\r
switch (*(InstructionData->OpCodes)) {\r
+ //\r
+ // INS opcodes\r
+ //\r
+ case 0x6C:\r
+ case 0x6D:\r
+ ExitInfo |= IOIO_TYPE_INS;\r
+ ExitInfo |= IOIO_SEG_ES;\r
+ ExitInfo |= ((Regs->Rdx & 0xffff) << 16);\r
+ break;\r
+\r
+ //\r
+ // OUTS opcodes\r
+ //\r
+ case 0x6E:\r
+ case 0x6F:\r
+ ExitInfo |= IOIO_TYPE_OUTS;\r
+ ExitInfo |= IOIO_SEG_DS;\r
+ ExitInfo |= ((Regs->Rdx & 0xffff) << 16);\r
+ break;\r
+\r
//\r
// IN immediate opcodes\r
//\r
//\r
// Single-byte opcodes\r
//\r
+ case 0x6C:\r
+ case 0x6E:\r
case 0xE4:\r
case 0xE6:\r
case 0xEC:\r
IN SEV_ES_INSTRUCTION_DATA *InstructionData\r
)\r
{\r
- UINT64 ExitInfo1, Status;\r
+ UINT64 ExitInfo1, ExitInfo2, Status;\r
+ BOOLEAN IsString;\r
\r
ExitInfo1 = IoioExitInfo (Regs, InstructionData);\r
if (ExitInfo1 == 0) {\r
return UnsupportedExit (Ghcb, Regs, InstructionData);\r
}\r
\r
- if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {\r
- Ghcb->SaveArea.Rax = 0;\r
+ IsString = ((ExitInfo1 & IOIO_TYPE_STR) != 0) ? TRUE : FALSE;\r
+ if (IsString) {\r
+ UINTN IoBytes, VmgExitBytes;\r
+ UINTN GhcbCount, OpCount;\r
+\r
+ Status = 0;\r
+\r
+ IoBytes = IOIO_DATA_BYTES (ExitInfo1);\r
+ GhcbCount = sizeof (Ghcb->SharedBuffer) / IoBytes;\r
+\r
+ OpCount = ((ExitInfo1 & IOIO_REP) != 0) ? Regs->Rcx : 1;\r
+ while (OpCount != 0) {\r
+ ExitInfo2 = MIN (OpCount, GhcbCount);\r
+ VmgExitBytes = ExitInfo2 * IoBytes;\r
+\r
+ if ((ExitInfo1 & IOIO_TYPE_IN) == 0) {\r
+ CopyMem (Ghcb->SharedBuffer, (VOID *) Regs->Rsi, VmgExitBytes);\r
+ Regs->Rsi += VmgExitBytes;\r
+ }\r
+\r
+ Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer;\r
+ Status = VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, ExitInfo2);\r
+ if (Status != 0) {\r
+ return Status;\r
+ }\r
+\r
+ if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {\r
+ CopyMem ((VOID *) Regs->Rdi, Ghcb->SharedBuffer, VmgExitBytes);\r
+ Regs->Rdi += VmgExitBytes;\r
+ }\r
+\r
+ if ((ExitInfo1 & IOIO_REP) != 0) {\r
+ Regs->Rcx -= ExitInfo2;\r
+ }\r
+\r
+ OpCount -= ExitInfo2;\r
+ }\r
} else {\r
- CopyMem (&Ghcb->SaveArea.Rax, &Regs->Rax, IOIO_DATA_BYTES (ExitInfo1));\r
- }\r
- GhcbSetRegValid (Ghcb, GhcbRax);\r
+ if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {\r
+ Ghcb->SaveArea.Rax = 0;\r
+ } else {\r
+ CopyMem (&Ghcb->SaveArea.Rax, &Regs->Rax, IOIO_DATA_BYTES (ExitInfo1));\r
+ }\r
+ GhcbSetRegValid (Ghcb, GhcbRax);\r
\r
- Status = VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, 0);\r
- if (Status != 0) {\r
- return Status;\r
- }\r
+ Status = VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, 0);\r
+ if (Status != 0) {\r
+ return Status;\r
+ }\r
\r
- if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {\r
- if (!GhcbIsRegValid (Ghcb, GhcbRax)) {\r
- return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+ if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {\r
+ if (!GhcbIsRegValid (Ghcb, GhcbRax)) {\r
+ return UnsupportedExit (Ghcb, Regs, InstructionData);\r
+ }\r
+ CopyMem (&Regs->Rax, &Ghcb->SaveArea.Rax, IOIO_DATA_BYTES (ExitInfo1));\r
}\r
- CopyMem (&Regs->Rax, &Ghcb->SaveArea.Rax, IOIO_DATA_BYTES (ExitInfo1));\r
}\r
\r
return 0;\r