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

[Xen-changelog] [xen-3.2-testing] vmx realmode: Restructure code for clarity and better treatment of



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1202291679 0
# Node ID 985bae80b6d7aa87e589e59b376f52a5000eaa64
# Parent  744ec35f1e3ab5aa6c5301c872c2f0685a46cd34
vmx realmode: Restructure code for clarity and better treatment of
VM_ENTRY_INTR_INFO. Also add more sanity checking.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
xen-unstable changeset:   16869:db620f1c9d3077e732440d1088e608b6d5530daa
xen-unstable date:        Thu Jan 24 14:29:13 2008 +0000

vmx realmode: Multiple I/O reads to qemu in an instruction is not
allowed. But we do allow, for example, a read followed by a write
(e.g., MOVS within video RAM).
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
xen-unstable changeset:   16922:ed2ca78286a8c30ab68e37c7eccae6d1748f0d50
xen-unstable date:        Mon Jan 28 11:28:55 2008 +0000
---
 xen/arch/x86/hvm/vmx/realmode.c |  178 ++++++++++++++++++++++++----------------
 1 files changed, 111 insertions(+), 67 deletions(-)

diff -r 744ec35f1e3a -r 985bae80b6d7 xen/arch/x86/hvm/vmx/realmode.c
--- a/xen/arch/x86/hvm/vmx/realmode.c   Wed Feb 06 09:52:43 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/realmode.c   Wed Feb 06 09:54:39 2008 +0000
@@ -41,6 +41,8 @@ struct realmode_emulate_ctxt {
 
     uint8_t exn_vector;
     uint8_t exn_insn_len;
+
+    uint32_t intr_shadow;
 };
 
 static void realmode_deliver_exception(
@@ -502,13 +504,108 @@ static struct x86_emulate_ops realmode_e
     .load_fpu_ctxt = realmode_load_fpu_ctxt
 };
 
+static void realmode_emulate_one(struct realmode_emulate_ctxt *rm_ctxt)
+{
+    struct cpu_user_regs *regs = rm_ctxt->ctxt.regs;
+    struct vcpu *curr = current;
+    u32 new_intr_shadow;
+    int rc, io_completed;
+
+    rm_ctxt->insn_buf_eip = regs->eip;
+    (void)hvm_copy_from_guest_phys(
+        rm_ctxt->insn_buf,
+        (uint32_t)(rm_ctxt->seg_reg[x86_seg_cs].base + regs->eip),
+        sizeof(rm_ctxt->insn_buf));
+
+    rm_ctxt->flag_word = 0;
+
+    io_completed = curr->arch.hvm_vmx.real_mode_io_completed;
+    if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
+    {
+        gdprintk(XENLOG_ERR, "I/O in progress before insn is emulated.\n");
+        goto fail;
+    }
+
+    rc = x86_emulate(&rm_ctxt->ctxt, &realmode_emulator_ops);
+
+    if ( curr->arch.hvm_vmx.real_mode_io_completed )
+    {
+        gdprintk(XENLOG_ERR, "I/O completion after insn is emulated.\n");
+        goto fail;
+    }
+
+    if ( rc == X86EMUL_UNHANDLEABLE )
+    {
+        gdprintk(XENLOG_ERR, "Failed to emulate insn.\n");
+        goto fail;
+    }
+
+    if ( rc == X86EMUL_RETRY )
+    {
+        BUG_ON(!curr->arch.hvm_vmx.real_mode_io_in_progress);
+        if ( !io_completed )
+            return;
+        gdprintk(XENLOG_ERR, "Multiple I/O reads in a single insn.\n");
+        goto fail;
+    }
+
+    if ( curr->arch.hvm_vmx.real_mode_io_in_progress &&
+         (get_ioreq(curr)->vp_ioreq.dir == IOREQ_READ) )
+    {
+        gdprintk(XENLOG_ERR, "I/O read in progress but insn is retired.\n");
+        goto fail;
+    }
+
+    new_intr_shadow = rm_ctxt->intr_shadow;
+
+    /* MOV-SS instruction toggles MOV-SS shadow, else we just clear it. */
+    if ( rm_ctxt->flags.mov_ss )
+        new_intr_shadow ^= VMX_INTR_SHADOW_MOV_SS;
+    else
+        new_intr_shadow &= ~VMX_INTR_SHADOW_MOV_SS;
+
+    /* STI instruction toggles STI shadow, else we just clear it. */
+    if ( rm_ctxt->flags.sti )
+        new_intr_shadow ^= VMX_INTR_SHADOW_STI;
+    else
+        new_intr_shadow &= ~VMX_INTR_SHADOW_STI;
+
+    /* Update interrupt shadow information in VMCS only if it changes. */
+    if ( rm_ctxt->intr_shadow != new_intr_shadow )
+    {
+        rm_ctxt->intr_shadow = new_intr_shadow;
+        __vmwrite(GUEST_INTERRUPTIBILITY_INFO, rm_ctxt->intr_shadow);
+    }
+
+    if ( rc == X86EMUL_EXCEPTION )
+    {
+        realmode_deliver_exception(
+            rm_ctxt->exn_vector, rm_ctxt->exn_insn_len, rm_ctxt);
+    }
+    else if ( rm_ctxt->flags.hlt && !hvm_local_events_need_delivery(curr) )
+    {
+        hvm_hlt(regs->eflags);
+    }
+
+    return;
+
+ fail:
+    gdprintk(XENLOG_ERR,
+             "Real-mode emulation failed @ %04x:%08lx: "
+             "%02x %02x %02x %02x %02x %02x\n",
+             rm_ctxt->seg_reg[x86_seg_cs].sel, rm_ctxt->insn_buf_eip,
+             rm_ctxt->insn_buf[0], rm_ctxt->insn_buf[1],
+             rm_ctxt->insn_buf[2], rm_ctxt->insn_buf[3],
+             rm_ctxt->insn_buf[4], rm_ctxt->insn_buf[5]);
+    domain_crash_synchronous();
+}
+
 void vmx_realmode(struct cpu_user_regs *regs)
 {
     struct vcpu *curr = current;
     struct realmode_emulate_ctxt rm_ctxt;
     unsigned long intr_info;
-    int i, rc;
-    u32 intr_shadow, new_intr_shadow;
+    int i;
 
     rm_ctxt.ctxt.regs = regs;
 
@@ -520,77 +617,24 @@ void vmx_realmode(struct cpu_user_regs *
     rm_ctxt.ctxt.sp_size =
         rm_ctxt.seg_reg[x86_seg_ss].attr.fields.db ? 32 : 16;
 
+    rm_ctxt.intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
+
+    if ( curr->arch.hvm_vmx.real_mode_io_in_progress ||
+         curr->arch.hvm_vmx.real_mode_io_completed )
+        realmode_emulate_one(&rm_ctxt);
+
     intr_info = __vmread(VM_ENTRY_INTR_INFO);
-    intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
-    new_intr_shadow = intr_shadow;
+    if ( intr_info & INTR_INFO_VALID_MASK )
+    {
+        realmode_deliver_exception((uint8_t)intr_info, 0, &rm_ctxt);
+        __vmwrite(VM_ENTRY_INTR_INFO, 0);
+    }
 
     while ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) &&
             !softirq_pending(smp_processor_id()) &&
             !hvm_local_events_need_delivery(curr) &&
             !curr->arch.hvm_vmx.real_mode_io_in_progress )
-    {
-        if ( (intr_info & INTR_INFO_VALID_MASK) &&
-             !curr->arch.hvm_vmx.real_mode_io_completed )
-        {
-            realmode_deliver_exception((uint8_t)intr_info, 0, &rm_ctxt);
-            __vmwrite(VM_ENTRY_INTR_INFO, 0);
-            intr_info = 0;
-        }
-
-        rm_ctxt.insn_buf_eip = regs->eip;
-        (void)hvm_copy_from_guest_phys(
-            rm_ctxt.insn_buf,
-            (uint32_t)(rm_ctxt.seg_reg[x86_seg_cs].base + regs->eip),
-            sizeof(rm_ctxt.insn_buf));
-
-        rm_ctxt.flag_word = 0;
-
-        rc = x86_emulate(&rm_ctxt.ctxt, &realmode_emulator_ops);
-
-        if ( rc == X86EMUL_RETRY )
-            continue;
-
-        if ( rc == X86EMUL_UNHANDLEABLE )
-        {
-            gdprintk(XENLOG_ERR,
-                     "Real-mode emulation failed @ %04x:%08lx: "
-                     "%02x %02x %02x %02x %02x %02x\n",
-                     rm_ctxt.seg_reg[x86_seg_cs].sel, rm_ctxt.insn_buf_eip,
-                     rm_ctxt.insn_buf[0], rm_ctxt.insn_buf[1],
-                     rm_ctxt.insn_buf[2], rm_ctxt.insn_buf[3],
-                     rm_ctxt.insn_buf[4], rm_ctxt.insn_buf[5]);
-            domain_crash_synchronous();
-        }
-
-        /* MOV-SS instruction toggles MOV-SS shadow, else we just clear it. */
-        if ( rm_ctxt.flags.mov_ss )
-            new_intr_shadow ^= VMX_INTR_SHADOW_MOV_SS;
-        else
-            new_intr_shadow &= ~VMX_INTR_SHADOW_MOV_SS;
-
-        /* STI instruction toggles STI shadow, else we just clear it. */
-        if ( rm_ctxt.flags.sti )
-            new_intr_shadow ^= VMX_INTR_SHADOW_STI;
-        else
-            new_intr_shadow &= ~VMX_INTR_SHADOW_STI;
-
-        /* Update interrupt shadow information in VMCS only if it changes. */
-        if ( intr_shadow != new_intr_shadow )
-        {
-            intr_shadow = new_intr_shadow;
-            __vmwrite(GUEST_INTERRUPTIBILITY_INFO, intr_shadow);
-        }
-
-        if ( rc == X86EMUL_EXCEPTION )
-        {
-            realmode_deliver_exception(
-                rm_ctxt.exn_vector, rm_ctxt.exn_insn_len, &rm_ctxt);
-        }
-        else if ( rm_ctxt.flags.hlt && !hvm_local_events_need_delivery(curr) )
-        {
-            hvm_hlt(regs->eflags);
-        }
-    }
+        realmode_emulate_one(&rm_ctxt);
 
     /*
      * Cannot enter protected mode with bogus selector RPLs and DPLs. Hence we

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