aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2024-03-14 14:02:56 +0000
committerAndrew Turner <andrew@FreeBSD.org>2024-07-15 12:23:21 +0000
commit64b0acf87c97d02929f99a14e9d47a4eba2958b4 (patch)
treea808974efb3b6c3778b730eb02d95122631b19ec
parent1ac1e83f189fae2e6bd346ae1abd877ea584192e (diff)
arm64: Mask non-debug exceptions when single stepping
When an exception is pending when single stepping we may execute the handler for that exception rather than the single step handler. This could cause the scheduler to fire to run a new thread. This will mean we single step to a new thread causing unexpected results. Handle this by masking non-debug exceptions. This will cause issues when stepping over instructions that access the DAIF values so future work is needed to handle these cases, but for most code this now works as expected. Reviewed by: jhb Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D44350 (cherry picked from commit ed3c6cd76de8560c46607abe506a03568e9acab2)
-rw-r--r--sys/arm64/arm64/debug_monitor.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/sys/arm64/arm64/debug_monitor.c b/sys/arm64/arm64/debug_monitor.c
index 271f6fc47ea4..380915d5163a 100644
--- a/sys/arm64/arm64/debug_monitor.c
+++ b/sys/arm64/arm64/debug_monitor.c
@@ -194,6 +194,15 @@ kdb_cpu_set_singlestep(void)
("%s: debug exceptions are not masked", __func__));
kdb_frame->tf_spsr |= PSR_SS;
+
+ /*
+ * TODO: Handle single stepping over instructions that access
+ * the DAIF values. On a read the value will be incorrect.
+ */
+ kernel_monitor.dbg_flags &= ~PSR_DAIF;
+ kernel_monitor.dbg_flags |= kdb_frame->tf_spsr & PSR_DAIF;
+ kdb_frame->tf_spsr |= (PSR_A | PSR_I | PSR_F);
+
WRITE_SPECIALREG(mdscr_el1, READ_SPECIALREG(mdscr_el1) |
MDSCR_SS | MDSCR_KDE);
@@ -215,6 +224,9 @@ kdb_cpu_clear_singlestep(void)
KASSERT((READ_SPECIALREG(daif) & PSR_D) == PSR_D,
("%s: debug exceptions are not masked", __func__));
+ kdb_frame->tf_spsr &= ~PSR_DAIF;
+ kdb_frame->tf_spsr |= kernel_monitor.dbg_flags & PSR_DAIF;
+
WRITE_SPECIALREG(mdscr_el1, READ_SPECIALREG(mdscr_el1) &
~(MDSCR_SS | MDSCR_KDE));