Skip to content

Commit 8d13386

Browse files
mrutland-armctmarinas
authored andcommitted
arm64: Check DAIF (and PMR) at task-switch time
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 <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: Jinjie Ruan <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Vladimir Murzin <[email protected]> Cc: Will Deacon <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Signed-off-by: Catalin Marinas <[email protected]>
1 parent ae65411 commit 8d13386

1 file changed

Lines changed: 25 additions & 0 deletions

File tree

arch/arm64/kernel/process.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,29 @@ void update_sctlr_el1(u64 sctlr)
699699
isb();
700700
}
701701

702+
static inline void debug_switch_state(void)
703+
{
704+
if (system_uses_irq_prio_masking()) {
705+
unsigned long daif_expected = 0;
706+
unsigned long daif_actual = read_sysreg(daif);
707+
unsigned long pmr_expected = GIC_PRIO_IRQOFF;
708+
unsigned long pmr_actual = read_sysreg_s(SYS_ICC_PMR_EL1);
709+
710+
WARN_ONCE(daif_actual != daif_expected ||
711+
pmr_actual != pmr_expected,
712+
"Unexpected DAIF + PMR: 0x%lx + 0x%lx (expected 0x%lx + 0x%lx)\n",
713+
daif_actual, pmr_actual,
714+
daif_expected, pmr_expected);
715+
} else {
716+
unsigned long daif_expected = DAIF_PROCCTX_NOIRQ;
717+
unsigned long daif_actual = read_sysreg(daif);
718+
719+
WARN_ONCE(daif_actual != daif_expected,
720+
"Unexpected DAIF value: 0x%lx (expected 0x%lx)\n",
721+
daif_actual, daif_expected);
722+
}
723+
}
724+
702725
/*
703726
* Thread switching.
704727
*/
@@ -708,6 +731,8 @@ struct task_struct *__switch_to(struct task_struct *prev,
708731
{
709732
struct task_struct *last;
710733

734+
debug_switch_state();
735+
711736
fpsimd_thread_switch(next);
712737
tls_thread_switch(next);
713738
hw_breakpoint_thread_switch(next);

0 commit comments

Comments
 (0)