On 2/13/22 2:31 AM, Marc Orr wrote: > 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> > Thank you Marc for going over the series! I'll have the v3 out soon. Regards, Varad