[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 2/3] VMX: Fix the mistake of exception execution
Fix the mistake for debug exception(#DB), overflow exception(#OF) and INT3(#BP), INTn instruction emulation. Introduce new function vmx_inject_sw_exception() which deliver the software excetion, software interrupt and privileged software exception. Split hardware exception as a seperate function(old function vmx_inject_hw_exception()). According to instruction length, to distinguish INT3 is generated by opcode 'CC' or 'CD ib =3', so do INTO and #DB(debug exception). Note: * For INTn (CD ib), it should use type 4 (software interrupt). * For INT3 (CC; NOT CD ib with ib=3) and INTO (CE; NOT CD ib with ib=4), it should use type 6 (software exception). * For other exceptions (#DE, #DB, #BR, #UD, #NM, #TS, #NP, #SS, #GP, #PF, #MF, #AC, #MC, and #XM), it should use type 3 (hardware exception). * In the unlikely event that you are emulating the undocumented opcode F1 (informally called INT1 or ICEBP), it would use type 5 (privileged software exception). Signed-off-by: Xudong Hao <xudong.hao@xxxxxxxxx> Signed-off-by: Eddie Dong <eddie.dong@xxxxxxxxx> Signed-off-by: Xiantao Zhang <xiantao.zhang@xxxxxxxxx> --- xen/arch/x86/hvm/vmx/vmx.c | 141 +++++++++++++++++++++++++++++++------ xen/include/asm-x86/hvm/hvm.h | 1 + xen/include/asm-x86/hvm/vmx/vmx.h | 1 + 3 files changed, 122 insertions(+), 21 deletions(-) diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index e15b7a4..8d78ffa 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -1344,12 +1344,27 @@ static void __vmx_inject_exception(int trap, int type, int error_code) curr->arch.hvm_vmx.vmx_emulate = 1; } -void vmx_inject_hw_exception(int trap, int error_code) +/* + * Generate the virtual event to guest. + * NOTE: + * This is for processor execution generated exceptions, + * and handle all software exception/interrupt, which include: + * - INT 3(CC), INTO (CE) instruction emulation, which should + * use X86_EVENTTYPE_SW_EXCEPTION; + * - INT nn (CD nn) instruction emulation, which should use + * X86_EVENTTYPE_SW_INTERRUPT as interrupt type; + * - opcode 0xf1 generated #DB should use privileged software + * exception. + * + * The caller of this function should set correct instruction + * length. + */ +void vmx_inject_sw_exception(int trap, int inslen, int error_code) { unsigned long intr_info; struct vcpu *curr = current; - int type = X86_EVENTTYPE_HW_EXCEPTION; + int type = X86_EVENTTYPE_SW_EXCEPTION; if ( nestedhvm_vcpu_in_guestmode(curr) ) intr_info = vcpu_2_nvmx(curr).intr.intr_info; @@ -1358,17 +1373,6 @@ void vmx_inject_hw_exception(int trap, int error_code) switch ( trap ) { - case TRAP_debug: - type = X86_EVENTTYPE_SW_EXCEPTION; - if ( guest_cpu_user_regs()->eflags & X86_EFLAGS_TF ) - { - __restore_debug_registers(curr); - write_debugreg(6, read_debugreg(6) | 0x4000); - } - if ( cpu_has_monitor_trap_flag ) - break; - /* fall through */ - case TRAP_int3: if ( curr->domain->debugger_attached ) { @@ -1377,16 +1381,75 @@ void vmx_inject_hw_exception(int trap, int error_code) return; } - type = X86_EVENTTYPE_SW_EXCEPTION; - __vmwrite(VM_ENTRY_INSTRUCTION_LEN, 1); /* int3 */ + if ( inslen == 2 ) + type = X86_EVENTTYPE_SW_INTERRUPT; /* CD ib with ib=3 */ + break; + + case TRAP_overflow: + if ( inslen == 2 ) + type = X86_EVENTTYPE_SW_INTERRUPT; /* CD ib with ib=4 */ + break; + + case TRAP_debug: + /* Handle DB generated by 0xf1 */ + type = X86_EVENTTYPE_PRI_SW_EXCEPTION; break; default: - if ( trap > TRAP_last_reserved ) + if ( trap > TRAP_last_reserved ) /* int imm8 */ + { + type = X86_EVENTTYPE_SW_INTERRUPT; + } + break; + + __vmwrite(VM_ENTRY_INSTRUCTION_LEN, inslen); + + } + + if ( nestedhvm_vcpu_in_guestmode(curr) && + nvmx_intercepts_exception(curr, trap, error_code) ) + { + nvmx_enqueue_n2_exceptions (curr, + INTR_INFO_VALID_MASK | (type<<8) | trap, + error_code); + return; + } + else + __vmx_inject_exception(trap, type, error_code); + + HVMTRACE_2D(INJ_EXC, trap, error_code); +} + +/* + * Generate the virtual event to guest. + * NOTE: + * This is only for hardware exceptions type delivery. + */ +void vmx_inject_hw_exception(int trap, int error_code) +{ + unsigned long intr_info; + struct vcpu *curr = current; + + int type = X86_EVENTTYPE_HW_EXCEPTION; + + if ( nestedhvm_vcpu_in_guestmode(curr) ) + intr_info = vcpu_2_nvmx(curr).intr.intr_info; + else + intr_info = __vmread(VM_ENTRY_INTR_INFO); + + switch ( trap ) + { + case TRAP_debug: + if ( guest_cpu_user_regs()->eflags & X86_EFLAGS_TF ) { - type = X86_EVENTTYPE_SW_EXCEPTION; - __vmwrite(VM_ENTRY_INSTRUCTION_LEN, 2); /* int imm8 */ + __restore_debug_registers(curr); + write_debugreg(6, read_debugreg(6) | 0x4000); } + if ( cpu_has_monitor_trap_flag ) + break; + /* fall through */ + + default: break; } @@ -1455,12 +1518,47 @@ void vmx_inject_nmi(void) } static void vmx_inject_exception( - unsigned int trapnr, int errcode, unsigned long cr2) + unsigned int trapnr, int inslen, int errcode, unsigned long cr2) { if ( trapnr == TRAP_page_fault ) current->arch.hvm_vcpu.guest_cr[2] = cr2; - vmx_inject_hw_exception(trapnr, errcode); + switch(trapnr) + { + case TRAP_divide_error: + case TRAP_bounds: + case TRAP_invalid_op: + case TRAP_no_device: + case TRAP_invalid_tss: + case TRAP_no_segment: + case TRAP_stack_error: + case TRAP_gp_fault: + case TRAP_page_fault: + case TRAP_copro_error: + case TRAP_alignment_check: + case TRAP_machine_check: + case TRAP_simd_error: + vmx_inject_hw_exception(trapnr, errcode); + break; + + case TRAP_debug: + if ( inslen != 0 ) + /* icebp: opcode 0xf1 generate #DB, should be a privileged + * software exception */ + vmx_inject_sw_exception(trapnr, inslen, errcode); + else + vmx_inject_hw_exception(trapnr, errcode); + break; + + case TRAP_int3: + case TRAP_overflow: + vmx_inject_sw_exception(trapnr, inslen, errcode); + break; + + default: + vmx_inject_sw_exception(trapnr, inslen, errcode); + break; + } } static int vmx_event_pending(struct vcpu *v) @@ -2440,7 +2538,8 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) if ( handled < 0 ) { - vmx_inject_exception(TRAP_int3, HVM_DELIVER_NO_ERROR_CODE, 0); + vmx_inject_exception(TRAP_int3, + __vmread(VM_EXIT_INSTRUCTION_LEN), HVM_DELIVER_NO_ERROR_CODE, 0); break; } else if ( handled ) diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index 3ba1615..c65ad09 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -370,6 +370,7 @@ static inline int hvm_do_pmu_interrupt(struct cpu_user_regs *regs) #define X86_EVENTTYPE_NMI 2 /* NMI */ #define X86_EVENTTYPE_HW_EXCEPTION 3 /* hardware exception */ #define X86_EVENTTYPE_SW_INTERRUPT 4 /* software interrupt */ +#define X86_EVENTTYPE_PRI_SW_EXCEPTION 5 /* privileged software exception */ #define X86_EVENTTYPE_SW_EXCEPTION 6 /* software exception */ int hvm_event_needs_reinjection(uint8_t type, uint8_t vector); diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h index f003f84..61078a6 100644 --- a/xen/include/asm-x86/hvm/vmx/vmx.h +++ b/xen/include/asm-x86/hvm/vmx/vmx.h @@ -387,6 +387,7 @@ static inline int __vmxon(u64 addr) return rc; } +void vmx_inject_sw_exception(int trap, int inslen, int error_code); void vmx_inject_hw_exception(int trap, int error_code); void vmx_inject_extint(int trap); void vmx_inject_nmi(void); -- 1.5.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |