[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.