[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] Single step in HVM domU on Intel machine may see wrong DB6
Jan Beulich wrote on 2014-03-05: >>>> On 05.03.14 at 03:22, "Zhang, Yang Z" <yang.z.zhang@xxxxxxxxx> wrote: >> Jan Beulich wrote on 2014-02-27: >>>>>> On 27.02.14 at 02:31, "Zhang, Yang Z" <yang.z.zhang@xxxxxxxxx> > wrote: >>>> Jan Beulich wrote on 2014-02-27: >>>>>>>> On 26.02.14 at 06:15, "Zhang, Yang Z" <yang.z.zhang@xxxxxxxxx> >>> wrote: >>>>>> @@ -2690,9 +2688,13 @@ void vmx_vmexit_handler(struct >>> cpu_user_regs >>>>> *regs) >>>>>> __vmread(EXIT_QUALIFICATION, &exit_qualification); >>>>>> HVMTRACE_1D(TRAP_DEBUG, exit_qualification); >>>>>> write_debugreg(6, exit_qualification | 0xffff0ff0); >>>>>> - if ( !v->domain->debugger_attached || >>>>>> cpu_has_monitor_trap_flag ) - goto exit_and_crash; - >>>>>> domain_pause_for_debugger(); + if ( >>>>>> v->domain->debugger_attached ) + >>>>>> domain_pause_for_debugger(); + else + { + >>>>>> __restore_debug_registers(v); + >>>>>> hvm_inject_hw_exception(TRAP_debug, >>> HVM_DELIVER_NO_ERROR_CODE); + >>>>>> } >>>>> >>>>> I suppose you need to set DR6.BS after restoring the reigsters? >>>> >>>> Right but is not enough. If flag_dr_dirty is set, we need to >>>> restore register from hardware. Conversely, restore is from >>>> debugreg and set >>>> DR6 to exit_qualification. >>> >>> After some more thought, I in fact doubt that restoring the debug >>> registers is in line with the current model: We should simply set >>> DR6.BS in the in-memory copy when the debug registers aren't live >>> yet (and it doesn't hurt to always do that). And since DR6 bits >>> generally are sticky, I think exit_qualification actually needs to >>> be or-ed into the >> in-memory copy. >> >> Will guest be confused to see the DR6.BS always set? > > It certainly shouldn't when single stepping. And as long as the guest > clears the bit while handling the single step trap, it won't see it set on > other kinds of #DB. > After all that's how hardware behaves. > >>> And presumably we would be better off if we dropped the >>> interception of TRAP_debug once we restored the debug registers. >> >> Yes, it's unnecessary to trap into hypervisor always. Also, if we >> set DR6.BS always, I guess there is no need to intercept the TRAP_debug. > > Oh, perhaps you misunderstood then: I didn't suggest to always set that flag. > What I suggested is that during the intercepted TRAP_debug we should > or exit_qualification (which ought to have BS set when single stepping > with no other breakpoint enabled in DR7) into the in-memory copy of > DR6. Once the intercept got dropped (as also suggested), hardware > would again take care of setting DR6 correctly. Oh, I am sorry, I misunderstand you. How about the following changes: Intercept the TRAP_debug when schedule out and drop it after restoring VCPU's DR register into hardware. diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index b128e81..5784dd1 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -372,6 +372,10 @@ static void vmx_save_dr(struct vcpu *v) v->arch.hvm_vmx.exec_control |= CPU_BASED_MOV_DR_EXITING; vmx_update_cpu_exec_control(v); + /* Trap debug for signle stepping. */ + v->arch.hvm_vmx.exception_bitmap |= 1 << TRAP_debug; + vmx_update_exception_bitmap(v); + v->arch.debugreg[0] = read_debugreg(0); v->arch.debugreg[1] = read_debugreg(1); v->arch.debugreg[2] = read_debugreg(2); @@ -388,6 +392,13 @@ static void __restore_debug_registers(struct vcpu *v) v->arch.hvm_vcpu.flag_dr_dirty = 1; + /* + * After restore, hardware has the right context. + * So no need to trap debug anymore. + */ + v->arch.hvm_vmx.exception_bitmap |= ~(1 << TRAP_debug); + vmx_update_exception_bitmap(v); + write_debugreg(0, v->arch.debugreg[0]); write_debugreg(1, v->arch.debugreg[1]); write_debugreg(2, v->arch.debugreg[2]); @@ -1171,8 +1182,6 @@ void vmx_update_debug_state(struct vcpu *v) unsigned long mask; mask = 1u << TRAP_int3; - if ( !cpu_has_monitor_trap_flag ) - mask |= 1u << TRAP_debug; if ( v->arch.hvm_vcpu.debug_state_latch ) v->arch.hvm_vmx.exception_bitmap |= mask; @@ -2689,10 +2698,18 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) */ __vmread(EXIT_QUALIFICATION, &exit_qualification); HVMTRACE_1D(TRAP_DEBUG, exit_qualification); - write_debugreg(6, exit_qualification | 0xffff0ff0); - if ( !v->domain->debugger_attached || cpu_has_monitor_trap_flag ) - goto exit_and_crash; - domain_pause_for_debugger(); + exit_qualification |= 0xffff0ff0; + if ( v->domain->debugger_attached ) + { + write_debugreg(6, exit_qualification); + domain_pause_for_debugger(); + } + else + { + __restore_debug_registers(v); + write_debugreg(6, exit_qualification | read_debugreg(6)); + hvm_inject_hw_exception(TRAP_debug, HVM_DELIVER_NO_ERROR_CODE); + } break; case TRAP_int3: { diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index dcc3483..0d76d8c 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -378,7 +378,8 @@ static inline int hvm_event_pending(struct vcpu *v) (cpu_has_xsave ? X86_CR4_OSXSAVE : 0)))) /* These exceptions must always be intercepted. */ -#define HVM_TRAP_MASK ((1U << TRAP_machine_check) | (1U << TRAP_invalid_op)) +#define HVM_TRAP_MASK ((1U << TRAP_machine_check) | (1U << TRAP_invalid_op) |\ + (1U << TRAP_debug)) /* * x86 event types. This enumeration is valid for: Best regards, Yang _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |