[xen-unstable] vmx realmode: Plumb through I/O port accesses in emulated realmode.

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[xen-unstable] vmx realmode: Plumb through I/O port accesses in emulated realmode.

Xen patchbot-unstable
# HG changeset patch
# User Keir Fraser <[hidden email]>
# Date 1195991033 0
# Node ID 368bcf480772fb32b22fa9cb0bffcd10f0ed2c25
# Parent  ce3e5e859d66455ab31b8db8f286933e455b4f7c
vmx realmode: Plumb through I/O port accesses in emulated realmode.
Signed-off-by: Keir Fraser <[hidden email]>
---
 xen/arch/x86/hvm/io.c              |    6 ++-
 xen/arch/x86/hvm/vmx/realmode.c    |   62 ++++++++++++++++++++++++++++++++++---
 xen/arch/x86/hvm/vmx/vmx.c         |    1
 xen/arch/x86/x86_emulate.c         |   34 +++++++++++++++++---
 xen/include/asm-x86/hvm/vcpu.h     |    3 +
 xen/include/asm-x86/hvm/vmx/vmcs.h |    4 ++
 xen/include/asm-x86/hvm/vmx/vmx.h  |    1
 7 files changed, 102 insertions(+), 9 deletions(-)

diff -r ce3e5e859d66 -r 368bcf480772 xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c Sun Nov 25 09:23:02 2007 +0000
+++ b/xen/arch/x86/hvm/io.c Sun Nov 25 11:43:53 2007 +0000
@@ -841,12 +841,16 @@ void hvm_io_assist(void)
     if ( p->state != STATE_IORESP_READY )
     {
         gdprintk(XENLOG_ERR, "Unexpected HVM iorequest state %d.\n", p->state);
-        domain_crash_synchronous();
+        domain_crash(v->domain);
+        goto out;
     }
 
     rmb(); /* see IORESP_READY /then/ read contents of ioreq */
 
     p->state = STATE_IOREQ_NONE;
+
+    if ( v->arch.hvm_vcpu.io_complete && v->arch.hvm_vcpu.io_complete() )
+        goto out;
 
     switch ( p->type )
     {
diff -r ce3e5e859d66 -r 368bcf480772 xen/arch/x86/hvm/vmx/realmode.c
--- a/xen/arch/x86/hvm/vmx/realmode.c Sun Nov 25 09:23:02 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/realmode.c Sun Nov 25 11:43:53 2007 +0000
@@ -178,7 +178,24 @@ realmode_read_io(
     unsigned long *val,
     struct x86_emulate_ctxt *ctxt)
 {
-    return X86EMUL_UNHANDLEABLE;
+    struct vcpu *curr = current;
+
+    if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
+        return X86EMUL_UNHANDLEABLE;
+
+    if ( !curr->arch.hvm_vmx.real_mode_io_completed )
+    {
+        curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
+        send_pio_req(port, 1, bytes, 0, IOREQ_READ, 0, 0);
+    }
+
+    if ( !curr->arch.hvm_vmx.real_mode_io_completed )
+        return X86EMUL_UNHANDLEABLE;
+    
+    *val = curr->arch.hvm_vmx.real_mode_io_data;
+    curr->arch.hvm_vmx.real_mode_io_completed = 0;
+
+    return X86EMUL_OKAY;
 }
 
 static int realmode_write_io(
@@ -187,7 +204,15 @@ static int realmode_write_io(
     unsigned long val,
     struct x86_emulate_ctxt *ctxt)
 {
-    return X86EMUL_UNHANDLEABLE;
+    struct vcpu *curr = current;
+
+    if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
+        return X86EMUL_UNHANDLEABLE;
+
+    curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
+    send_pio_req(port, 1, bytes, val, IOREQ_WRITE, 0, 0);
+
+    return X86EMUL_OKAY;
 }
 
 static int
@@ -259,8 +284,19 @@ int vmx_realmode(struct cpu_user_regs *r
                  rm_ctxt.insn_buf[2], rm_ctxt.insn_buf[3],
                  rm_ctxt.insn_buf[4], rm_ctxt.insn_buf[5]);
 
-        if ( x86_emulate(&rm_ctxt.ctxt, &realmode_emulator_ops) )
-        {            
+        rc = x86_emulate(&rm_ctxt.ctxt, &realmode_emulator_ops);
+
+        if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
+        {
+            ioreq_t *p = &get_ioreq(curr)->vp_ioreq;
+            gdprintk(XENLOG_DEBUG, "RM I/O %d %c addr=%lx data=%lx\n",
+                     p->type, p->dir ? 'R' : 'W', p->addr, p->data);
+            rc = 0;
+            break;
+        }
+
+        if ( rc )
+        {
             gdprintk(XENLOG_ERR, "Emulation failed\n");
             rc = -EINVAL;
             break;
@@ -272,3 +308,21 @@ int vmx_realmode(struct cpu_user_regs *r
 
     return rc;
 }
+
+int vmx_realmode_io_complete(void)
+{
+    struct vcpu *curr = current;
+    ioreq_t *p = &get_ioreq(curr)->vp_ioreq;
+
+    if ( !curr->arch.hvm_vmx.real_mode_io_in_progress )
+        return 0;
+
+    curr->arch.hvm_vmx.real_mode_io_in_progress = 0;
+    if ( p->dir == IOREQ_READ )
+    {
+        curr->arch.hvm_vmx.real_mode_io_completed = 1;
+        curr->arch.hvm_vmx.real_mode_io_data = p->data;
+    }
+
+    return 1;
+}
diff -r ce3e5e859d66 -r 368bcf480772 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Sun Nov 25 09:23:02 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c Sun Nov 25 11:43:53 2007 +0000
@@ -95,6 +95,7 @@ static int vmx_vcpu_initialise(struct vc
 #ifndef VMXASSIST
     if ( v->vcpu_id == 0 )
         v->arch.guest_context.user_regs.eax = 1;
+    v->arch.hvm_vcpu.io_complete = vmx_realmode_io_complete;
 #endif
 
     return 0;
diff -r ce3e5e859d66 -r 368bcf480772 xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c Sun Nov 25 09:23:02 2007 +0000
+++ b/xen/arch/x86/x86_emulate.c Sun Nov 25 11:43:53 2007 +0000
@@ -264,6 +264,7 @@ struct operand {
 };
 
 /* EFLAGS bit definitions. */
+#define EFLG_VM (1<<17)
 #define EFLG_RF (1<<16)
 #define EFLG_OF (1<<11)
 #define EFLG_DF (1<<10)
@@ -478,10 +479,6 @@ do {                                    
 /* In future we will be able to generate arbitrary exceptions. */
 #define generate_exception_if(p, e) fail_if(p)
 
-/* To be done... */
-#define mode_ring0() (0)
-#define mode_iopl()  (0)
-
 /* Given byte has even parity (even number of 1s)? */
 static int even_parity(uint8_t v)
 {
@@ -678,6 +675,35 @@ test_cc(
     /* Odd condition identifiers (lsb == 1) have inverted sense. */
     return (!!rc ^ (condition & 1));
 }
+
+static int
+get_cpl(
+    struct x86_emulate_ctxt *ctxt,
+    struct x86_emulate_ops  *ops)
+{
+    struct segment_register reg;
+
+    if ( ctxt->regs->eflags & EFLG_VM )
+        return 3;
+
+    if ( (ops->read_segment == NULL) ||
+         ops->read_segment(x86_seg_ss, &reg, ctxt) )
+        return -1;
+
+    return reg.attr.fields.dpl;
+}
+
+static int
+_mode_iopl(
+    struct x86_emulate_ctxt *ctxt,
+    struct x86_emulate_ops  *ops)
+{
+    int cpl = get_cpl(ctxt, ops);
+    return ((cpl >= 0) && (cpl <= ((ctxt->regs->eflags >> 12) & 3)));
+}
+
+#define mode_ring0() (get_cpl(ctxt, ops) == 0)
+#define mode_iopl()  _mode_iopl(ctxt, ops)
 
 static int
 in_realmode(
diff -r ce3e5e859d66 -r 368bcf480772 xen/include/asm-x86/hvm/vcpu.h
--- a/xen/include/asm-x86/hvm/vcpu.h Sun Nov 25 09:23:02 2007 +0000
+++ b/xen/include/asm-x86/hvm/vcpu.h Sun Nov 25 11:43:53 2007 +0000
@@ -59,6 +59,9 @@ struct hvm_vcpu {
     bool_t              flag_dr_dirty;
     bool_t              debug_state_latch;
 
+    /* Callback function for I/O completion. */
+    int                 (*io_complete)(void);
+
     union {
         struct arch_vmx_struct vmx;
         struct arch_svm_struct svm;
diff -r ce3e5e859d66 -r 368bcf480772 xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h Sun Nov 25 09:23:02 2007 +0000
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Sun Nov 25 11:43:53 2007 +0000
@@ -92,6 +92,10 @@ struct arch_vmx_struct {
     unsigned long        vmxassist_enabled:1;
     unsigned long        irqbase_mode:1;
     unsigned char        pm_irqbase[2];
+#else
+    bool_t               real_mode_io_in_progress;
+    bool_t               real_mode_io_completed;
+    unsigned long        real_mode_io_data;
 #endif
 };
 
diff -r ce3e5e859d66 -r 368bcf480772 xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Sun Nov 25 09:23:02 2007 +0000
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Sun Nov 25 11:43:53 2007 +0000
@@ -34,6 +34,7 @@ void set_guest_time(struct vcpu *v, u64
 void set_guest_time(struct vcpu *v, u64 gtime);
 void vmx_vlapic_msr_changed(struct vcpu *v);
 int vmx_realmode(struct cpu_user_regs *regs);
+int vmx_realmode_io_complete(void);
 
 /*
  * Exit Reasons

_______________________________________________
Xen-changelog mailing list
[hidden email]
http://lists.xensource.com/xen-changelog