Re: [kvm-unit-tests PATCH v2 09/10] x86: AMD SEV-ES: Handle IOIO #VC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Feb 9, 2022 at 8:44 AM Varad Gautam <varad.gautam@xxxxxxxx> wrote:
>
> Using Linux's IOIO #VC processing logic.
>
> Signed-off-by: Varad Gautam <varad.gautam@xxxxxxxx>
> ---
>  lib/x86/amd_sev_vc.c | 146 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 146 insertions(+)
>
> diff --git a/lib/x86/amd_sev_vc.c b/lib/x86/amd_sev_vc.c
> index 401cb29..88c95e1 100644
> --- a/lib/x86/amd_sev_vc.c
> +++ b/lib/x86/amd_sev_vc.c
> @@ -172,6 +172,149 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
>         return ret;
>  }
>
> +#define IOIO_TYPE_STR  BIT(2)
> +#define IOIO_TYPE_IN   1
> +#define IOIO_TYPE_INS  (IOIO_TYPE_IN | IOIO_TYPE_STR)
> +#define IOIO_TYPE_OUT  0
> +#define IOIO_TYPE_OUTS (IOIO_TYPE_OUT | IOIO_TYPE_STR)
> +
> +#define IOIO_REP       BIT(3)
> +
> +#define IOIO_ADDR_64   BIT(9)
> +#define IOIO_ADDR_32   BIT(8)
> +#define IOIO_ADDR_16   BIT(7)
> +
> +#define IOIO_DATA_32   BIT(6)
> +#define IOIO_DATA_16   BIT(5)
> +#define IOIO_DATA_8    BIT(4)
> +
> +#define IOIO_SEG_ES    (0 << 10)
> +#define IOIO_SEG_DS    (3 << 10)
> +
> +static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo)
> +{
> +       struct insn *insn = &ctxt->insn;
> +       *exitinfo = 0;
> +
> +       switch (insn->opcode.bytes[0]) {
> +       /* INS opcodes */
> +       case 0x6c:
> +       case 0x6d:
> +               *exitinfo |= IOIO_TYPE_INS;
> +               *exitinfo |= IOIO_SEG_ES;
> +               *exitinfo |= (ctxt->regs->rdx & 0xffff) << 16;
> +               break;
> +
> +       /* OUTS opcodes */
> +       case 0x6e:
> +       case 0x6f:
> +               *exitinfo |= IOIO_TYPE_OUTS;
> +               *exitinfo |= IOIO_SEG_DS;
> +               *exitinfo |= (ctxt->regs->rdx & 0xffff) << 16;
> +               break;
> +
> +       /* IN immediate opcodes */
> +       case 0xe4:
> +       case 0xe5:
> +               *exitinfo |= IOIO_TYPE_IN;
> +               *exitinfo |= (u8)insn->immediate.value << 16;
> +               break;
> +
> +       /* OUT immediate opcodes */
> +       case 0xe6:
> +       case 0xe7:
> +               *exitinfo |= IOIO_TYPE_OUT;
> +               *exitinfo |= (u8)insn->immediate.value << 16;
> +               break;
> +
> +       /* IN register opcodes */
> +       case 0xec:
> +       case 0xed:
> +               *exitinfo |= IOIO_TYPE_IN;
> +               *exitinfo |= (ctxt->regs->rdx & 0xffff) << 16;
> +               break;
> +
> +       /* OUT register opcodes */
> +       case 0xee:
> +       case 0xef:
> +               *exitinfo |= IOIO_TYPE_OUT;
> +               *exitinfo |= (ctxt->regs->rdx & 0xffff) << 16;
> +               break;
> +
> +       default:
> +               return ES_DECODE_FAILED;
> +       }
> +
> +       switch (insn->opcode.bytes[0]) {
> +       case 0x6c:
> +       case 0x6e:
> +       case 0xe4:
> +       case 0xe6:
> +       case 0xec:
> +       case 0xee:
> +               /* Single byte opcodes */
> +               *exitinfo |= IOIO_DATA_8;
> +               break;
> +       default:
> +               /* Length determined by instruction parsing */
> +               *exitinfo |= (insn->opnd_bytes == 2) ? IOIO_DATA_16
> +                                                    : IOIO_DATA_32;
> +       }
> +       switch (insn->addr_bytes) {
> +       case 2:
> +               *exitinfo |= IOIO_ADDR_16;
> +               break;
> +       case 4:
> +               *exitinfo |= IOIO_ADDR_32;
> +               break;
> +       case 8:
> +               *exitinfo |= IOIO_ADDR_64;
> +               break;
> +       }
> +
> +       if (insn_has_rep_prefix(insn))
> +               *exitinfo |= IOIO_REP;
> +
> +       return ES_OK;
> +}
> +
> +static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
> +{
> +       struct ex_regs *regs = ctxt->regs;
> +       u64 exit_info_1;
> +       enum es_result ret;
> +
> +       ret = vc_ioio_exitinfo(ctxt, &exit_info_1);
> +       if (ret != ES_OK)
> +               return ret;
> +
> +       if (exit_info_1 & IOIO_TYPE_STR) {
> +               ret = ES_VMM_ERROR;
> +       } else {
> +               /* IN/OUT into/from rAX */
> +
> +               int bits = (exit_info_1 & 0x70) >> 1;
> +               u64 rax = 0;
> +
> +               if (!(exit_info_1 & IOIO_TYPE_IN))
> +                       rax = lower_bits(regs->rax, bits);
> +
> +               ghcb_set_rax(ghcb, rax);
> +
> +               ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_IOIO, exit_info_1, 0);
> +               if (ret != ES_OK)
> +                       return ret;
> +
> +               if (exit_info_1 & IOIO_TYPE_IN) {
> +                       if (!ghcb_rax_is_valid(ghcb))
> +                               return ES_VMM_ERROR;
> +                       regs->rax = lower_bits(ghcb->save.rax, bits);
> +               }
> +       }
> +
> +       return ret;
> +}
> +
>  static enum es_result vc_handle_exitcode(struct es_em_ctxt *ctxt,
>                                          struct ghcb *ghcb,
>                                          unsigned long exit_code)
> @@ -185,6 +328,9 @@ static enum es_result vc_handle_exitcode(struct es_em_ctxt *ctxt,
>         case SVM_EXIT_MSR:
>                 result = vc_handle_msr(ghcb, ctxt);
>                 break;
> +       case SVM_EXIT_IOIO:
> +               result = vc_handle_ioio(ghcb, ctxt);
> +               break;
>         default:
>                 /*
>                  * Unexpected #VC exception
> --
> 2.32.0
>

Reviewed-by: Marc Orr <marcorr@xxxxxxxxxx>



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux