[edk2-devel] [PATCH v9 14/46] OvmfPkg/VmgExitLib: Support string IO for IOIO_PROT NAE events

Laszlo Ersek lersek at redhat.com
Wed Jun 10 12:39:50 UTC 2020


On 06/05/20 15:27, Tom Lendacky wrote:
> 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: Jordan Justen <jordan.l.justen at intel.com>
> Cc: Laszlo Ersek <lersek at redhat.com>
> Cc: Ard Biesheuvel <ard.biesheuvel at arm.com>
> Acked-by: Laszlo Ersek <lersek at redhat.com>
> Signed-off-by: Tom Lendacky <thomas.lendacky at amd.com>
> ---
>  OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c | 90 +++++++++++++++++---
>  1 file changed, 76 insertions(+), 14 deletions(-)
> 
> diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
> index 7c2bb12df10a..b74b13045cfd 100644
> --- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
> +++ b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
> @@ -397,6 +397,26 @@ IoioExitInfo (
>    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
>    //
> @@ -445,6 +465,8 @@ IoioExitInfo (
>    //
>    // Single-byte opcodes
>    //
> +  case 0x6C:
> +  case 0x6E:
>    case 0xE4:
>    case 0xE6:
>    case 0xEC:
> @@ -506,30 +528,70 @@ IoioExit (
>    IN     SEV_ES_INSTRUCTION_DATA  *InstructionData
>    )
>  {
> -  UINT64  ExitInfo1, Status;
> +  UINT64   ExitInfo1, ExitInfo2, Status;
> +  BOOLEAN  IsString;
>  
>    ExitInfo1 = IoioExitInfo (Regs, InstructionData);
>    if (ExitInfo1 == 0) {
>      return UnsupportedExit (Ghcb, Regs, InstructionData);
>    }
>  
> -  if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
> -    Ghcb->SaveArea.Rax = 0;
> +  IsString = ((ExitInfo1 & IOIO_TYPE_STR) != 0) ? TRUE : FALSE;
> +  if (IsString) {
> +    UINTN  IoBytes, VmgExitBytes;
> +    UINTN  GhcbCount, OpCount;
> +
> +    Status = 0;
> +
> +    IoBytes = IOIO_DATA_BYTES(ExitInfo1);

(1) missing space before the opening paren, but we're at v9. So my ACK
stands.

Thanks
Laszlo

> +    GhcbCount = sizeof (Ghcb->SharedBuffer) / IoBytes;
> +
> +    OpCount = ((ExitInfo1 & IOIO_REP) != 0) ? Regs->Rcx : 1;
> +    while (OpCount) {
> +      ExitInfo2 = MIN (OpCount, GhcbCount);
> +      VmgExitBytes = ExitInfo2 * IoBytes;
> +
> +      if ((ExitInfo1 & IOIO_TYPE_IN) == 0) {
> +        CopyMem (Ghcb->SharedBuffer, (VOID *) Regs->Rsi, VmgExitBytes);
> +        Regs->Rsi += VmgExitBytes;
> +      }
> +
> +      Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer;
> +      Status = VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, ExitInfo2);
> +      if (Status != 0) {
> +        return Status;
> +      }
> +
> +      if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
> +        CopyMem ((VOID *) Regs->Rdi, Ghcb->SharedBuffer, VmgExitBytes);
> +        Regs->Rdi += VmgExitBytes;
> +      }
> +
> +      if ((ExitInfo1 & IOIO_REP) != 0) {
> +        Regs->Rcx -= ExitInfo2;
> +      }
> +
> +      OpCount -= ExitInfo2;
> +    }
>    } else {
> -    CopyMem (&Ghcb->SaveArea.Rax, &Regs->Rax, IOIO_DATA_BYTES (ExitInfo1));
> -  }
> -  GhcbSetRegValid (Ghcb, GhcbRax);
> +    if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
> +      Ghcb->SaveArea.Rax = 0;
> +    } else {
> +      CopyMem (&Ghcb->SaveArea.Rax, &Regs->Rax, IOIO_DATA_BYTES (ExitInfo1));
> +    }
> +    GhcbSetRegValid (Ghcb, GhcbRax);
>  
> -  Status = VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, 0);
> -  if (Status != 0) {
> -    return Status;
> -  }
> +    Status = VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, 0);
> +    if (Status != 0) {
> +      return Status;
> +    }
>  
> -  if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
> -    if (!GhcbIsRegValid (Ghcb, GhcbRax)) {
> -      return UnsupportedExit (Ghcb, Regs, InstructionData);
> +    if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
> +      if (!GhcbIsRegValid (Ghcb, GhcbRax)) {
> +        return UnsupportedExit (Ghcb, Regs, InstructionData);
> +      }
> +      CopyMem (&Regs->Rax, &Ghcb->SaveArea.Rax, IOIO_DATA_BYTES (ExitInfo1));
>      }
> -    CopyMem (&Regs->Rax, &Ghcb->SaveArea.Rax, IOIO_DATA_BYTES (ExitInfo1));
>    }
>  
>    return 0;
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#61074): https://edk2.groups.io/g/devel/message/61074
Mute This Topic: https://groups.io/mt/74692420/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list