[edk2-devel] [PATCH V1 2/2] OvmfPkg/CcExitLib: Refactor TDX MmioExit

Min Xu min.m.xu at intel.com
Mon Jan 9 01:18:56 UTC 2023


Thanks for the comments. It will be updated in the next version.

> -----Original Message-----
> From: Yao, Jiewen <jiewen.yao at intel.com>
> Sent: Friday, January 6, 2023 4:51 PM
> To: Xu, Min M <min.m.xu at intel.com>; devel at edk2.groups.io
> Cc: Aktas, Erdem <erdemaktas at google.com>; James Bottomley
> <jejb at linux.ibm.com>; Gerd Hoffmann <kraxel at redhat.com>; Tom
> Lendacky <thomas.lendacky at amd.com>; Ryan Afranji <afranji at google.com>
> Subject: RE: [PATCH V1 2/2] OvmfPkg/CcExitLib: Refactor TDX MmioExit
> 
> Thanks for the cleanup.
> Comments inline.
> 
> In general, we need ensure CpuDeadLoop() for *any* parsing error in VE
> handler. Just ASSERT or VmCall(HALT) is not enough, because ASSERT ==
> nothing in release, while VmCall(HALT) is not trusted.
> 
> ASSERT can only be used to handle internal impossible logic, but not input
> from VMM.
> 
> Thank you
> Yao, Jiewen
> 
> > -----Original Message-----
> > From: Xu, Min M <min.m.xu at intel.com>
> > Sent: Thursday, December 29, 2022 4:56 PM
> > To: devel at edk2.groups.io
> > Cc: Xu, Min M <min.m.xu at intel.com>; Aktas, Erdem
> > <erdemaktas at google.com>; James Bottomley <jejb at linux.ibm.com>; Yao,
> > Jiewen <jiewen.yao at intel.com>; Gerd Hoffmann <kraxel at redhat.com>;
> Tom
> > Lendacky <thomas.lendacky at amd.com>; Ryan Afranji
> <afranji at google.com>
> > Subject: [PATCH V1 2/2] OvmfPkg/CcExitLib: Refactor TDX MmioExit
> >
> > From: Min M Xu <min.m.xu at intel.com>
> >
> > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4169
> >
> > The previous TDX MmioExit doesn't handle the Mmio instructions
> > correctly in some scenarios. This patch refactors the implementation
> > to fix the issues.
> >
> > Cc: Erdem Aktas <erdemaktas at google.com>
> > Cc: James Bottomley <jejb at linux.ibm.com>
> > Cc: Jiewen Yao <jiewen.yao at intel.com>
> > Cc: Gerd Hoffmann <kraxel at redhat.com>
> > Cc: Tom Lendacky <thomas.lendacky at amd.com>
> > Cc: Ryan Afranji <afranji at google.com>
> > Reported-by: Ryan Afranji <afranji at google.com>
> > Signed-off-by: Min Xu <min.m.xu at intel.com>
> > ---
> >  OvmfPkg/Library/CcExitLib/CcExitVeHandler.c | 498
> > ++++++++++++++------
> >  1 file changed, 347 insertions(+), 151 deletions(-)
> >
> > diff --git a/OvmfPkg/Library/CcExitLib/CcExitVeHandler.c
> > b/OvmfPkg/Library/CcExitLib/CcExitVeHandler.c
> > index 30d547d5fe55..e0998722af39 100644
> > --- a/OvmfPkg/Library/CcExitLib/CcExitVeHandler.c
> > +++ b/OvmfPkg/Library/CcExitLib/CcExitVeHandler.c
> > @@ -13,6 +13,10 @@
> >  #include <Library/BaseMemoryLib.h>
> >  #include <IndustryStandard/Tdx.h>
> >  #include <IndustryStandard/InstructionParsing.h>
> > +#include "CcInstruction.h"
> > +
> > +#define TDX_MMIO_READ   0
> > +#define TDX_MMIO_WRITE  1
> >
> >  typedef union {
> >    struct {
> > @@ -216,14 +220,15 @@ STATIC
> >  VOID
> >  EFIAPI
> >  TdxDecodeInstruction (
> > -  IN UINT8  *Rip
> > +  IN UINT8   *Rip,
> > +  IN UINT32  Length
> >    )
> >  {
> >    UINTN  i;
> >
> >    DEBUG ((DEBUG_INFO, "TDX: #TD[EPT] instruction (%p):", Rip));
> > -  for (i = 0; i < 15; i++) {
> > -    DEBUG ((DEBUG_INFO, "%02x:", Rip[i]));
> > +  for (i = 0; i < MIN (15, Length); i++) {
> > +    DEBUG ((DEBUG_INFO, "%02x ", Rip[i]));
> >    }
> >
> >    DEBUG ((DEBUG_INFO, "\n"));
> > @@ -235,50 +240,324 @@ TdxDecodeInstruction (
> >      TdVmCall(TDVMCALL_HALT, 0, 0, 0, 0, 0); \
> 
> [Jiewen] Please put CpuDeadLoop() here.
> 
> >    }
> >
> > +/**
> > + * Tdx MMIO access via TdVmcall.
> > + *
> > + * @param MmioSize      Size of the MMIO access
> > + * @param ReadOrWrite   Read or write operation
> > + * @param GuestPA       Guest physical address
> > + * @param Val           Pointer to the value which is read or written
> > +
> > + * @retval EFI_SUCCESS  Successfully access the mmio
> > + * @retval Others       Other errors as indicated
> > + */
> >  STATIC
> > -UINT64 *
> > -EFIAPI
> > -GetRegFromContext (
> > -  IN EFI_SYSTEM_CONTEXT_X64  *Regs,
> > -  IN UINTN                   RegIndex
> > +UINT64
> [Jiewen] According to the return code in the function, I think we need use
> EFI_STATUS here.
> 
> 
> > +TdxMmioReadWrite (
> > +  IN UINT32  MmioSize,
> > +  IN UINT32  ReadOrWrite,
> > +  IN UINT64  GuestPA,
> > +  IN UINT64  *Val
> >    )
> >  {
> > -  switch (RegIndex) {
> > -    case 0: return &Regs->Rax;
> > -      break;
> > -    case 1: return &Regs->Rcx;
> > -      break;
> > -    case 2: return &Regs->Rdx;
> > -      break;
> > -    case 3: return &Regs->Rbx;
> > -      break;
> > -    case 4: return &Regs->Rsp;
> > -      break;
> > -    case 5: return &Regs->Rbp;
> > -      break;
> > -    case 6: return &Regs->Rsi;
> > -      break;
> > -    case 7: return &Regs->Rdi;
> > -      break;
> > -    case 8: return &Regs->R8;
> > -      break;
> > -    case 9: return &Regs->R9;
> > +  UINT64  Status;
> > +
> > +  if ((MmioSize != 1) && (MmioSize != 2) && (MmioSize != 4) &&
> > (MmioSize != 8)) {
> > +    ASSERT (FALSE);
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  if (Val == NULL) {
> > +    ASSERT (FALSE);
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  if (ReadOrWrite == TDX_MMIO_READ) {
> > +    Status = TdVmCall (TDVMCALL_MMIO, MmioSize, TDX_MMIO_READ,
> > GuestPA, 0, Val);
> > +  } else if (ReadOrWrite == TDX_MMIO_WRITE) {
> > +    Status = TdVmCall (TDVMCALL_MMIO, MmioSize, TDX_MMIO_WRITE,
> > GuestPA, *Val, 0);
> > +  } else {
> > +    ASSERT (FALSE);
> > +    Status = EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  return Status;
> > +}
> 
> [Jiewen] I checked error state.
> I think we need add CpuDeadLoo() after TdVmCall(TDVMCALL_HALT) below:
> 
>   if (Status) {
>     DEBUG ((
>       DEBUG_ERROR,
>       "#VE Error (0x%llx) returned from host, ExitReason is %d, ExitQualification
> = 0x%x.\n",
>       Status,
>       ReturnData.VeInfo.ExitReason,
>       ReturnData.VeInfo.ExitQualification.Val
>       ));
> 
>     TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);
>   }
> 
> In general, please CpuDeadLoop() for all TDVMCALL_HALT in CcExitHandleVe()
> 
> 
> > +
> > +typedef struct {
> > +  UINT8                   OpCode;
> > +  UINT32                  Bytes;
> > +  EFI_PHYSICAL_ADDRESS    Address;
> > +  UINT64                  Val;
> > +  UINT64                  *Register;
> > +  UINT32                  ReadOrWrite;
> > +} MMIO_EXIT_PARSED_INSTRUCTION;
> > +
> > +/**
> > + * Parse the MMIO instructions.
> > + *
> > + * @param Regs              Pointer to the EFI_SYSTEM_CONTEXT_X64 which
> > includes the instructions
> > + * @param InstructionData   Pointer to the CC_INSTRUCTION_DATA
> > + * @param ParsedInstruction Pointer to the parsed instruction data
> > + *
> > + * @retval EFI_SUCCESS      Successfully parsed the instructions
> > + * @retval Others           Other error as indicated
> > + */
> > +STATIC
> > +EFI_STATUS
> > +ParseMmioExitInstructions (
> > +  IN OUT EFI_SYSTEM_CONTEXT_X64     *Regs,
> > +  IN OUT CC_INSTRUCTION_DATA        *InstructionData,
> > +  OUT MMIO_EXIT_PARSED_INSTRUCTION  *ParsedInstruction
> > +  )
> > +{
> > +  EFI_STATUS            Status;
> > +  UINT8                 OpCode;
> > +  UINT8                 SignByte;
> > +  UINT32                Bytes;
> > +  EFI_PHYSICAL_ADDRESS  Address;
> > +  UINT64                Val;
> > +  UINT64                *Register;
> > +  UINT32                ReadOrWrite;
> > +
> > +  Address  = 0;
> > +  Bytes    = 0;
> > +  Register = NULL;
> > +  Status   = EFI_SUCCESS;
> > +  Val      = 0;
> > +
> > +  Status = CcInitInstructionData (InstructionData, NULL, Regs);  if
> > + (Status != EFI_SUCCESS) {
> > +    DEBUG ((DEBUG_ERROR, "%a: Initialize InstructionData failed!
> > + (%r)\n",
> > __FUNCTION__, Status));
> > +    ASSERT (FALSE);
> > +    return Status;
> > +  }
> > +
> > +  OpCode = *(InstructionData->OpCodes);  if (OpCode ==
> > + TWO_BYTE_OPCODE_ESCAPE) {
> > +    OpCode = *(InstructionData->OpCodes + 1);  }
> > +
> > +  switch (OpCode) {
> > +    //
> > +    // MMIO write (MOV reg/memX, regX)
> > +    //
> > +    case 0x88:
> > +      Bytes = 1;
> > +    //
> > +    // fall through
> > +    //
> > +    case 0x89:
> > +      CcDecodeModRm (Regs, InstructionData);
> > +      Bytes = ((Bytes != 0) ? Bytes :
> > +               (InstructionData->DataSize == Size16Bits) ? 2 :
> > +               (InstructionData->DataSize == Size32Bits) ? 4 :
> > +               (InstructionData->DataSize == Size64Bits) ? 8 :
> > +               0);
> > +
> > +      if (InstructionData->Ext.ModRm.Mod == 3) {
> > +        DEBUG ((DEBUG_ERROR, "%a: Parse Ext.ModRm.Mod error! (OpCode:
> > 0x%x)\n", __FUNCTION__, OpCode));
> > +        ASSERT (FALSE);
> > +        return EFI_UNSUPPORTED;
> > +      }
> > +
> > +      Address     = InstructionData->Ext.RmData;
> > +      Val         = InstructionData->Ext.RegData;
> > +      ReadOrWrite = TDX_MMIO_WRITE;
> > +
> >        break;
> > -    case 10: return &Regs->R10;
> > +
> > +    //
> > +    // MMIO write (MOV moffsetX, aX)
> > +    //
> > +    case 0xA2:
> > +      Bytes = 1;
> > +    //
> > +    // fall through
> > +    //
> > +    case 0xA3:
> > +      Bytes = ((Bytes != 0) ? Bytes :
> > +               (InstructionData->DataSize == Size16Bits) ? 2 :
> > +               (InstructionData->DataSize == Size32Bits) ? 4 :
> > +               (InstructionData->DataSize == Size64Bits) ? 8 :
> > +               0);
> > +
> > +      InstructionData->ImmediateSize = (UINTN)(1 << InstructionData-
> > >AddrSize);
> > +      InstructionData->End          += InstructionData->ImmediateSize;
> > +      CopyMem (&Address, InstructionData->Immediate, InstructionData-
> > >ImmediateSize);
> > +
> > +      Val         = Regs->Rax;
> > +      ReadOrWrite = TDX_MMIO_WRITE;
> >        break;
> > -    case 11: return &Regs->R11;
> > +
> > +    //
> > +    // MMIO write (MOV reg/memX, immX)
> > +    //
> > +    case 0xC6:
> > +      Bytes = 1;
> > +    //
> > +    // fall through
> > +    //
> > +    case 0xC7:
> > +      CcDecodeModRm (Regs, InstructionData);
> > +      Bytes = ((Bytes != 0) ? Bytes :
> > +               (InstructionData->DataSize == Size16Bits) ? 2 :
> > +               (InstructionData->DataSize == Size32Bits) ? 4 :
> > +               (InstructionData->DataSize == Size64Bits) ? 8 :
> > +               0);
> > +
> > +      InstructionData->ImmediateSize = Bytes;
> > +      InstructionData->End          += Bytes;
> > +
> > +      Val = 0;
> > +      CopyMem (&Val, InstructionData->Immediate, InstructionData-
> > >ImmediateSize);
> > +
> > +      Address     = InstructionData->Ext.RmData;
> > +      ReadOrWrite = TDX_MMIO_WRITE;
> > +
> >        break;
> > -    case 12: return &Regs->R12;
> > +
> > +    //
> > +    // MMIO read (MOV regX, reg/memX)
> > +    //
> > +    case 0x8A:
> > +      Bytes = 1;
> > +    //
> > +    // fall through
> > +    //
> > +    case 0x8B:
> > +      CcDecodeModRm (Regs, InstructionData);
> > +      Bytes = ((Bytes != 0) ? Bytes :
> > +               (InstructionData->DataSize == Size16Bits) ? 2 :
> > +               (InstructionData->DataSize == Size32Bits) ? 4 :
> > +               (InstructionData->DataSize == Size64Bits) ? 8 :
> > +               0);
> > +      if (InstructionData->Ext.ModRm.Mod == 3) {
> > +        //
> > +        // NPF on two register operands???
> > +        //
> > +        DEBUG ((DEBUG_ERROR, "%a: Parse Ext.ModRm.Mod error! (OpCode:
> > 0x%x)\n", __FUNCTION__, OpCode));
> > +        ASSERT (FALSE);
> 
> [Jiewen] I am not sure if it is useful to put ASSERT here.
> If this is possible case, but we don't want to support, just return
> UNSUPPORTED without ASSERT.
> It will cause CpuDeadLoop() later anyway.
> 
> 
> > +        return EFI_UNSUPPORTED;
> > +      }
> > +
> > +      Address     = InstructionData->Ext.RmData;
> > +      ReadOrWrite = TDX_MMIO_READ;
> > +
> > +      Register = CcGetRegisterPointer (Regs, InstructionData-
> >Ext.ModRm.Reg);
> > +      if (Bytes == 4) {
> > +        //
> > +        // Zero-extend for 32-bit operation
> > +        //
> > +        *Register = 0;
> > +      }
> > +
> >        break;
> > -    case 13: return &Regs->R13;
> > +
> > +    //
> > +    // MMIO read (MOV aX, moffsetX)
> > +    //
> > +    case 0xA0:
> > +      Bytes = 1;
> > +    //
> > +    // fall through
> > +    //
> > +    case 0xA1:
> > +      Bytes = ((Bytes != 0) ? Bytes :
> > +               (InstructionData->DataSize == Size16Bits) ? 2 :
> > +               (InstructionData->DataSize == Size32Bits) ? 4 :
> > +               (InstructionData->DataSize == Size64Bits) ? 8 :
> > +               0);
> > +
> > +      InstructionData->ImmediateSize = (UINTN)(1 << InstructionData-
> > >AddrSize);
> > +      InstructionData->End          += InstructionData->ImmediateSize;
> > +
> > +      Address = 0;
> > +      CopyMem (
> > +        &Address,
> > +        InstructionData->Immediate,
> > +        InstructionData->ImmediateSize
> > +        );
> > +
> > +      if (Bytes == 4) {
> > +        //
> > +        // Zero-extend for 32-bit operation
> > +        //
> > +        Regs->Rax = 0;
> > +      }
> > +
> > +      Register    = &Regs->Rax;
> > +      ReadOrWrite = TDX_MMIO_READ;
> > +
> >        break;
> > -    case 14: return &Regs->R14;
> > +
> > +    //
> > +    // MMIO read w/ zero-extension ((MOVZX regX, reg/memX)
> > +    //
> > +    case 0xB6:
> > +      Bytes = 1;
> > +    //
> > +    // fall through
> > +    //
> > +    case 0xB7:
> > +      CcDecodeModRm (Regs, InstructionData);
> > +      Bytes   = (Bytes != 0) ? Bytes : 2;
> > +      Address = InstructionData->Ext.RmData;
> > +
> > +      Register = CcGetRegisterPointer (Regs, InstructionData-
> >Ext.ModRm.Reg);
> > +      SetMem (Register, (UINTN)(1 << InstructionData->DataSize), 0);
> > +
> > +      ReadOrWrite = TDX_MMIO_READ;
> > +
> >        break;
> > -    case 15: return &Regs->R15;
> > +
> > +    //
> > +    // MMIO read w/ sign-extension (MOVSX regX, reg/memX)
> > +    //
> > +    case 0xBE:
> > +      Bytes = 1;
> > +    //
> > +    // fall through
> > +    //
> > +    case 0xBF:
> > +      CcDecodeModRm (Regs, InstructionData);
> > +      Bytes = (Bytes != 0) ? Bytes : 2;
> > +
> > +      Address = InstructionData->Ext.RmData;
> > +
> > +      if (Bytes == 1) {
> > +        UINT8  *Data;
> > +        Data     = (UINT8 *)&Val;
> > +        SignByte = ((*Data & BIT7) != 0) ? 0xFF : 0x00;
> > +      } else {
> > +        UINT16  *Data;
> > +        Data     = (UINT16 *)&Val;
> > +        SignByte = ((*Data & BIT15) != 0) ? 0xFF : 0x00;
> > +      }
> > +
> > +      Register = CcGetRegisterPointer (Regs, InstructionData-
> >Ext.ModRm.Reg);
> > +      SetMem (Register, (UINTN)(1 << InstructionData->DataSize),
> > + SignByte);
> > +
> > +      ReadOrWrite = TDX_MMIO_READ;
> > +
> >        break;
> > +
> > +    default:
> > +      DEBUG ((DEBUG_ERROR, "%a: Invalid MMIO opcode (%x)\n",
> > __FUNCTION__, OpCode));
> > +      Status = EFI_UNSUPPORTED;
> > +      ASSERT (FALSE);
> > +  }
> > +
> > +  if (!EFI_ERROR (Status)) {
> > +    ParsedInstruction->OpCode      = OpCode;
> > +    ParsedInstruction->Address     = Address;
> > +    ParsedInstruction->Bytes       = Bytes;
> > +    ParsedInstruction->Register    = Register;
> > +    ParsedInstruction->Val         = Val;
> > +    ParsedInstruction->ReadOrWrite = ReadOrWrite;
> >    }
> >
> > -  return NULL;
> > +  return Status;
> >  }
> >
> >  /**
> > @@ -300,25 +579,13 @@ MmioExit (
> >    IN TDCALL_VEINFO_RETURN_DATA   *Veinfo
> >    )
> >  {
> > -  UINT64          Status;
> > -  UINT32          MmioSize;
> > -  UINT32          RegSize;
> > -  UINT8           OpCode;
> > -  BOOLEAN         SeenRex;
> > -  UINT64          *Reg;
> > -  UINT8           *Rip;
> > -  UINT64          Val;
> > -  UINT32          OpSize;
> > -  MODRM           ModRm;
> > -  REX             Rex;
> > -  TD_RETURN_DATA  TdReturnData;
> > -  UINT8           Gpaw;
> > -  UINT64          TdSharedPageMask;
> > -
> > -  Rip     = (UINT8 *)Regs->Rip;
> > -  Val     = 0;
> > -  Rex.Val = 0;
> > -  SeenRex = FALSE;
> > +  UINT64                        Status;
> > +  TD_RETURN_DATA                TdReturnData;
> > +  UINT8                         Gpaw;
> > +  UINT64                        Val;
> > +  UINT64                        TdSharedPageMask;
> > +  CC_INSTRUCTION_DATA           InstructionData;
> > +  MMIO_EXIT_PARSED_INSTRUCTION  ParsedInstruction;
> >
> >    Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);
> >    if (Status == TDX_EXIT_REASON_SUCCESS) { @@ -335,112 +602,41 @@
> > MmioExit (
> >      CpuDeadLoop ();
> >    }
> >
> > -  //
> > -  // Default to 32bit transfer
> > -  //
> > -  OpSize = 4;
> > +  Status = ParseMmioExitInstructions (Regs, &InstructionData,
> > &ParsedInstruction);
> > +  if (Status != EFI_SUCCESS) {
> > +    return Status;
> > +  }
> >
> > -  do {
> > -    OpCode = *Rip++;
> > -    if (OpCode == 0x66) {
> > -      OpSize = 2;
> > -    } else if ((OpCode == 0x64) || (OpCode == 0x65) || (OpCode == 0x67)) {
> > -      continue;
> > -    } else if ((OpCode >= 0x40) && (OpCode <= 0x4f)) {
> > -      SeenRex = TRUE;
> > -      Rex.Val = OpCode;
> > -    } else {
> > -      break;
> > +  if (Veinfo->GuestPA != (ParsedInstruction.Address | TdSharedPageMask))
> {
> > +    DEBUG ((
> > +      DEBUG_ERROR,
> > +      "%a: Address is not correct! (%d: 0x%llx != 0x%llx)\n",
> > +      __FUNCTION__,
> > +      ParsedInstruction.OpCode,
> > +      Veinfo->GuestPA,
> > +      ParsedInstruction.Address
> > +      ));
> > +    ASSERT (FALSE);
> [Jiewen] Not sure if ASSERT here is useful. We should DeadLoop() later.
> 
> > +    return EFI_ABORTED;
> > +  }
> > +
> > +  if (ParsedInstruction.ReadOrWrite == TDX_MMIO_WRITE ) {
> > +    Status = TdxMmioReadWrite (ParsedInstruction.Bytes,
> > TDX_MMIO_WRITE, Veinfo->GuestPA, &ParsedInstruction.Val);
> > +  } else {
> > +    Val    = 0;
> > +    Status = TdxMmioReadWrite (ParsedInstruction.Bytes,
> > + TDX_MMIO_READ,
> > Veinfo->GuestPA, &Val);
> > +    if (Status == 0) {
> > +      CopyMem (ParsedInstruction.Register, &Val,
> > + ParsedInstruction.Bytes);
> >      }
> > -  } while (TRUE);
> > -
> > -  //
> > -  // We need to have at least 2 more bytes for this instruction
> > -  //
> > -  TDX_DECODER_BUG_ON (((UINT64)Rip - Regs->Rip) > 13);
> [Jiewen] We need make sure it will DeadLoop() if TDX_DECODER_BUG_ON is
> ON.
> 
> > -
> > -  OpCode = *Rip++;
> > -  //
> > -  // Two-byte opecode, get next byte
> > -  //
> > -  if (OpCode == 0x0F) {
> > -    OpCode = *Rip++;
> > -  }
> > -
> > -  switch (OpCode) {
> > -    case 0x88:
> > -    case 0x8A:
> > -    case 0xB6:
> > -      MmioSize = 1;
> > -      break;
> > -    case 0xB7:
> > -      MmioSize = 2;
> > -      break;
> > -    default:
> > -      MmioSize = Rex.Bits.W ? 8 : OpSize;
> > -      break;
> > -  }
> > -
> > -  /* Punt on AH/BH/CH/DH unless it shows up. */
> > -  ModRm.Val = *Rip++;
> > -  TDX_DECODER_BUG_ON (MmioSize == 1 && ModRm.Bits.Reg > 4
> && !SeenRex
> > && OpCode != 0xB6);
> > -  Reg = GetRegFromContext (Regs, ModRm.Bits.Reg | ((int)Rex.Bits.R <<
> > 3));
> > -  TDX_DECODER_BUG_ON (!Reg);
> > -
> > -  if (ModRm.Bits.Rm == 4) {
> > -    ++Rip; /* SIB byte */
> > -  }
> > -
> > -  if ((ModRm.Bits.Mod == 2) || ((ModRm.Bits.Mod == 0) &&
> > (ModRm.Bits.Rm == 5))) {
> > -    Rip += 4; /* DISP32 */
> > -  } else if (ModRm.Bits.Mod == 1) {
> > -    ++Rip;  /* DISP8 */
> > -  }
> > -
> > -  switch (OpCode) {
> > -    case 0x88:
> > -    case 0x89:
> > -      CopyMem ((void *)&Val, Reg, MmioSize);
> > -      Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA,
> > Val, 0);
> > -      break;
> > -    case 0xC7:
> > -      CopyMem ((void *)&Val, Rip, OpSize);
> > -      Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 1, Veinfo->GuestPA,
> > Val, 0);
> > -      Rip   += OpSize;
> > -    default:
> > -      //
> > -      // 32-bit write registers are zero extended to the full register
> > -      // Hence 'MOVZX r[32/64], r/m16' is
> > -      // hardcoded to reg size 8, and the straight MOV case has a reg
> > -      // size of 8 in the 32-bit read case.
> > -      //
> > -      switch (OpCode) {
> > -        case 0xB6:
> > -          RegSize = Rex.Bits.W ? 8 : OpSize;
> > -          break;
> > -        case 0xB7:
> > -          RegSize =  8;
> > -          break;
> > -        default:
> > -          RegSize = MmioSize == 4 ? 8 : MmioSize;
> > -          break;
> > -      }
> > -
> > -      Status = TdVmCall (TDVMCALL_MMIO, MmioSize, 0, Veinfo->GuestPA,
> 0,
> > &Val);
> > -      if (Status == 0) {
> [Jiewen] Status is EFI_STATUS. We need use !EFI_ERROR(Status)
> 
> 
> > -        ZeroMem (Reg, RegSize);
> > -        CopyMem (Reg, (void *)&Val, MmioSize);
> > -      }
> >    }
> >
> >    if (Status == 0) {
> [Jiewen] Status is EFI_STATUS. We need use !EFI_ERROR(Status)
> 
> 
> > -    TDX_DECODER_BUG_ON (((UINT64)Rip - Regs->Rip) > 15);
> > -
> >      //
> >      // We change instruction length to reflect true size so handler can
> >      // bump rip
> >      //
> > -    Veinfo->ExitInstructionLength =  (UINT32)((UINT64)Rip - Regs->Rip);
> > +    Veinfo->ExitInstructionLength =  (UINT32)(CcInstructionLength
> > (&InstructionData));
> > +    TdxDecodeInstruction ((UINT8 *)Regs->Rip, Veinfo-
> > >ExitInstructionLength);
> >    }
> >
> >    return Status;
> > --
> > 2.29.2.windows.2



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#98158): https://edk2.groups.io/g/devel/message/98158
Mute This Topic: https://groups.io/mt/95934165/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