# 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
|