|
13 | 13 | #include <linux/export.h>
|
14 | 14 | #include <linux/kallsyms.h>
|
15 | 15 | #include <linux/module.h>
|
| 16 | +#include <linux/nmi.h> |
16 | 17 | #include <linux/sched.h>
|
17 | 18 | #include <linux/sched/debug.h>
|
18 | 19 | #include <linux/sched/task_stack.h>
|
|
22 | 23 | #include <linux/ftrace.h>
|
23 | 24 | #include <asm/kprobes.h>
|
24 | 25 |
|
| 26 | +#include <asm/paca.h> |
| 27 | + |
25 | 28 | /*
|
26 | 29 | * Save stack-backtrace addresses into a stack_trace buffer.
|
27 | 30 | */
|
@@ -194,3 +197,51 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,
|
194 | 197 | }
|
195 | 198 | EXPORT_SYMBOL_GPL(save_stack_trace_tsk_reliable);
|
196 | 199 | #endif /* CONFIG_HAVE_RELIABLE_STACKTRACE */
|
| 200 | + |
| 201 | +#ifdef CONFIG_PPC_BOOK3S_64 |
| 202 | +static void handle_backtrace_ipi(struct pt_regs *regs) |
| 203 | +{ |
| 204 | + nmi_cpu_backtrace(regs); |
| 205 | +} |
| 206 | + |
| 207 | +static void raise_backtrace_ipi(cpumask_t *mask) |
| 208 | +{ |
| 209 | + unsigned int cpu; |
| 210 | + |
| 211 | + for_each_cpu(cpu, mask) { |
| 212 | + if (cpu == smp_processor_id()) |
| 213 | + handle_backtrace_ipi(NULL); |
| 214 | + else |
| 215 | + smp_send_safe_nmi_ipi(cpu, handle_backtrace_ipi, 5 * USEC_PER_SEC); |
| 216 | + } |
| 217 | + |
| 218 | + for_each_cpu(cpu, mask) { |
| 219 | + struct paca_struct *p = paca_ptrs[cpu]; |
| 220 | + |
| 221 | + cpumask_clear_cpu(cpu, mask); |
| 222 | + |
| 223 | + pr_warn("CPU %d didn't respond to backtrace IPI, inspecting paca.\n", cpu); |
| 224 | + if (!virt_addr_valid(p)) { |
| 225 | + pr_warn("paca pointer appears corrupt? (%px)\n", p); |
| 226 | + continue; |
| 227 | + } |
| 228 | + |
| 229 | + pr_warn("irq_soft_mask: 0x%02x in_mce: %d in_nmi: %d", |
| 230 | + p->irq_soft_mask, p->in_mce, p->in_nmi); |
| 231 | + |
| 232 | + if (virt_addr_valid(p->__current)) |
| 233 | + pr_cont(" current: %d (%s)\n", p->__current->pid, |
| 234 | + p->__current->comm); |
| 235 | + else |
| 236 | + pr_cont(" current pointer corrupt? (%px)\n", p->__current); |
| 237 | + |
| 238 | + pr_warn("Back trace of paca->saved_r1 (0x%016llx) (possibly stale):\n", p->saved_r1); |
| 239 | + show_stack(p->__current, (unsigned long *)p->saved_r1); |
| 240 | + } |
| 241 | +} |
| 242 | + |
| 243 | +void arch_trigger_cpumask_backtrace(const cpumask_t *mask, bool exclude_self) |
| 244 | +{ |
| 245 | + nmi_trigger_cpumask_backtrace(mask, exclude_self, raise_backtrace_ipi); |
| 246 | +} |
| 247 | +#endif /* CONFIG_PPC64 */ |
0 commit comments