[PATCH 3/3] arm64: entry: Exceptions from single-step should leave debug masked
James Morse
james.morse at arm.com
Thu Aug 3 08:15:33 PDT 2017
If we interrupted an instruction being single-stepped we may end up
taking a single-step exception from the interrupt handler. This
confuses single-step users who are typically just waiting for 'the next'
single step exception before re-enabling {break,watch}points.
Returning from the interrupt causes us to hit the {break,watch}point
again.
For the least-surprising results, lets confine single-step to its
intended context.
>From the ARM-ARM DDI 0487B.a, D.12.5 'Behaviour in the active-not-pending
state's 'If the PE takes an exception' section, we enter the inactive
state because the exception sets PSTATE.D.
D2.12.6 'Entering the active-pending state', from the inactive state, we
re-enter active-pending if we clear PSTATE.D. This causes a debug
single step exception and we we step the exception handler.
Change the EL1 entry.S handlers to inherit their debug state if the
SPSR.SS bit is clear, instead of unconditionally unmasking it.
This bit will be set if we took this exception instead of stepping an
instruction.
This isn't needed for the EL0 entry.S handlers as we will have cleared
MDSCR_EL1.SS on entry from EL0.
Signed-off-by: James Morse <james.morse at arm.com>
CC: Pratyush Anand <panand at redhat.com>
CC: AKASHI Takahiro <takahiro.akashi at linaro.org>
---
arch/arm64/include/asm/assembler.h | 14 ++++++++++++++
arch/arm64/kernel/entry.S | 10 +++++-----
2 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index 1c490c578a2e..96f01cc33d0e 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -25,6 +25,7 @@
#include <asm/asm-offsets.h>
#include <asm/cpufeature.h>
+#include <asm/debug-monitors.h>
#include <asm/mmu_context.h>
#include <asm/page.h>
#include <asm/pgtable-hwdef.h>
@@ -66,6 +67,19 @@
msr daifclr, #8
.endm
+ /*
+ * If we interrupted single step from EL1 then we may end up stepping
+ * the exception handler. Leave debug masked. Otherwise inherit
+ * the value we interrupted.
+ */
+ .macro inherit_dbg, pstate, reg
+ mov_q \reg, (PSR_D_BIT | DBG_SPSR_SS)
+ and \reg, \reg, \pstate
+ cbnz \reg, 9998f
+ enable_dbg
+9998:
+ .endm
+
.macro disable_step_tsk, flgs, tmp
tbz \flgs, #TIF_SINGLESTEP, 9990f
mrs \tmp, mdscr_el1
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index eed2d51e16e6..9788bb47a7f7 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -431,7 +431,7 @@ el1_da:
* Data abort handling
*/
mrs x3, far_el1
- enable_dbg
+ inherit_dbg, pstate=x23 reg=x0
// re-enable interrupts if they were enabled in the aborted context
tbnz x23, #7, 1f // PSR_I_BIT
enable_irq
@@ -446,14 +446,14 @@ el1_sp_pc:
* Stack or PC alignment exception handling
*/
mrs x0, far_el1
- enable_dbg
+ inherit_dbg, pstate=x23 reg=x2
mov x2, sp
b do_sp_pc_abort
el1_undef:
/*
* Undefined instruction
*/
- enable_dbg
+ inherit_dbg, pstate=x23 reg=x0
mov x0, sp
b do_undefinstr
el1_dbg:
@@ -469,7 +469,7 @@ el1_dbg:
kernel_exit 1
el1_inv:
// TODO: add support for undefined instructions in kernel mode
- enable_dbg
+ inherit_dbg, pstate=x23 reg=x0
mov x0, sp
mov x2, x1
mov x1, #BAD_SYNC
@@ -479,7 +479,7 @@ ENDPROC(el1_sync)
.align 6
el1_irq:
kernel_entry 1
- enable_dbg
+ inherit_dbg, pstate=x23 reg=x0
#ifdef CONFIG_TRACE_IRQFLAGS
bl trace_hardirqs_off
#endif
--
2.13.3
More information about the linux-arm-kernel
mailing list