[PATCH 10/10] arm64: Check DAIF (and PMR) at task-switch time
Mark Rutland
mark.rutland at arm.com
Tue Apr 7 06:16:50 PDT 2026
When __switch_to() switches from a 'prev' task to a 'next' task, various
pieces of CPU state are expected to have specific values, such that
these do not need to be saved/restored. If any of these hold an
unexpected value when switching away from the prev task, they could lead
to surprising behaviour in the context of the next task, and it would be
difficult to determine where they were configured to their unexpected
value.
Add some checks for DAIF and PMR at task-switch time so that we can
detect such issues.
Signed-off-by: Mark Rutland <mark.rutland at arm.com>
Cc: Andy Lutomirski <luto at kernel.org>
Cc: Catalin Marinas <catalin.marinas at arm.com>
Cc: Jinjie Ruan <ruanjinjie at huawei.com>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Thomas Gleixner <tglx at kernel.org>
Cc: Vladimir Murzin <vladimir.murzin at arm.com>
Cc: Will Deacon <will at kernel.org>
---
arch/arm64/kernel/process.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 489554931231e..ba9038434d2fb 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -699,6 +699,29 @@ void update_sctlr_el1(u64 sctlr)
isb();
}
+static inline void debug_switch_state(void)
+{
+ if (system_uses_irq_prio_masking()) {
+ unsigned long daif_expected = 0;
+ unsigned long daif_actual = read_sysreg(daif);
+ unsigned long pmr_expected = GIC_PRIO_IRQOFF;
+ unsigned long pmr_actual = read_sysreg_s(SYS_ICC_PMR_EL1);
+
+ WARN_ONCE(daif_actual != daif_expected ||
+ pmr_actual != pmr_expected,
+ "Unexpected DAIF + PMR: 0x%lx + 0x%lx (expected 0x%lx + 0x%lx)\n",
+ daif_actual, pmr_actual,
+ daif_expected, pmr_expected);
+ } else {
+ unsigned long daif_expected = DAIF_PROCCTX_NOIRQ;
+ unsigned long daif_actual = read_sysreg(daif);
+
+ WARN_ONCE(daif_actual != daif_expected,
+ "Unexpected DAIF value: 0x%lx (expected 0x%lx)\n",
+ daif_actual, daif_expected);
+ }
+}
+
/*
* Thread switching.
*/
@@ -708,6 +731,8 @@ struct task_struct *__switch_to(struct task_struct *prev,
{
struct task_struct *last;
+ debug_switch_state();
+
fpsimd_thread_switch(next);
tls_thread_switch(next);
hw_breakpoint_thread_switch(next);
--
2.30.2
More information about the linux-arm-kernel
mailing list