[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [HVM] Create I/O context for MMIO/PIO processing in an



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 3fa8b914e2b50789262934bcfb313c95df9c3c31
# Parent  fa143f374f3deac2c63b4f9585bb7e89d2d9614b
[HVM] Create I/O context for MMIO/PIO processing in an
off-stack structure.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
Signed-off-by: Xin B Li <xin.b.li@xxxxxxxxx>
---
 xen/arch/x86/hvm/io.c          |   66 ++++++++++++++++++++---------------------
 xen/arch/x86/hvm/platform.c    |   19 ++++++-----
 xen/arch/x86/hvm/svm/svm.c     |   27 +++++++++-------
 xen/arch/x86/hvm/vmx/vmx.c     |   27 +++++++++-------
 xen/include/asm-x86/hvm/io.h   |    4 +-
 xen/include/asm-x86/hvm/vcpu.h |   18 ++++++-----
 6 files changed, 87 insertions(+), 74 deletions(-)

diff -r fa143f374f3d -r 3fa8b914e2b5 xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c     Fri Jul 14 13:53:59 2006 +0100
+++ b/xen/arch/x86/hvm/io.c     Fri Jul 14 13:59:15 2006 +0100
@@ -360,19 +360,19 @@ static inline void set_eflags_PF(int siz
 }
 
 static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
-                           struct mmio_op *mmio_opp)
+                           struct hvm_io_op *pio_opp)
 {
     unsigned long old_eax;
     int sign = p->df ? -1 : 1;
 
-    if ( p->pdata_valid || (mmio_opp->flags & OVERLAP) )
+    if ( p->pdata_valid || (pio_opp->flags & OVERLAP) )
     {
-        if ( mmio_opp->flags & REPZ )
+        if ( pio_opp->flags & REPZ )
             regs->ecx -= p->count;
         if ( p->dir == IOREQ_READ )
         {
             regs->edi += sign * p->count * p->size;
-            if ( mmio_opp->flags & OVERLAP )
+            if ( pio_opp->flags & OVERLAP )
             {
                 unsigned long addr = regs->edi;
                 if (hvm_realmode(current))
@@ -409,8 +409,8 @@ static void hvm_pio_assist(struct cpu_us
     }
 }
 
-static void hvm_mmio_assist(struct vcpu *v, struct cpu_user_regs *regs,
-                            ioreq_t *p, struct mmio_op *mmio_opp)
+static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
+                            struct hvm_io_op *mmio_opp)
 {
     int sign = p->df ? -1 : 1;
     int size = -1, index = -1;
@@ -657,51 +657,51 @@ static void hvm_mmio_assist(struct vcpu 
         break;
 
     case INSTR_XCHG:
-       if (src & REGISTER) {
-               index = operand_index(src);
-               set_reg_value(size, index, 0, regs, p->u.data);
-       } else {
-               index = operand_index(dst);
-               set_reg_value(size, index, 0, regs, p->u.data);
-       }
-       break;
-    }
-
-    hvm_load_cpu_guest_regs(v, regs);
+        if (src & REGISTER) {
+            index = operand_index(src);
+            set_reg_value(size, index, 0, regs, p->u.data);
+        } else {
+            index = operand_index(dst);
+            set_reg_value(size, index, 0, regs, p->u.data);
+        }
+        break;
+    }
 }
 
 void hvm_io_assist(struct vcpu *v)
 {
     vcpu_iodata_t *vio;
     ioreq_t *p;
-    struct cpu_user_regs *regs = guest_cpu_user_regs();
-    struct mmio_op *mmio_opp;
-    struct cpu_user_regs *inst_decoder_regs;
-
-    mmio_opp = &v->arch.hvm_vcpu.mmio_op;
-    inst_decoder_regs = mmio_opp->inst_decoder_regs;
+    struct cpu_user_regs *regs;
+    struct hvm_io_op *io_opp;
+
+    io_opp = &v->arch.hvm_vcpu.io_op;
+    regs   = &io_opp->io_context;
 
     vio = get_vio(v->domain, v->vcpu_id);
 
-    if (vio == 0) {
-        HVM_DBG_LOG(DBG_LEVEL_1,
-                    "bad shared page: %lx", (unsigned long) vio);
-        printf("bad shared page: %lx\n", (unsigned long) vio);
+    if ( vio == 0 ) {
+        printf("bad shared page: %lx\n", (unsigned long)vio);
         domain_crash_synchronous();
     }
 
     p = &vio->vp_ioreq;
 
     /* clear IO wait HVM flag */
-    if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)) {
-        if (p->state == STATE_IORESP_READY) {
+    if ( test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags) ) {
+        if ( p->state == STATE_IORESP_READY ) {
             p->state = STATE_INVALID;
             clear_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags);
 
-            if (p->type == IOREQ_TYPE_PIO)
-                hvm_pio_assist(regs, p, mmio_opp);
-            else
-                hvm_mmio_assist(v, regs, p, mmio_opp);
+            if ( p->type == IOREQ_TYPE_PIO )
+                hvm_pio_assist(regs, p, io_opp);
+            else {
+                hvm_mmio_assist(regs, p, io_opp);
+                hvm_load_cpu_guest_regs(v, regs);
+            }
+
+            /* Copy register changes back into current guest state. */
+            memcpy(guest_cpu_user_regs(), regs, HVM_CONTEXT_STACK_BYTES);
         }
         /* else an interrupt send event raced us */
     }
diff -r fa143f374f3d -r 3fa8b914e2b5 xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c       Fri Jul 14 13:53:59 2006 +0100
+++ b/xen/arch/x86/hvm/platform.c       Fri Jul 14 13:59:15 2006 +0100
@@ -729,7 +729,7 @@ void send_mmio_req(
     ioreq_t *p;
     struct cpu_user_regs *regs;
 
-    regs = current->arch.hvm_vcpu.mmio_op.inst_decoder_regs;
+    regs = &current->arch.hvm_vcpu.io_op.io_context;
 
     vio = get_vio(v->domain, v->vcpu_id);
     if (vio == NULL) {
@@ -777,7 +777,7 @@ void send_mmio_req(
 }
 
 static void mmio_operands(int type, unsigned long gpa, struct instruction 
*inst,
-                          struct mmio_op *mmio_opp, struct cpu_user_regs *regs)
+                          struct hvm_io_op *mmio_opp, struct cpu_user_regs 
*regs)
 {
     unsigned long value = 0;
     int index, size_reg;
@@ -815,16 +815,19 @@ void handle_mmio(unsigned long va, unsig
 void handle_mmio(unsigned long va, unsigned long gpa)
 {
     unsigned long inst_addr;
-    struct mmio_op *mmio_opp;
+    struct hvm_io_op *mmio_opp;
     struct cpu_user_regs *regs;
     struct instruction mmio_inst;
     unsigned char inst[MAX_INST_LEN];
     int i, realmode, ret, inst_len;
     struct vcpu *v = current;
 
-    mmio_opp = &v->arch.hvm_vcpu.mmio_op;
-
-    regs = mmio_opp->inst_decoder_regs;
+    mmio_opp = &v->arch.hvm_vcpu.io_op;
+    regs = &mmio_opp->io_context;
+
+    /* Copy current guest state into io instruction state structure. */
+    memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
+
     hvm_store_cpu_guest_regs(v, regs, NULL);
 
     if ((inst_len = hvm_instruction_length(v)) <= 0) {
@@ -1009,7 +1012,7 @@ void handle_mmio(unsigned long va, unsig
             unsigned long operand = mmio_inst.operand[0];
             value = get_reg_value(operand_size(operand),
                                   operand_index(operand), 0,
-                                  mmio_opp->inst_decoder_regs);
+                                  regs);
             /* send the request and wait for the value */
             send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
                           mmio_inst.op_size, value, IOREQ_WRITE, 0);
@@ -1019,7 +1022,7 @@ void handle_mmio(unsigned long va, unsig
             unsigned long operand = mmio_inst.operand[1];
             value = get_reg_value(operand_size(operand),
                                   operand_index(operand), 0,
-                                  mmio_opp->inst_decoder_regs);
+                                  regs);
             /* send the request and wait for the value */
             send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
                           mmio_inst.op_size, value, IOREQ_WRITE, 0);
diff -r fa143f374f3d -r 3fa8b914e2b5 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Fri Jul 14 13:53:59 2006 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c        Fri Jul 14 13:59:15 2006 +0100
@@ -1374,18 +1374,24 @@ static inline int svm_get_io_address(
 }
 
 
-static void svm_io_instruction(struct vcpu *v, struct cpu_user_regs *regs) 
-{
-    struct mmio_op *mmio_opp;
+static void svm_io_instruction(struct vcpu *v)
+{
+    struct cpu_user_regs *regs;
+    struct hvm_io_op *pio_opp;
     unsigned int port;
     unsigned int size, dir;
     ioio_info_t info;
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
 
     ASSERT(vmcb);
-    mmio_opp = &current->arch.hvm_vcpu.mmio_op;
-    mmio_opp->instr = INSTR_PIO;
-    mmio_opp->flags = 0;
+    pio_opp = &current->arch.hvm_vcpu.io_op;
+    pio_opp->instr = INSTR_PIO;
+    pio_opp->flags = 0;
+
+    regs = &pio_opp->io_context;
+
+    /* Copy current guest state into io instruction state structure. */
+    memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
 
     info.bytes = vmcb->exitinfo1;
 
@@ -1421,7 +1427,7 @@ static void svm_io_instruction(struct vc
         /* "rep" prefix */
         if (info.fields.rep) 
         {
-            mmio_opp->flags |= REPZ;
+            pio_opp->flags |= REPZ;
         }
         else 
         {
@@ -1436,7 +1442,7 @@ static void svm_io_instruction(struct vc
         {
             unsigned long value = 0;
 
-            mmio_opp->flags |= OVERLAP;
+            pio_opp->flags |= OVERLAP;
 
             if (dir == IOREQ_WRITE)
                 hvm_copy(&value, addr, size, HVM_COPY_IN);
@@ -2785,9 +2791,6 @@ asmlinkage void svm_vmexit_handler(struc
                 (unsigned long)regs.ecx, (unsigned long)regs.edx,
                 (unsigned long)regs.esi, (unsigned long)regs.edi);
 
-        v->arch.hvm_vcpu.mmio_op.inst_decoder_regs = &regs;
-
-//printk("PF1\n");
         if (!(error = svm_do_page_fault(va, &regs))) 
         {
             /* Inject #PG using Interruption-Information Fields */
@@ -2936,7 +2939,7 @@ asmlinkage void svm_vmexit_handler(struc
         break;
 
     case VMEXIT_IOIO:
-        svm_io_instruction(v, &regs);
+        svm_io_instruction(v);
         break;
 
     case VMEXIT_MSR:
diff -r fa143f374f3d -r 3fa8b914e2b5 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Fri Jul 14 13:53:59 2006 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Fri Jul 14 13:59:15 2006 +0100
@@ -1056,17 +1056,23 @@ extern void send_pio_req(struct cpu_user
                          unsigned long count, int size, long value,
                         int dir, int pvalid);
 
-static void vmx_io_instruction(struct cpu_user_regs *regs,
-                               unsigned long exit_qualification, unsigned long 
inst_len)
-{
-    struct mmio_op *mmio_opp;
+static void vmx_io_instruction(unsigned long exit_qualification,
+                               unsigned long inst_len)
+{
+    struct cpu_user_regs *regs;
+    struct hvm_io_op *pio_opp;
     unsigned long eip, cs, eflags;
     unsigned long port, size, dir;
     int vm86;
 
-    mmio_opp = &current->arch.hvm_vcpu.mmio_op;
-    mmio_opp->instr = INSTR_PIO;
-    mmio_opp->flags = 0;
+    pio_opp = &current->arch.hvm_vcpu.io_op;
+    pio_opp->instr = INSTR_PIO;
+    pio_opp->flags = 0;
+
+    regs = &pio_opp->io_context;
+
+    /* Copy current guest state into io instruction state structure. */
+    memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
 
     __vmread(GUEST_RIP, &eip);
     __vmread(GUEST_CS_SELECTOR, &cs);
@@ -1100,7 +1106,7 @@ static void vmx_io_instruction(struct cp
             addr = dir == IOREQ_WRITE ? regs->esi : regs->edi;
 
         if (test_bit(5, &exit_qualification)) { /* "rep" prefix */
-            mmio_opp->flags |= REPZ;
+            pio_opp->flags |= REPZ;
             count = vm86 ? regs->ecx & 0xFFFF : regs->ecx;
         }
 
@@ -1111,7 +1117,7 @@ static void vmx_io_instruction(struct cp
         if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) {
             unsigned long value = 0;
 
-            mmio_opp->flags |= OVERLAP;
+            pio_opp->flags |= OVERLAP;
             if (dir == IOREQ_WRITE)
                 hvm_copy(&value, addr, size, HVM_COPY_IN);
             send_pio_req(regs, port, 1, size, value, dir, 0);
@@ -2206,7 +2212,6 @@ asmlinkage void vmx_vmexit_handler(struc
                         (unsigned long)regs.eax, (unsigned long)regs.ebx,
                         (unsigned long)regs.ecx, (unsigned long)regs.edx,
                         (unsigned long)regs.esi, (unsigned long)regs.edi);
-            v->arch.hvm_vcpu.mmio_op.inst_decoder_regs = &regs;
 
             if (!(error = vmx_do_page_fault(va, &regs))) {
                 /*
@@ -2299,7 +2304,7 @@ asmlinkage void vmx_vmexit_handler(struc
     case EXIT_REASON_IO_INSTRUCTION:
         __vmread(EXIT_QUALIFICATION, &exit_qualification);
         __get_instruction_length(inst_len);
-        vmx_io_instruction(&regs, exit_qualification, inst_len);
+        vmx_io_instruction(exit_qualification, inst_len);
         TRACE_VMEXIT(4,exit_qualification);
         break;
     case EXIT_REASON_MSR_READ:
diff -r fa143f374f3d -r 3fa8b914e2b5 xen/include/asm-x86/hvm/io.h
--- a/xen/include/asm-x86/hvm/io.h      Fri Jul 14 13:53:59 2006 +0100
+++ b/xen/include/asm-x86/hvm/io.h      Fri Jul 14 13:59:15 2006 +0100
@@ -80,12 +80,12 @@ struct instruction {
 
 #define MAX_INST_LEN      15 /* Maximum instruction length = 15 bytes */
 
-struct mmio_op {
+struct hvm_io_op {
     int                    flags;
     int                    instr;       /* instruction */
     unsigned long          operand[2];  /* operands */
     unsigned long          immediate;   /* immediate portion */
-    struct cpu_user_regs   *inst_decoder_regs; /* current context */
+    struct cpu_user_regs   io_context;  /* current context */
 };
 
 #define MAX_IO_HANDLER              8
diff -r fa143f374f3d -r 3fa8b914e2b5 xen/include/asm-x86/hvm/vcpu.h
--- a/xen/include/asm-x86/hvm/vcpu.h    Fri Jul 14 13:53:59 2006 +0100
+++ b/xen/include/asm-x86/hvm/vcpu.h    Fri Jul 14 13:59:15 2006 +0100
@@ -29,17 +29,17 @@
 #define HVM_VCPU_INIT_SIPI_SIPI_STATE_WAIT_SIPI     1
 
 struct hvm_vcpu {
-    unsigned long   ioflags;
-    struct mmio_op  mmio_op;
-    struct vlapic   *vlapic;
-    s64             cache_tsc_offset;
-    u64             guest_time;
+    unsigned long       ioflags;
+    struct hvm_io_op    io_op;
+    struct vlapic       *vlapic;
+    s64                 cache_tsc_offset;
+    u64                 guest_time;
 
     /* For AP startup */
-    unsigned long   init_sipi_sipi_state;
+    unsigned long       init_sipi_sipi_state;
 
     /* Flags */
-    int   flag_dr_dirty;
+    int                 flag_dr_dirty;
 
     union {
         struct arch_vmx_struct vmx;
@@ -47,7 +47,9 @@ struct hvm_vcpu {
     } u;
 };
 
-#define ARCH_HVM_IO_WAIT   1       /* Waiting for I/O completion */
+#define ARCH_HVM_IO_WAIT            1   /* Waiting for I/O completion */
+
+#define HVM_CONTEXT_STACK_BYTES     (offsetof(struct cpu_user_regs, 
error_code))
 
 #endif /* __ASM_X86_HVM_VCPU_H__ */
 

_______________________________________________
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®.