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

[Xen-changelog] [xen-unstable] vmx realmode: Fix exception delivery w.r.t. in-flight I/O.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1197045555 0
# Node ID a74efcdc87b34904c6ab02b74ae3c981427fa9f9
# Parent  822d4ec5cfb177744cbeb1de2ad80b9d297b943f
vmx realmode: Fix exception delivery w.r.t. in-flight I/O.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/hvm/vmx/realmode.c |   95 +++++++++++++++++++++-------------------
 1 files changed, 52 insertions(+), 43 deletions(-)

diff -r 822d4ec5cfb1 -r a74efcdc87b3 xen/arch/x86/hvm/vmx/realmode.c
--- a/xen/arch/x86/hvm/vmx/realmode.c   Fri Dec 07 14:44:13 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/realmode.c   Fri Dec 07 16:39:15 2007 +0000
@@ -35,10 +35,12 @@ struct realmode_emulate_ctxt {
             unsigned int hlt:1;
             unsigned int mov_ss:1;
             unsigned int sti:1;
-            unsigned int exn_raised:1;
         } flags;
         unsigned int flag_word;
     };
+
+    uint8_t exn_vector;
+    uint8_t exn_insn_len;
 };
 
 static void realmode_deliver_exception(
@@ -104,8 +106,7 @@ static void realmode_deliver_exception(
     csr->sel  = cs_eip >> 16;
     csr->base = (uint32_t)csr->sel << 4;
     regs->eip = (uint16_t)cs_eip;
-    regs->eflags &= ~(X86_EFLAGS_AC | X86_EFLAGS_TF |
-                      X86_EFLAGS_AC | X86_EFLAGS_RF);
+    regs->eflags &= ~(X86_EFLAGS_TF | X86_EFLAGS_IF | X86_EFLAGS_RF);
 }
 
 static int
@@ -145,7 +146,7 @@ realmode_read(
         }
 
         if ( !curr->arch.hvm_vmx.real_mode_io_completed )
-            return X86EMUL_UNHANDLEABLE;
+            return X86EMUL_RETRY;
 
         *val = curr->arch.hvm_vmx.real_mode_io_data;
         curr->arch.hvm_vmx.real_mode_io_completed = 0;
@@ -286,7 +287,7 @@ realmode_read_io(
     }
 
     if ( !curr->arch.hvm_vmx.real_mode_io_completed )
-        return X86EMUL_UNHANDLEABLE;
+        return X86EMUL_RETRY;
     
     *val = curr->arch.hvm_vmx.real_mode_io_data;
     curr->arch.hvm_vmx.real_mode_io_completed = 0;
@@ -413,8 +414,8 @@ static int realmode_inject_hw_exception(
     struct realmode_emulate_ctxt *rm_ctxt =
         container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
 
-    rm_ctxt->flags.exn_raised = 1;
-    realmode_deliver_exception(vector, 0, rm_ctxt);
+    rm_ctxt->exn_vector = vector;
+    rm_ctxt->exn_insn_len = 0;
 
     return X86EMUL_OKAY;
 }
@@ -427,7 +428,8 @@ static int realmode_inject_sw_interrupt(
     struct realmode_emulate_ctxt *rm_ctxt =
         container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
 
-    realmode_deliver_exception(vector, insn_len, rm_ctxt);
+    rm_ctxt->exn_vector = vector;
+    rm_ctxt->exn_insn_len = insn_len;
 
     return X86EMUL_OKAY;
 }
@@ -470,19 +472,22 @@ void vmx_realmode(struct cpu_user_regs *
         rm_ctxt.seg_reg[x86_seg_ss].attr.fields.db ? 32 : 16;
 
     intr_info = __vmread(VM_ENTRY_INTR_INFO);
-    if ( intr_info & INTR_INFO_VALID_MASK )
-    {
-        __vmwrite(VM_ENTRY_INTR_INFO, 0);
-        realmode_deliver_exception((uint8_t)intr_info, 0, &rm_ctxt);
-    }
-
     intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
     new_intr_shadow = intr_shadow;
 
     while ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) &&
             !softirq_pending(smp_processor_id()) &&
-            !hvm_local_events_need_delivery(curr) )
-    {
+            !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,
@@ -493,33 +498,8 @@ void vmx_realmode(struct cpu_user_regs *
 
         rc = x86_emulate(&rm_ctxt.ctxt, &realmode_emulator_ops);
 
-        /* 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);
-        }
-
-        /* HLT happens after instruction retire, if no interrupt/exception. */
-        if ( unlikely(rm_ctxt.flags.hlt) &&
-             !rm_ctxt.flags.exn_raised &&
-             !hvm_local_events_need_delivery(curr) )
-            hvm_hlt(regs->eflags);
-
-        if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
-            break;
+        if ( rc == X86EMUL_RETRY )
+            continue;
 
         if ( rc == X86EMUL_UNHANDLEABLE )
         {
@@ -531,6 +511,35 @@ void vmx_realmode(struct cpu_user_regs *
                      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);
         }
     }
 

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