arm64: fix hardware single-stepping from EL1
The main issue is that debug exceptions must to be disabled for the entire duration that SS bit in MDSCR_EL1 is set. Otherwise, a single-step exception will be generated immediately. This can occur before returning from the debugger (when MDSCR is written to) or before re-entering it after the single-step (when debug exceptions are unmasked in the exception handler). Solve this by delaying the unmask to C code for EL1, and avoid unmasking at all while handling debug exceptions, thus avoiding any recursive debug traps. Reviewed by: markj, jhb MFC after: 5 days Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D28944
This commit is contained in:
parent
79fbd48378
commit
874635e381
@ -186,6 +186,9 @@ void
|
||||
kdb_cpu_set_singlestep(void)
|
||||
{
|
||||
|
||||
KASSERT((READ_SPECIALREG(daif) & PSR_D) == PSR_D,
|
||||
("%s: debug exceptions are not masked", __func__));
|
||||
|
||||
kdb_frame->tf_spsr |= DBG_SPSR_SS;
|
||||
WRITE_SPECIALREG(mdscr_el1, READ_SPECIALREG(mdscr_el1) |
|
||||
DBG_MDSCR_SS | DBG_MDSCR_KDE);
|
||||
@ -205,6 +208,9 @@ void
|
||||
kdb_cpu_clear_singlestep(void)
|
||||
{
|
||||
|
||||
KASSERT((READ_SPECIALREG(daif) & PSR_D) == PSR_D,
|
||||
("%s: debug exceptions are not masked", __func__));
|
||||
|
||||
WRITE_SPECIALREG(mdscr_el1, READ_SPECIALREG(mdscr_el1) &
|
||||
~(DBG_MDSCR_SS | DBG_MDSCR_KDE));
|
||||
|
||||
|
@ -75,8 +75,12 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
ldr x0, [x18, #(PC_CURTHREAD)]
|
||||
bl dbg_monitor_enter
|
||||
.endif
|
||||
msr daifclr, #8 /* Enable the debug exception */
|
||||
.endif
|
||||
/*
|
||||
* For EL1, debug exceptions are conditionally unmasked in
|
||||
* do_el1h_sync().
|
||||
*/
|
||||
.endm
|
||||
|
||||
.macro restore_registers el
|
||||
|
@ -377,6 +377,14 @@ do_el1h_sync(struct thread *td, struct trapframe *frame)
|
||||
"do_el1_sync: curthread: %p, esr %lx, elr: %lx, frame: %p", td,
|
||||
esr, frame->tf_elr, frame);
|
||||
|
||||
/*
|
||||
* Enable debug exceptions if we aren't already handling one. They will
|
||||
* be masked again in the exception handler's epilogue.
|
||||
*/
|
||||
if (exception != EXCP_BRK && exception != EXCP_WATCHPT_EL1 &&
|
||||
exception != EXCP_SOFTSTP_EL1)
|
||||
dbg_enable();
|
||||
|
||||
switch (exception) {
|
||||
case EXCP_FP_SIMD:
|
||||
case EXCP_TRAP_FP:
|
||||
|
Loading…
Reference in New Issue
Block a user