diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index f78dc9d5e4..404dcfe5ab 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -2800,6 +2800,33 @@ static int vmx_handle_eoi_write(void) return 0; } +/* + * Propagate VM_EXIT_INTR_INFO to VM_ENTRY_INTR_INFO. Used to mirror an + * intercepted exception back to the guest as if Xen hadn't intercepted it. + * + * It is the callers responsibility to ensure that this function is only used + * in the context of an appropriate vmexit. + */ +static void vmx_propagate_intr(void) +{ + unsigned long intr, tmp; + + __vmread(VM_EXIT_INTR_INFO, &intr); + + ASSERT(intr & INTR_INFO_VALID_MASK); + + __vmwrite(VM_ENTRY_INTR_INFO, intr); + + if ( intr & INTR_INFO_DELIVER_CODE_MASK ) + { + __vmread(VM_EXIT_INTR_ERROR_CODE, &tmp); + __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, tmp); + } + + __vmread(VM_EXIT_INSTRUCTION_LEN, &tmp); + __vmwrite(VM_ENTRY_INSTRUCTION_LEN, tmp); +} + static void vmx_idtv_reinject(unsigned long idtv_info) { @@ -3048,7 +3075,7 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) HVMTRACE_1D(TRAP_DEBUG, exit_qualification); write_debugreg(6, exit_qualification | DR_STATUS_RESERVED_ONE); if ( !v->domain->debugger_attached ) - hvm_inject_hw_exception(vector, HVM_DELIVER_NO_ERROR_CODE); + vmx_propagate_intr(); else domain_pause_for_debugger(); break; @@ -3117,8 +3144,7 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) break; case TRAP_alignment_check: HVMTRACE_1D(TRAP, vector); - __vmread(VM_EXIT_INTR_ERROR_CODE, &ecode); - hvm_inject_hw_exception(vector, ecode); + vmx_propagate_intr(); break; case TRAP_nmi: if ( MASK_EXTR(intr_info, INTR_INFO_INTR_TYPE_MASK) !=