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 | 108 ++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 106 insertions(+), 2 deletions(-) > > diff --git a/lib/x86/amd_sev_vc.c b/lib/x86/amd_sev_vc.c > index 88c95e1..c79d9be 100644 > --- a/lib/x86/amd_sev_vc.c > +++ b/lib/x86/amd_sev_vc.c > @@ -278,10 +278,46 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo) > return ES_OK; > } > > +static enum es_result vc_insn_string_read(struct es_em_ctxt *ctxt, > + void *src, unsigned char *buf, > + unsigned int data_size, > + unsigned int count, > + bool backwards) > +{ > + int i, b = backwards ? -1 : 1; > + > + for (i = 0; i < count; i++) { > + void *s = src + (i * data_size * b); > + unsigned char *d = buf + (i * data_size); > + > + memcpy(d, s, data_size); > + } > + > + return ES_OK; > +} > + > +static enum es_result vc_insn_string_write(struct es_em_ctxt *ctxt, > + void *dst, unsigned char *buf, > + unsigned int data_size, > + unsigned int count, > + bool backwards) > +{ > + int i, s = backwards ? -1 : 1; > + > + for (i = 0; i < count; i++) { > + void *d = dst + (i * data_size * s); > + unsigned char *b = buf + (i * data_size); > + > + memcpy(d, b, data_size); > + } > + > + 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; > + u64 exit_info_1, exit_info_2; > enum es_result ret; > > ret = vc_ioio_exitinfo(ctxt, &exit_info_1); > @@ -289,7 +325,75 @@ static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt) > return ret; > > if (exit_info_1 & IOIO_TYPE_STR) { > - ret = ES_VMM_ERROR; > + /* (REP) INS/OUTS */ > + > + bool df = ((regs->rflags & X86_EFLAGS_DF) == X86_EFLAGS_DF); > + unsigned int io_bytes, exit_bytes; > + unsigned int ghcb_count, op_count; > + unsigned long es_base; > + u64 sw_scratch; > + > + /* > + * For the string variants with rep prefix the amount of in/out > + * operations per #VC exception is limited so that the kernel > + * has a chance to take interrupts and re-schedule while the > + * instruction is emulated. > + */ > + io_bytes = (exit_info_1 >> 4) & 0x7; > + ghcb_count = sizeof(ghcb->shared_buffer) / io_bytes; > + > + op_count = (exit_info_1 & IOIO_REP) ? regs->rcx : 1; > + exit_info_2 = op_count < ghcb_count ? op_count : ghcb_count; > + exit_bytes = exit_info_2 * io_bytes; > + > + es_base = 0; > + > + /* Read bytes of OUTS into the shared buffer */ > + if (!(exit_info_1 & IOIO_TYPE_IN)) { > + ret = vc_insn_string_read(ctxt, > + (void *)(es_base + regs->rsi), > + ghcb->shared_buffer, io_bytes, > + exit_info_2, df); > + if (ret) > + return ret; > + } > + > + /* > + * Issue an VMGEXIT to the HV to consume the bytes from the > + * shared buffer or to have it write them into the shared buffer > + * depending on the instruction: OUTS or INS. > + */ > + sw_scratch = __pa(ghcb) + offsetof(struct ghcb, shared_buffer); > + ghcb_set_sw_scratch(ghcb, sw_scratch); > + ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_IOIO, > + exit_info_1, exit_info_2); > + if (ret != ES_OK) > + return ret; > + > + /* Read bytes from shared buffer into the guest's destination. */ > + if (exit_info_1 & IOIO_TYPE_IN) { > + ret = vc_insn_string_write(ctxt, > + (void *)(es_base + regs->rdi), > + ghcb->shared_buffer, io_bytes, > + exit_info_2, df); > + if (ret) > + return ret; > + > + if (df) > + regs->rdi -= exit_bytes; > + else > + regs->rdi += exit_bytes; > + } else { > + if (df) > + regs->rsi -= exit_bytes; > + else > + regs->rsi += exit_bytes; > + } > + > + if (exit_info_1 & IOIO_REP) > + regs->rcx -= exit_info_2; > + > + ret = regs->rcx ? ES_RETRY : ES_OK; > } else { > /* IN/OUT into/from rAX */ > > -- > 2.32.0 > I was able to run both the amd_sev and msr tests under SEV-ES using this built-in #VC handler on my setup. Obviously, that doesn't exercise all of this #VC handler code. But I also compared it against what's in LInux and read through all of it as well. Great job, Varad! Reviewed-by: Marc Orr <marcorr@xxxxxxxxxx> Tested-by: Marc Orr <marcorr@xxxxxxxxxx>