[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86 hvm: Clean up PIO fast path emulation.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1284555806 -3600 # Node ID ff011e0cb17c29db8a46ce046f6074a27461cfb8 # Parent 1087f9a03ab61d3a8bb0a1c65e5b09f82f3a4277 x86 hvm: Clean up PIO fast path emulation. Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- xen/arch/x86/hvm/emulate.c | 5 + xen/arch/x86/hvm/io.c | 111 ++++++++++++++++++++------------------ xen/arch/x86/hvm/svm/svm.c | 27 ++------- xen/arch/x86/hvm/vmx/vmx.c | 34 +++-------- xen/include/asm-x86/hvm/emulate.h | 4 - xen/include/asm-x86/hvm/io.h | 2 xen/include/asm-x86/hvm/vcpu.h | 5 - 7 files changed, 86 insertions(+), 102 deletions(-) diff -r 1087f9a03ab6 -r ff011e0cb17c xen/arch/x86/hvm/emulate.c --- a/xen/arch/x86/hvm/emulate.c Wed Sep 15 09:00:35 2010 +0100 +++ b/xen/arch/x86/hvm/emulate.c Wed Sep 15 14:03:26 2010 +0100 @@ -48,7 +48,7 @@ static void hvmtrace_io_assist(int is_mm trace_var(event, 0/*!cycles*/, size, buffer); } -int hvmemul_do_io( +static int hvmemul_do_io( int is_mmio, paddr_t addr, unsigned long *reps, int size, paddr_t ram_gpa, int dir, int df, void *p_data) { @@ -142,6 +142,7 @@ int hvmemul_do_io( curr->arch.hvm_vcpu.io_state = (p_data == NULL) ? HVMIO_dispatched : HVMIO_awaiting_completion; + curr->arch.hvm_vcpu.io_size = size; p->dir = dir; p->data_is_ptr = value_is_ptr; @@ -224,7 +225,7 @@ int hvmemul_do_io( return X86EMUL_OKAY; } -static int hvmemul_do_pio( +int hvmemul_do_pio( unsigned long port, unsigned long *reps, int size, paddr_t ram_gpa, int dir, int df, void *p_data) { diff -r 1087f9a03ab6 -r ff011e0cb17c xen/arch/x86/hvm/io.c --- a/xen/arch/x86/hvm/io.c Wed Sep 15 09:00:35 2010 +0100 +++ b/xen/arch/x86/hvm/io.c Wed Sep 15 14:03:26 2010 +0100 @@ -171,22 +171,10 @@ int handle_mmio(void) struct hvm_emulate_ctxt ctxt; struct vcpu *curr = current; int rc; - unsigned long data, reps = 1; - - if ( curr->arch.hvm_vcpu.io_size == 0 ) { - hvm_emulate_prepare(&ctxt, guest_cpu_user_regs()); - rc = hvm_emulate_one(&ctxt); - } else { - if ( curr->arch.hvm_vcpu.io_dir == 0 ) - data = guest_cpu_user_regs()->eax; - rc = hvmemul_do_io(0, curr->arch.hvm_vcpu.io_port, &reps, - curr->arch.hvm_vcpu.io_size, 0, - curr->arch.hvm_vcpu.io_dir, 0, &data); - if ( curr->arch.hvm_vcpu.io_dir == 1 && rc == X86EMUL_OKAY ) { - memcpy(&(guest_cpu_user_regs()->eax), - &data, curr->arch.hvm_vcpu.io_size); - } - } + + hvm_emulate_prepare(&ctxt, guest_cpu_user_regs()); + + rc = hvm_emulate_one(&ctxt); if ( curr->arch.hvm_vcpu.io_state == HVMIO_awaiting_completion ) curr->arch.hvm_vcpu.io_state = HVMIO_handle_mmio_awaiting_completion; @@ -196,21 +184,14 @@ int handle_mmio(void) switch ( rc ) { case X86EMUL_UNHANDLEABLE: - if ( curr->arch.hvm_vcpu.io_size == 0 ) - gdprintk(XENLOG_WARNING, - "MMIO emulation failed @ %04x:%lx: " - "%02x %02x %02x %02x %02x %02x\n", - hvmemul_get_seg_reg(x86_seg_cs, &ctxt)->sel, - ctxt.insn_buf_eip, - ctxt.insn_buf[0], ctxt.insn_buf[1], - ctxt.insn_buf[2], ctxt.insn_buf[3], - ctxt.insn_buf[4], ctxt.insn_buf[5]); - else - gdprintk(XENLOG_WARNING, - "I/O emulation failed: %s 0x%04x, %i bytes, data=%08lx\n", - curr->arch.hvm_vcpu.io_dir ? "in" : "out", - curr->arch.hvm_vcpu.io_port, - curr->arch.hvm_vcpu.io_size, data); + gdprintk(XENLOG_WARNING, + "MMIO emulation failed @ %04x:%lx: " + "%02x %02x %02x %02x %02x %02x\n", + hvmemul_get_seg_reg(x86_seg_cs, &ctxt)->sel, + ctxt.insn_buf_eip, + ctxt.insn_buf[0], ctxt.insn_buf[1], + ctxt.insn_buf[2], ctxt.insn_buf[3], + ctxt.insn_buf[4], ctxt.insn_buf[5]); return 0; case X86EMUL_EXCEPTION: if ( ctxt.exn_pending ) @@ -220,15 +201,9 @@ int handle_mmio(void) break; } - if ( curr->arch.hvm_vcpu.io_size == 0 ) - hvm_emulate_writeback(&ctxt); - else - curr->arch.hvm_vcpu.io_size = 0; - - if (rc == X86EMUL_RETRY) - return rc; - else - return 1; + hvm_emulate_writeback(&ctxt); + + return 1; } int handle_mmio_with_translation(unsigned long gva, unsigned long gpfn) @@ -238,12 +213,36 @@ int handle_mmio_with_translation(unsigne return handle_mmio(); } -int handle_mmio_decoded(uint16_t port, int size, int dir) -{ - current->arch.hvm_vcpu.io_port = port; - current->arch.hvm_vcpu.io_size = size; - current->arch.hvm_vcpu.io_dir = dir; - return handle_mmio(); +int handle_pio(uint16_t port, int size, int dir) +{ + struct vcpu *curr = current; + unsigned long data, reps = 1; + int rc; + + if ( dir == IOREQ_WRITE ) + data = guest_cpu_user_regs()->eax; + + rc = hvmemul_do_pio(port, &reps, size, 0, dir, 0, &data); + + switch ( rc ) + { + case X86EMUL_OKAY: + if ( dir == IOREQ_READ ) + memcpy(&guest_cpu_user_regs()->eax, + &data, curr->arch.hvm_vcpu.io_size); + break; + case X86EMUL_RETRY: + if ( curr->arch.hvm_vcpu.io_state != HVMIO_awaiting_completion ) + return 0; + /* Completion in hvm_io_assist() with no re-emulation required. */ + ASSERT(dir == IOREQ_READ); + curr->arch.hvm_vcpu.io_state = HVMIO_handle_pio_awaiting_completion; + break; + default: + BUG(); + } + + return 1; } void hvm_io_assist(void) @@ -259,13 +258,23 @@ void hvm_io_assist(void) io_state = curr->arch.hvm_vcpu.io_state; curr->arch.hvm_vcpu.io_state = HVMIO_none; - if ( (io_state == HVMIO_awaiting_completion) || - (io_state == HVMIO_handle_mmio_awaiting_completion) ) - { + switch ( io_state ) + { + case HVMIO_awaiting_completion: curr->arch.hvm_vcpu.io_state = HVMIO_completed; curr->arch.hvm_vcpu.io_data = p->data; - if ( io_state == HVMIO_handle_mmio_awaiting_completion ) - (void)handle_mmio(); + break; + case HVMIO_handle_mmio_awaiting_completion: + curr->arch.hvm_vcpu.io_state = HVMIO_completed; + curr->arch.hvm_vcpu.io_data = p->data; + (void)handle_mmio(); + break; + case HVMIO_handle_pio_awaiting_completion: + memcpy(&guest_cpu_user_regs()->eax, + &p->data, curr->arch.hvm_vcpu.io_size); + break; + default: + break; } if ( p->state == STATE_IOREQ_NONE ) diff -r 1087f9a03ab6 -r ff011e0cb17c xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Wed Sep 15 09:00:35 2010 +0100 +++ b/xen/arch/x86/hvm/svm/svm.c Wed Sep 15 14:03:26 2010 +0100 @@ -1333,23 +1333,6 @@ static void svm_vmexit_do_invalidate_cac __update_guest_eip(regs, inst_len); } -static int svm_vmexit_do_io(struct vmcb_struct *vmcb, - struct cpu_user_regs *regs) -{ - uint16_t port; - int bytes, dir; - int rc; - - port = (vmcb->exitinfo1 >> 16) & 0xFFFF; - bytes = ((vmcb->exitinfo1 >> 4) & 0x07); - dir = (vmcb->exitinfo1 & 1) ? IOREQ_READ : IOREQ_WRITE; - - rc = handle_mmio_decoded(port, bytes, dir); - if ( rc != X86EMUL_RETRY ) - __update_guest_eip(regs, vmcb->exitinfo2 - vmcb->rip); - return rc; -} - static void svm_invlpg_intercept(unsigned long vaddr) { struct vcpu *curr = current; @@ -1558,9 +1541,13 @@ asmlinkage void svm_vmexit_handler(struc break; case VMEXIT_IOIO: - if ( ( vmcb->exitinfo1 & ( 1 << 2 ) ) == 0 ) { - if ( !svm_vmexit_do_io(vmcb, regs) ) - hvm_inject_exception(TRAP_gp_fault, 0, 0); + if ( (vmcb->exitinfo1 & (1u<<2)) == 0 ) + { + uint16_t port = (vmcb->exitinfo1 >> 16) & 0xFFFF; + int bytes = ((vmcb->exitinfo1 >> 4) & 0x07); + int dir = (vmcb->exitinfo1 & 1) ? IOREQ_READ : IOREQ_WRITE; + if ( handle_pio(port, bytes, dir) ) + __update_guest_eip(regs, vmcb->exitinfo2 - vmcb->rip); break; } /* fallthrough to emulation if a string instruction */ diff -r 1087f9a03ab6 -r ff011e0cb17c xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Sep 15 09:00:35 2010 +0100 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Sep 15 14:03:26 2010 +0100 @@ -1700,25 +1700,6 @@ static int vmx_cr_access(unsigned long e return 1; } -static int vmx_io_intercept(unsigned long exit_qualification, - struct cpu_user_regs *regs) -{ - uint16_t port; - int bytes, dir; - int rc; - int inst_len; - - port = (exit_qualification >> 16) & 0xFFFF; - bytes = (exit_qualification & 0x07) + 1; - dir = (exit_qualification & 0x08) ? IOREQ_READ : IOREQ_WRITE; - - inst_len = __get_instruction_length(); - rc = handle_mmio_decoded(port, bytes, dir); - if ( rc != X86EMUL_RETRY) - __update_guest_eip(inst_len); - return rc; -} - static const struct lbr_info { u32 base, count; } p4_lbr[] = { @@ -2594,12 +2575,19 @@ asmlinkage void vmx_vmexit_handler(struc case EXIT_REASON_IO_INSTRUCTION: exit_qualification = __vmread(EXIT_QUALIFICATION); - if (exit_qualification & 0x10) { + if ( exit_qualification & 0x10 ) + { if ( !handle_mmio() ) vmx_inject_hw_exception(TRAP_gp_fault, 0); - } else { - if ( !vmx_io_intercept(exit_qualification, regs) ) - vmx_inject_hw_exception(TRAP_gp_fault, 0); + } + else + { + uint16_t port = (exit_qualification >> 16) & 0xFFFF; + int bytes = (exit_qualification & 0x07) + 1; + int dir = (exit_qualification & 0x08) ? IOREQ_READ : IOREQ_WRITE; + inst_len = __get_instruction_length(); + if ( handle_pio(port, bytes, dir) ) + __update_guest_eip(inst_len); } break; diff -r 1087f9a03ab6 -r ff011e0cb17c xen/include/asm-x86/hvm/emulate.h --- a/xen/include/asm-x86/hvm/emulate.h Wed Sep 15 09:00:35 2010 +0100 +++ b/xen/include/asm-x86/hvm/emulate.h Wed Sep 15 14:03:26 2010 +0100 @@ -46,8 +46,8 @@ struct segment_register *hvmemul_get_seg enum x86_segment seg, struct hvm_emulate_ctxt *hvmemul_ctxt); -int hvmemul_do_io( - int is_mmio, paddr_t addr, unsigned long *reps, int size, +int hvmemul_do_pio( + paddr_t addr, unsigned long *reps, int size, paddr_t ram_gpa, int dir, int df, void *p_data); #endif /* __ASM_X86_HVM_EMULATE_H__ */ diff -r 1087f9a03ab6 -r ff011e0cb17c xen/include/asm-x86/hvm/io.h --- a/xen/include/asm-x86/hvm/io.h Wed Sep 15 09:00:35 2010 +0100 +++ b/xen/include/asm-x86/hvm/io.h Wed Sep 15 14:03:26 2010 +0100 @@ -100,7 +100,7 @@ void send_invalidate_req(void); void send_invalidate_req(void); int handle_mmio(void); int handle_mmio_with_translation(unsigned long gva, unsigned long gpfn); -int handle_mmio_decoded(uint16_t port, int size, int dir); +int handle_pio(uint16_t port, int size, int dir); void hvm_interrupt_post(struct vcpu *v, int vector, int type); void hvm_io_assist(void); void hvm_dpci_eoi(struct domain *d, unsigned int guest_irq, diff -r 1087f9a03ab6 -r ff011e0cb17c xen/include/asm-x86/hvm/vcpu.h --- a/xen/include/asm-x86/hvm/vcpu.h Wed Sep 15 09:00:35 2010 +0100 +++ b/xen/include/asm-x86/hvm/vcpu.h Wed Sep 15 14:03:26 2010 +0100 @@ -32,6 +32,7 @@ enum hvm_io_state { HVMIO_dispatched, HVMIO_awaiting_completion, HVMIO_handle_mmio_awaiting_completion, + HVMIO_handle_pio_awaiting_completion, HVMIO_completed }; @@ -98,6 +99,7 @@ struct hvm_vcpu { /* I/O request in flight to device model. */ enum hvm_io_state io_state; unsigned long io_data; + int io_size; /* * HVM emulation: @@ -107,9 +109,6 @@ struct hvm_vcpu { */ unsigned long mmio_gva; unsigned long mmio_gpfn; - uint16_t io_port; - int io_size; - unsigned io_dir; /* Callback into x86_emulate when emulating FPU/MMX/XMM instructions. */ void (*fpu_exception_callback)(void *, struct cpu_user_regs *); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |