[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |