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

[Xen-changelog] [xen-unstable] [HVM][VMX] Fix injection of software exceptions (#BP, #OF)



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Node ID f42039dcdc814cf3d154cdccd58f930df98901dd
# Parent  ed20a5addce450af042e61f0bdb6f7b59de9b25c
[HVM][VMX] Fix injection of software exceptions (#BP,#OF)
From: George Dunlap <dunlapg@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/vmx/vmx.c        |   18 ++++++-------
 xen/include/asm-x86/hvm/vmx/vmx.h |   52 +++++++++++++++++++++++++++-----------
 2 files changed, 47 insertions(+), 23 deletions(-)

diff -r ed20a5addce4 -r f42039dcdc81 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Thu Jul 27 12:59:36 2006 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Thu Jul 27 13:05:33 2006 +0100
@@ -286,7 +286,7 @@ static inline int long_mode_do_msr_write
         if ( msr_content & ~(EFER_LME | EFER_LMA | EFER_NX | EFER_SCE) )
         {
             printk("trying to set reserved bit in EFER\n");
-            vmx_inject_exception(v, TRAP_gp_fault, 0);
+            vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
             return 0;
         }
 
@@ -300,7 +300,7 @@ static inline int long_mode_do_msr_write
             {
                 printk("trying to set LME bit when "
                        "in paging mode or PAE bit is not set\n");
-                vmx_inject_exception(v, TRAP_gp_fault, 0);
+                vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
                 return 0;
             }
 
@@ -318,7 +318,7 @@ static inline int long_mode_do_msr_write
         if ( !IS_CANO_ADDRESS(msr_content) )
         {
             HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n");
-            vmx_inject_exception(v, TRAP_gp_fault, 0);
+            vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
             return 0;
         }
 
@@ -1438,7 +1438,7 @@ static int vmx_set_cr0(unsigned long val
                        &v->arch.hvm_vmx.cpu_state) )
         {
             HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enabled\n");
-            vmx_inject_exception(v, TRAP_gp_fault, 0);
+            vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
         }
 
         if ( test_bit(VMX_CPU_STATE_LME_ENABLED,
@@ -1520,7 +1520,7 @@ static int vmx_set_cr0(unsigned long val
     {
         if ( value & X86_CR0_PG ) {
             /* inject GP here */
-            vmx_inject_exception(v, TRAP_gp_fault, 0);
+            vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
             return 0;
         } else {
             /*
@@ -1764,7 +1764,7 @@ static int mov_to_cr(int gp, int cr, str
         else
         {
             if ( test_bit(VMX_CPU_STATE_LMA_ENABLED, 
&v->arch.hvm_vmx.cpu_state) )
-                vmx_inject_exception(v, TRAP_gp_fault, 0);
+                vmx_inject_hw_exception(v, TRAP_gp_fault, 0);
 
             clear_bit(VMX_CPU_STATE_PAE_ENABLED, &v->arch.hvm_vmx.cpu_state);
         }
@@ -2192,7 +2192,7 @@ asmlinkage void vmx_vmexit_handler(struc
             if ( test_bit(_DOMF_debugging, &v->domain->domain_flags) )
                 domain_pause_for_debugger();
             else 
-                vmx_inject_exception(v, TRAP_int3, VMX_DELIVER_NO_ERROR_CODE);
+                vmx_reflect_exception(v);
             break;
         }
 #endif
@@ -2219,7 +2219,7 @@ asmlinkage void vmx_vmexit_handler(struc
                 /*
                  * Inject #PG using Interruption-Information Fields
                  */
-                vmx_inject_exception(v, TRAP_page_fault, regs.error_code);
+                vmx_inject_hw_exception(v, TRAP_page_fault, regs.error_code);
                 v->arch.hvm_vmx.cpu_cr2 = va;
                 TRACE_3D(TRC_VMX_INT, v->domain->domain_id, TRAP_page_fault, 
va);
             }
@@ -2335,7 +2335,7 @@ asmlinkage void vmx_vmexit_handler(struc
     case EXIT_REASON_VMON:
         /* Report invalid opcode exception when a VMX guest tries to execute 
             any of the VMX instructions */
-        vmx_inject_exception(v, TRAP_invalid_op, VMX_DELIVER_NO_ERROR_CODE);
+        vmx_inject_hw_exception(v, TRAP_invalid_op, VMX_DELIVER_NO_ERROR_CODE);
         break;
 
     default:
diff -r ed20a5addce4 -r f42039dcdc81 xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Thu Jul 27 12:59:36 2006 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Thu Jul 27 13:05:33 2006 +0100
@@ -143,11 +143,12 @@ extern unsigned int cpu_rev;
  */
 #define INTR_INFO_VECTOR_MASK           0xff            /* 7:0 */
 #define INTR_INFO_INTR_TYPE_MASK        0x700           /* 10:8 */
-#define INTR_INFO_DELIEVER_CODE_MASK    0x800           /* 11 */
+#define INTR_INFO_DELIVER_CODE_MASK     0x800           /* 11 */
 #define INTR_INFO_VALID_MASK            0x80000000      /* 31 */
 
 #define INTR_TYPE_EXT_INTR              (0 << 8) /* external interrupt */
-#define INTR_TYPE_EXCEPTION             (3 << 8) /* processor exception */
+#define INTR_TYPE_HW_EXCEPTION             (3 << 8) /* hardware exception */
+#define INTR_TYPE_SW_EXCEPTION             (6 << 8) /* software exception */
 
 /*
  * Exit Qualifications for MOV for Control Register Access
@@ -421,7 +422,7 @@ static inline int vmx_pgbit_test(struct 
 }
 
 static inline int __vmx_inject_exception(struct vcpu *v, int trap, int type, 
-                                         int error_code)
+                                         int error_code, int ilen)
 {
     unsigned long intr_fields;
 
@@ -429,22 +430,33 @@ static inline int __vmx_inject_exception
     intr_fields = (INTR_INFO_VALID_MASK | type | trap);
     if (error_code != VMX_DELIVER_NO_ERROR_CODE) {
         __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
-        intr_fields |= INTR_INFO_DELIEVER_CODE_MASK;
+        intr_fields |= INTR_INFO_DELIVER_CODE_MASK;
      }
-    
+
+    if(ilen)
+      __vmwrite(VM_ENTRY_INSTRUCTION_LEN, ilen);
+
     __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields);
     return 0;
 }
 
-static inline int vmx_inject_exception(struct vcpu *v, int trap, int 
error_code)
+static inline int vmx_inject_hw_exception(struct vcpu *v, int trap, int 
error_code)
 {
     v->arch.hvm_vmx.vector_injected = 1;
-    return __vmx_inject_exception(v, trap, INTR_TYPE_EXCEPTION, error_code);
+    return __vmx_inject_exception(v, trap, INTR_TYPE_HW_EXCEPTION,
+                                 error_code, 0);
+}
+
+static inline int vmx_inject_sw_exception(struct vcpu *v, int trap, int 
instruction_len) {
+     v->arch.hvm_vmx.vector_injected=1;
+     return __vmx_inject_exception(v, trap, INTR_TYPE_SW_EXCEPTION,
+                                  VMX_DELIVER_NO_ERROR_CODE,
+                                  instruction_len);
 }
 
 static inline int vmx_inject_extint(struct vcpu *v, int trap, int error_code)
 {
-    __vmx_inject_exception(v, trap, INTR_TYPE_EXT_INTR, error_code);
+    __vmx_inject_exception(v, trap, INTR_TYPE_EXT_INTR, error_code, 0);
     __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
 
     return 0;
@@ -452,14 +464,14 @@ static inline int vmx_inject_extint(stru
 
 static inline int vmx_reflect_exception(struct vcpu *v)
 {
-    int error_code, vector;
-
-    __vmread(VM_EXIT_INTR_INFO, &vector);
-    if (vector & INTR_INFO_DELIEVER_CODE_MASK)
+    int error_code, intr_info, vector;
+
+    __vmread(VM_EXIT_INTR_INFO, &intr_info);
+    vector = intr_info & 0xff;
+    if (intr_info & INTR_INFO_DELIVER_CODE_MASK)
         __vmread(VM_EXIT_INTR_ERROR_CODE, &error_code);
     else
         error_code = VMX_DELIVER_NO_ERROR_CODE;
-    vector &= 0xff;
 
 #ifndef NDEBUG
     {
@@ -472,7 +484,19 @@ static inline int vmx_reflect_exception(
     }
 #endif /* NDEBUG */
 
-    vmx_inject_exception(v, vector, error_code);
+    /* According to Intel Virtualization Technology Specification for
+       the IA-32 Intel Architecture (C97063-002 April 2005), section
+       2.8.3, SW_EXCEPTION should be used for #BP and #OV, and
+       HW_EXCPEPTION used for everything else.  The main difference
+       appears to be that for SW_EXCEPTION, the EIP/RIP is incremented
+       by VM_ENTER_INSTRUCTION_LEN bytes, whereas for HW_EXCEPTION, 
+       it is not.  */
+    if((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_SW_EXCEPTION) {
+      int ilen;
+      __vmread(VM_EXIT_INSTRUCTION_LEN, &ilen);
+      vmx_inject_sw_exception(v, vector, ilen);
+    } else
+      vmx_inject_hw_exception(v, vector, error_code);
     return 0;
 }
 

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