FRED provides PENDING_DBG in the the stack frame, avoiding the need to read %dr6 manually.
Rename do_debug() to handle_DB(), and update it to take a dbg field using positive polarity. Introduce a new handle_DB_IDT() which reads %dr6. No functional change. Signed-off-by: Andrew Cooper <andrew.coop...@citrix.com> --- CC: Jan Beulich <jbeul...@suse.com> CC: Roger Pau Monné <roger....@citrix.com> v2: * New --- xen/arch/x86/traps.c | 28 +++++++++++++++++----------- xen/arch/x86/x86_64/entry.S | 2 +- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 7ae46ae20f98..0372f1c386a8 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -1992,14 +1992,11 @@ void asmlinkage do_device_not_available(struct cpu_user_regs *regs) void nocall sysenter_eflags_saved(void); -void asmlinkage do_debug(struct cpu_user_regs *regs) +/* Handle #DB. @dbg is PENDING_DBG, a.k.a. %dr6 with positive polarity. */ +static void handle_DB(struct cpu_user_regs *regs, unsigned long dbg) { - unsigned long dr6; struct vcpu *v = current; - /* Stash dr6 as early as possible. */ - dr6 = read_debugreg(6); - /* * At the time of writing (March 2018), on the subject of %dr6: * @@ -2066,13 +2063,13 @@ void asmlinkage do_debug(struct cpu_user_regs *regs) * If however we do, safety measures need to be enacted. Use a big * hammer and clear all debug settings. */ - if ( dr6 & (DR_TRAP3 | DR_TRAP2 | DR_TRAP1 | DR_TRAP0) ) + if ( dbg & (DR_TRAP3 | DR_TRAP2 | DR_TRAP1 | DR_TRAP0) ) { unsigned int bp, dr7 = read_debugreg(7); for ( bp = 0; bp < 4; ++bp ) { - if ( (dr6 & (1u << bp)) && /* Breakpoint triggered? */ + if ( (dbg & (1u << bp)) && /* Breakpoint triggered? */ (dr7 & (3u << (bp * DR_ENABLE_SIZE))) && /* Enabled? */ ((dr7 & (3u << ((bp * DR_CONTROL_SIZE) + /* Insn? */ DR_CONTROL_SHIFT))) == DR_RW_EXECUTE) ) @@ -2093,9 +2090,9 @@ void asmlinkage do_debug(struct cpu_user_regs *regs) * so ensure the message is ratelimited. */ gprintk(XENLOG_WARNING, - "Hit #DB in Xen context: %04x:%p [%ps], stk %04x:%p, dr6 %lx\n", + "Hit #DB in Xen context: %04x:%p [%ps], stk %04x:%p, dbg %lx\n", regs->cs, _p(regs->rip), _p(regs->rip), - regs->ss, _p(regs->rsp), dr6); + regs->ss, _p(regs->rsp), dbg); return; } @@ -2107,7 +2104,7 @@ void asmlinkage do_debug(struct cpu_user_regs *regs) * by debugging actions completed behind it's back. */ v->arch.dr6 = x86_merge_dr6(v->domain->arch.cpu_policy, - v->arch.dr6, dr6 ^ X86_DR6_DEFAULT); + v->arch.dr6, dbg); if ( guest_kernel_mode(v, regs) && v->domain->debugger_attached ) { @@ -2115,7 +2112,16 @@ void asmlinkage do_debug(struct cpu_user_regs *regs) return; } - pv_inject_DB(dr6 ^ X86_DR6_DEFAULT); + pv_inject_DB(dbg); +} + +/* + * When using IDT delivery, it is our responsibility to read %dr6. Convert it + * to positive polarity. + */ +void asmlinkage handle_DB_IDT(struct cpu_user_regs *regs) +{ + handle_DB(regs, read_debugreg(6) ^ X86_DR6_DEFAULT); } void asmlinkage do_entry_CP(struct cpu_user_regs *regs) diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 39c7b9d17f9e..789687488c5f 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -1171,7 +1171,7 @@ FUNC(handle_ist_exception) .L_ ## vec ## _done: DISPATCH(X86_EXC_NMI, do_nmi) - DISPATCH(X86_EXC_DB, do_debug) + DISPATCH(X86_EXC_DB, handle_DB_IDT) DISPATCH(X86_EXC_MC, do_machine_check) #undef DISPATCH -- 2.39.5