WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] x86 hvm: Clean up PIO fast path emulation

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86 hvm: Clean up PIO fast path emulation.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Sat, 09 Oct 2010 14:55:15 -0700
Delivery-date: Sat, 09 Oct 2010 14:56:25 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] x86 hvm: Clean up PIO fast path emulation., Xen patchbot-unstable <=