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.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@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 545c42a10862..3fd0f5709a52 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:
*
@@ -2067,13 +2064,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) )
@@ -2094,9 +2091,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;
}
@@ -2108,7 +2105,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 )
{
@@ -2116,7 +2113,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