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

arm64: make irq_stack_ptr more robust

Switching between stacks is only valid if we are tracing ourselves while on the
irq_stack, so it is only valid when in current and non-preemptible context,
otherwise is is just zeroed off.

Fixes: 132cd887b5c5 ("arm64: Modify stack trace and dump for use with irq_stack")
Acked-by: James Morse <james.morse@arm.com>
Tested-by: James Morse <james.morse@arm.com>
Signed-off-by: Yang Shi <yang.shi@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>

authored by

Yang Shi and committed by
Will Deacon
a80a0eb7 e04a28d4

+16 -8
+6 -7
arch/arm64/kernel/stacktrace.c
··· 44 44 unsigned long irq_stack_ptr; 45 45 46 46 /* 47 - * Use raw_smp_processor_id() to avoid false-positives from 48 - * CONFIG_DEBUG_PREEMPT. get_wchan() calls unwind_frame() on sleeping 49 - * task stacks, we can be pre-empted in this case, so 50 - * {raw_,}smp_processor_id() may give us the wrong value. Sleeping 51 - * tasks can't ever be on an interrupt stack, so regardless of cpu, 52 - * the checks will always fail. 47 + * Switching between stacks is valid when tracing current and in 48 + * non-preemptible context. 53 49 */ 54 - irq_stack_ptr = IRQ_STACK_PTR(raw_smp_processor_id()); 50 + if (tsk == current && !preemptible()) 51 + irq_stack_ptr = IRQ_STACK_PTR(smp_processor_id()); 52 + else 53 + irq_stack_ptr = 0; 55 54 56 55 low = frame->sp; 57 56 /* irq stacks are not THREAD_SIZE aligned */
+10 -1
arch/arm64/kernel/traps.c
··· 146 146 static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) 147 147 { 148 148 struct stackframe frame; 149 - unsigned long irq_stack_ptr = IRQ_STACK_PTR(smp_processor_id()); 149 + unsigned long irq_stack_ptr; 150 150 int skip; 151 + 152 + /* 153 + * Switching between stacks is valid when tracing current and in 154 + * non-preemptible context. 155 + */ 156 + if (tsk == current && !preemptible()) 157 + irq_stack_ptr = IRQ_STACK_PTR(smp_processor_id()); 158 + else 159 + irq_stack_ptr = 0; 151 160 152 161 pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); 153 162