Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <mark.rutland@arm.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Jinjie Ruan <ruanjinjie@huawei.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@kernel.org>
Cc: Vladimir Murzin <vladimir.murzin@arm.com>
Cc: Will Deacon <will@kernel.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

Mark Rutland and committed by
Catalin Marinas
8d13386c ae654112

+25
+25
arch/arm64/kernel/process.c
··· 699 699 isb(); 700 700 } 701 701 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 + 702 725 /* 703 726 * Thread switching. 704 727 */ ··· 730 707 struct task_struct *next) 731 708 { 732 709 struct task_struct *last; 710 + 711 + debug_switch_state(); 733 712 734 713 fpsimd_thread_switch(next); 735 714 tls_thread_switch(next);