BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198
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. Cc: Eric Dong <eric.d...@intel.com> Cc: Ray Ni <ray...@intel.com> Cc: Laszlo Ersek <ler...@redhat.com> Signed-off-by: Tom Lendacky <thomas.lenda...@amd.com> --- .../X64/ArchAMDSevVcHandler.c | 78 ++++++++++++++++--- 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchAMDSevVcHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchAMDSevVcHandler.c index eb7b776859c1..28adf0d5e9c4 100644 --- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchAMDSevVcHandler.c +++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchAMDSevVcHandler.c @@ -321,6 +321,22 @@ IoioExitInfo ( UINT64 ExitInfo = 0; switch (*(InstructionData->OpCodes)) { + // INS opcodes + case 0x6C: + case 0x6D: + ExitInfo |= IOIO_TYPE_INS; + ExitInfo |= IOIO_SEG_ES; + ExitInfo |= ((Regs->Rdx & 0xffff) << 16); + break; + + // OUTS opcodes + case 0x6E: + case 0x6F: + ExitInfo |= IOIO_TYPE_OUTS; + ExitInfo |= IOIO_SEG_DS; + ExitInfo |= ((Regs->Rdx & 0xffff) << 16); + break; + // IN immediate opcodes case 0xE4: case 0xE5: @@ -358,6 +374,8 @@ IoioExitInfo ( } switch (*(InstructionData->OpCodes)) { + case 0x6C: + case 0x6E: case 0xE4: case 0xE6: case 0xEC: @@ -404,7 +422,8 @@ IoioExit ( SEV_ES_INSTRUCTION_DATA *InstructionData ) { - UINT64 ExitInfo1, Status; + UINT64 ExitInfo1, ExitInfo2, Status; + BOOLEAN String; ExitInfo1 = IoioExitInfo (Regs, InstructionData); if (!ExitInfo1) { @@ -421,16 +440,55 @@ 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)) { - return UnsupportedExit (Ghcb, Regs, InstructionData); + 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)) { + return UnsupportedExit (Ghcb, Regs, InstructionData); + } + 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 (#55252): https://edk2.groups.io/g/devel/message/55252 Mute This Topic: https://groups.io/mt/71687803/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-