From mboxrd@z Thu Jan 1 00:00:00 1970 From: Xudong Hao Subject: [PATCH v2 2/4] VMX: Fix the mistake of exception execution Date: Wed, 30 May 2012 10:35:46 +0800 Message-ID: <1338345347-22433-3-git-send-email-xudong.hao@intel.com> References: <1338345347-22433-1-git-send-email-xudong.hao@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1338345347-22433-1-git-send-email-xudong.hao@intel.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: JBeulich@suse.com, keir.xen@gmail.com Cc: aravindh@virtuata.com, eddie.dong@intel.com, xen-devel@lists.xen.org, Xudong Hao , Ian.Jackson@eu.citrix.com, Xiantao Zhang List-Id: xen-devel@lists.xenproject.org Fix the mistake for debug exception(#DB), overflow exception(#OF) and INT3(#BP), INTn instruction emulation. Add inslen field in struct hvm_trap. 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 Signed-off-by: Eddie Dong Signed-off-by: Xiantao Zhang --- xen/arch/x86/hvm/vmx/vmx.c | 43 ++++++++++++++++++++++++++++++++++++++++- xen/include/asm-x86/hvm/hvm.h | 2 + 2 files changed, 44 insertions(+), 1 deletions(-) diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index c96d18b..cf08a11 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -1381,6 +1381,19 @@ void vmx_inject_nmi(void) HVM_DELIVER_NO_ERROR_CODE); } +/* + * Generate the virtual event to guest. + * NOTE: + * This is for processor execution generated exceptions, + * and handle #DB hardware exception and 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. + */ static void vmx_inject_trap(struct hvm_trap *trap) { unsigned long intr_info; @@ -1399,6 +1412,12 @@ static void vmx_inject_trap(struct hvm_trap *trap) switch ( _trap.vector ) { case TRAP_debug: + _trap.type = X86_EVENTTYPE_HW_EXCEPTION; + if ( _trap.inslen != 1 ) { + _trap.type = X86_EVENTTYPE_PRI_SW_EXCEPTION; /* opcode 0xf1 */ + __vmwrite(VM_ENTRY_INSTRUCTION_LEN, _trap.inslen); + } + if ( guest_cpu_user_regs()->eflags & X86_EFLAGS_TF ) { __restore_debug_registers(curr); @@ -1414,6 +1433,27 @@ static void vmx_inject_trap(struct hvm_trap *trap) domain_pause_for_debugger(); return; } + _trap.type = X86_EVENTTYPE_SW_EXCEPTION; /* CC */ + if ( _trap.inslen != 1 ) + _trap.type = X86_EVENTTYPE_SW_INTERRUPT; /* CD ib with ib=3 */ + __vmwrite(VM_ENTRY_INSTRUCTION_LEN, _trap.inslen); + break; + + case TRAP_overflow: + _trap.type = X86_EVENTTYPE_SW_EXCEPTION; /* CE */ + if ( _trap.inslen != 1 ) + _trap.type = X86_EVENTTYPE_SW_INTERRUPT; /* CD ib with ib=4 */ + __vmwrite(VM_ENTRY_INSTRUCTION_LEN, _trap.inslen); + break; + + default: + if ( _trap.vector > TRAP_last_reserved ) /* int imm8 */ + { + _trap.type = X86_EVENTTYPE_SW_INTERRUPT; + __vmwrite(VM_ENTRY_INSTRUCTION_LEN, _trap.inslen); + } + break; + } if ( unlikely(intr_info & INTR_INFO_VALID_MASK) && @@ -2424,7 +2464,8 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) struct hvm_trap trap = { .vector = TRAP_int3, .type = X86_EVENTTYPE_SW_EXCEPTION, - .error_code = HVM_DELIVER_NO_ERROR_CODE + .error_code = HVM_DELIVER_NO_ERROR_CODE, + .inslen = __vmread(VM_EXIT_INSTRUCTION_LEN) }; hvm_inject_trap(&trap); break; diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index 65f7e20..a3d8bf1 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -76,6 +76,7 @@ struct hvm_trap { unsigned int type; /* X86_EVENTTYPE_* */ int error_code; /* HVM_DELIVER_NO_ERROR_CODE if n/a */ unsigned long cr2; /* Only for TRAP_page_fault h/w exception */ + int inslen; /* Instruction length */ }; /* @@ -375,6 +376,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); -- 1.5.5