sparc64: fatal trap should stop all cpus
authorDave Kleikamp <dave.kleikamp@oracle.com>
Wed, 7 Jan 2015 00:31:39 +0000 (18:31 -0600)
committerDavid S. Miller <davem@davemloft.net>
Mon, 2 Mar 2015 05:42:57 +0000 (21:42 -0800)
"echo c > /proc/sysrq-trigger" does not result in a system crash. There
are two problems. One is that the trap handler ignores the global
variable, panic_on_oops. The other is that smp_send_stop() is a no-op
which leaves the other cpus running normally when one cpu panics.

Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
arch/sparc/kernel/smp_64.c
arch/sparc/kernel/traps_64.c

index da6f1a7fc4db4713425d1927af185cb797b4c1fc..61139d9924cae4a8fdf5d4d5366a31052ea29616 100644 (file)
@@ -1406,11 +1406,32 @@ void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs)
        scheduler_ipi();
 }
 
-/* This is a nop because we capture all other cpus
- * anyways when making the PROM active.
- */
+static void stop_this_cpu(void *dummy)
+{
+       prom_stopself();
+}
+
 void smp_send_stop(void)
 {
+       int cpu;
+
+       if (tlb_type == hypervisor) {
+               for_each_online_cpu(cpu) {
+                       if (cpu == smp_processor_id())
+                               continue;
+#ifdef CONFIG_SUN_LDOMS
+                       if (ldom_domaining_enabled) {
+                               unsigned long hv_err;
+                               hv_err = sun4v_cpu_stop(cpu);
+                               if (hv_err)
+                                       printk(KERN_ERR "sun4v_cpu_stop() "
+                                              "failed err=%lu\n", hv_err);
+                       } else
+#endif
+                               prom_stopcpu_cpuid(cpu);
+               }
+       } else
+               smp_call_function(stop_this_cpu, NULL, 0);
 }
 
 /**
index 1ef1af4cf96b1dea3f01c1623f9b04421a8e2ede..0e699745d64311d44439327d3e971ce78114b7da 100644 (file)
@@ -2427,6 +2427,8 @@ void __noreturn die_if_kernel(char *str, struct pt_regs *regs)
                }
                user_instruction_dump ((unsigned int __user *) regs->tpc);
        }
+       if (panic_on_oops)
+               panic("Fatal exception");
        if (regs->tstate & TSTATE_PRIV)
                do_exit(SIGKILL);
        do_exit(SIGSEGV);