From mboxrd@z Thu Jan 1 00:00:00 1970 From: Paul Durrant Subject: [PATCH v3 16/18] x86/hvm: use ioreq_t to track in-flight state Date: Tue, 23 Jun 2015 11:39:55 +0100 Message-ID: <1435055997-30017-17-git-send-email-paul.durrant@citrix.com> References: <1435055997-30017-1-git-send-email-paul.durrant@citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1Z7Li3-0002kW-4A for xen-devel@lists.xenproject.org; Tue, 23 Jun 2015 10:45:43 +0000 In-Reply-To: <1435055997-30017-1-git-send-email-paul.durrant@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xenproject.org Cc: Andrew Cooper , Paul Durrant , Keir Fraser , Jan Beulich List-Id: xen-devel@lists.xenproject.org Use an ioreq_t rather than open coded state, size, dir and data fields in struct hvm_vcpu_io. This also allows PIO completion to be handled similarly to MMIO completion by re-issuing the handle_pio() call. Signed-off-by: Paul Durrant Cc: Keir Fraser Cc: Jan Beulich Cc: Andrew Cooper --- xen/arch/x86/hvm/emulate.c | 35 +++++++++++++++++++++-------------- xen/arch/x86/hvm/hvm.c | 15 ++++++++------- xen/arch/x86/hvm/svm/nestedsvm.c | 2 +- xen/arch/x86/hvm/vmx/realmode.c | 4 ++-- xen/include/asm-x86/hvm/vcpu.h | 12 ++++-------- 5 files changed, 36 insertions(+), 32 deletions(-) diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c index 23582af..57a93f2 100644 --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -92,6 +92,7 @@ static int hvmemul_do_io( .df = df, .data = data, .data_is_ptr = data_is_addr, /* ioreq_t field name is misleading */ + .state = STATE_IOREQ_READY, }; void *p_data = (void *)data; int rc; @@ -129,12 +130,24 @@ static int hvmemul_do_io( } } - switch ( vio->io_state ) + switch ( vio->io_req.state ) { case STATE_IOREQ_NONE: break; case STATE_IORESP_READY: - vio->io_state = STATE_IOREQ_NONE; + vio->io_req.state = STATE_IOREQ_NONE; + p = vio->io_req; + + /* Verify the emulation request has been correctly re-issued */ + if ( (p.type != is_mmio ? IOREQ_TYPE_COPY : IOREQ_TYPE_PIO) || + (p.addr != addr) || + (p.size != size) || + (p.count != reps) || + (p.dir != dir) || + (p.df != df) || + (p.data_is_ptr != data_is_addr) ) + domain_crash(curr->domain); + if ( data_is_addr || dir == IOREQ_WRITE ) return X86EMUL_UNHANDLEABLE; goto finish_access; @@ -142,11 +155,6 @@ static int hvmemul_do_io( return X86EMUL_UNHANDLEABLE; } - vio->io_state = STATE_IOREQ_READY; - vio->io_size = size; - vio->io_dir = dir; - vio->io_data_is_addr = data_is_addr; - if ( dir == IOREQ_WRITE ) { if ( !data_is_addr ) @@ -155,13 +163,14 @@ static int hvmemul_do_io( hvmtrace_io_assist(&p); } + vio->io_req = p; + rc = hvm_io_intercept(&p); switch ( rc ) { case X86EMUL_OKAY: - vio->io_data = p.data; - vio->io_state = STATE_IOREQ_NONE; + vio->io_req.state = STATE_IOREQ_NONE; break; case X86EMUL_UNHANDLEABLE: { @@ -172,15 +181,13 @@ static int hvmemul_do_io( if ( !s ) { rc = hvm_process_io_intercept(&null_handler, &p); - if ( rc == X86EMUL_OKAY ) - vio->io_data = p.data; - vio->io_state = STATE_IOREQ_NONE; + vio->io_req.state = STATE_IOREQ_NONE; } else { rc = hvm_send_assist_req(s, &p); if ( rc != X86EMUL_RETRY ) - vio->io_state = STATE_IOREQ_NONE; + vio->io_req.state = STATE_IOREQ_NONE; else if ( data_is_addr || dir == IOREQ_WRITE ) rc = X86EMUL_OKAY; } @@ -199,7 +206,7 @@ static int hvmemul_do_io( hvmtrace_io_assist(&p); if ( !data_is_addr ) - memcpy(p_data, &vio->io_data, size); + memcpy(p_data, &p.data, size); } if ( is_mmio && !data_is_addr ) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 7411287..8abf29b 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -421,11 +421,11 @@ static void hvm_io_assist(ioreq_t *p) if ( HVMIO_NEED_COMPLETION(vio) ) { - vio->io_state = STATE_IORESP_READY; - vio->io_data = p->data; + vio->io_req.state = STATE_IORESP_READY; + vio->io_req.data = p->data; } else - vio->io_state = STATE_IOREQ_NONE; + vio->io_req.state = STATE_IOREQ_NONE; msix_write_completion(curr); vcpu_end_shutdown_deferral(curr); @@ -501,11 +501,12 @@ void hvm_do_resume(struct vcpu *v) (void)handle_mmio(); break; case HVMIO_pio_completion: - if ( vio->io_size == 4 ) /* Needs zero extension. */ - guest_cpu_user_regs()->rax = (uint32_t)vio->io_data; + if ( vio->io_req.size == 4 ) /* Needs zero extension. */ + guest_cpu_user_regs()->rax = (uint32_t)vio->io_req.data; else - memcpy(&guest_cpu_user_regs()->rax, &vio->io_data, vio->io_size); - vio->io_state = STATE_IOREQ_NONE; + memcpy(&guest_cpu_user_regs()->rax, &vio->io_req.data, + vio->io_req.size); + vio->io_req.state = STATE_IOREQ_NONE; break; case HVMIO_realmode_completion: { diff --git a/xen/arch/x86/hvm/svm/nestedsvm.c b/xen/arch/x86/hvm/svm/nestedsvm.c index 8b165c6..78667a2 100644 --- a/xen/arch/x86/hvm/svm/nestedsvm.c +++ b/xen/arch/x86/hvm/svm/nestedsvm.c @@ -1231,7 +1231,7 @@ enum hvm_intblk nsvm_intr_blocked(struct vcpu *v) * Delay the injection because this would result in delivering * an interrupt *within* the execution of an instruction. */ - if ( v->arch.hvm_vcpu.hvm_io.io_state != STATE_IOREQ_NONE ) + if ( v->arch.hvm_vcpu.hvm_io.io_req.state != STATE_IOREQ_NONE ) return hvm_intblk_shadow; if ( !nv->nv_vmexit_pending && n2vmcb->exitintinfo.bytes != 0 ) { diff --git a/xen/arch/x86/hvm/vmx/realmode.c b/xen/arch/x86/hvm/vmx/realmode.c index 4135ad4..0f3124d 100644 --- a/xen/arch/x86/hvm/vmx/realmode.c +++ b/xen/arch/x86/hvm/vmx/realmode.c @@ -205,7 +205,7 @@ void vmx_realmode(struct cpu_user_regs *regs) vmx_realmode_emulate_one(&hvmemul_ctxt); - if ( vio->io_state != STATE_IOREQ_NONE || vio->mmio_retry ) + if ( vio->io_req.state != STATE_IOREQ_NONE || vio->mmio_retry ) break; /* Stop emulating unless our segment state is not safe */ @@ -219,7 +219,7 @@ void vmx_realmode(struct cpu_user_regs *regs) } /* Need to emulate next time if we've started an IO operation */ - if ( vio->io_state != STATE_IOREQ_NONE ) + if ( vio->io_req.state != STATE_IOREQ_NONE ) curr->arch.hvm_vmx.vmx_emulate = 1; if ( !curr->arch.hvm_vmx.vmx_emulate && !curr->arch.hvm_vmx.vmx_realmode ) diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h index f797518..7338638 100644 --- a/xen/include/asm-x86/hvm/vcpu.h +++ b/xen/include/asm-x86/hvm/vcpu.h @@ -44,17 +44,13 @@ struct hvm_vcpu_asid { struct hvm_vcpu_io { /* I/O request in flight to device model. */ - uint8_t io_state; - unsigned long io_data; - int io_size; + ioreq_t io_req; enum hvm_io_completion io_completion; - uint8_t io_dir; - uint8_t io_data_is_addr; #define HVMIO_NEED_COMPLETION(_vio) \ - ( ((_vio)->io_state == STATE_IOREQ_READY) && \ - !(_vio)->io_data_is_addr && \ - ((_vio)->io_dir == IOREQ_READ) ) + ( ((_vio)->io_req.state == STATE_IOREQ_READY) && \ + !(_vio)->io_req.data_is_ptr && \ + ((_vio)->io_req.dir == IOREQ_READ) ) /* * HVM emulation: -- 1.7.10.4