From: Tom Lendacky <thomas.lendacky@amd.com>
Add support to the #VC exception handler to handle string IO. This
requires expanding the IO instruction parsing to recognize string based
IO instructions as well as preparing an un-encrypted buffer to be used
to transfer (either to or from the guest) the string contents for the IO
operation. The SW_EXITINFO2 and SW_SCRATCH fields of the GHCB are set
appropriately for the operation. Multiple VMGEXIT invocations may be
needed to complete the string IO operation.
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
.../X64/AMDSevVcCommon.c | 92 ++++++++++++++++---
1 file changed, 80 insertions(+), 12 deletions(-)
diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c
index 3b69aca48055..2bc156840e74 100644
--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c
+++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/AMDSevVcCommon.c
@@ -278,6 +278,34 @@ IoioExitInfo (
UINT64 ExitInfo = 0;
switch (*(InstructionData->OpCodes)) {
+ case 0x6C: /* INSB / INS mem8, DX */
+ ExitInfo |= IOIO_TYPE_INS;
+ ExitInfo |= IOIO_DATA_8;
+ ExitInfo |= IOIO_SEG_ES;
+ ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
+ break;
+ case 0x6D: /* INSW / INS mem16, DX / INSD / INS mem32, DX */
+ ExitInfo |= IOIO_TYPE_INS;
+ ExitInfo |= (InstructionData->DataSize == Size16Bits) ? IOIO_DATA_16
+ : IOIO_DATA_32;
+ ExitInfo |= IOIO_SEG_ES;
+ ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
+ break;
+
+ case 0x6E: /* OUTSB / OUTS DX, mem8 */
+ ExitInfo |= IOIO_TYPE_OUTS;
+ ExitInfo |= IOIO_DATA_8;
+ ExitInfo |= IOIO_SEG_DS;
+ ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
+ break;
+ case 0x6F: /* OUTSW / OUTS DX, mem16 / OUTSD / OUTS DX, mem32 */
+ ExitInfo |= IOIO_TYPE_OUTS;
+ ExitInfo |= (InstructionData->DataSize == Size16Bits) ? IOIO_DATA_16
+ : IOIO_DATA_32;
+ ExitInfo |= IOIO_SEG_DS;
+ ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
+ break;
+
case 0xE4: /* IN AL, imm8 */
InstructionData->ImmediateSize = 1;
InstructionData->End++;
@@ -370,8 +398,9 @@ IoioExit (
SEV_ES_INSTRUCTION_DATA *InstructionData
)
{
- UINT64 ExitInfo1;
- UINTN Status;
+ UINT64 ExitInfo1, ExitInfo2;
+ UINTN Status;
+ BOOLEAN String;
ExitInfo1 = IoioExitInfo (Regs, InstructionData);
if (!ExitInfo1) {
@@ -389,17 +418,56 @@ IoioExit (
Ghcb->SaveArea.Rax = Regs->Rax;
GhcbSetRegValid (Ghcb, GhcbRax);
- Status = VmgExit (Ghcb, SvmExitIoioProt, ExitInfo1, 0);
- if (Status) {
- return Status;
- }
-
- if (ExitInfo1 & IOIO_TYPE_IN) {
- if (!GhcbIsRegValid (Ghcb, GhcbRax)) {
- VmgExit (Ghcb, SvmExitUnsupported, SvmExitIoioProt, 0);
- ASSERT (0);
+ String = (ExitInfo1 & IOIO_TYPE_STR) ? TRUE : FALSE;
+ if (String) {
+ UINTN IoBytes, VmgExitBytes;
+ UINTN GhcbCount, OpCount;
+
+ Status = 0;
+
+ IoBytes = (ExitInfo1 >> 4) & 0x7;
+ GhcbCount = sizeof (Ghcb->SharedBuffer) / IoBytes;
+
+ OpCount = (ExitInfo1 & IOIO_REP) ? Regs->Rcx : 1;
+ while (OpCount) {
+ ExitInfo2 = MIN (OpCount, GhcbCount);
+ VmgExitBytes = ExitInfo2 * IoBytes;
+
+ if (!(ExitInfo1 & IOIO_TYPE_IN)) {
+ CopyMem (Ghcb->SharedBuffer, (VOID *) Regs->Rsi, VmgExitBytes);
+ Regs->Rsi += VmgExitBytes;
+ }
+
+ Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer;
+ Status = VmgExit (Ghcb, SvmExitIoioProt, ExitInfo1, ExitInfo2);
+ if (Status) {
+ return Status;
+ }
+
+ if (ExitInfo1 & IOIO_TYPE_IN) {
+ CopyMem ((VOID *) Regs->Rdi, Ghcb->SharedBuffer, VmgExitBytes);
+ Regs->Rdi += VmgExitBytes;
+ }
+
+ if (ExitInfo1 & IOIO_REP) {
+ Regs->Rcx -= ExitInfo2;
+ }
+
+ OpCount -= ExitInfo2;
+ }
+ } else {
+ Status = VmgExit (Ghcb, SvmExitIoioProt, ExitInfo1, 0);
+ if (Status) {
+ return Status;
+ }
+
+ if (ExitInfo1 & IOIO_TYPE_IN) {
+ if (!GhcbIsRegValid (Ghcb, GhcbRax)) {
+ VmgExit (Ghcb, SvmExitUnsupported, SvmExitIoioProt, 0);
+ ASSERT (0);
+ }
+ Regs->Rax = Ghcb->SaveArea.Rax;
}
- Regs->Rax = Ghcb->SaveArea.Rax;
}
return 0;
--
2.17.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#46106): https://edk2.groups.io/g/devel/message/46106
Mute This Topic: https://groups.io/mt/32966278/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-