0001
0002 #include <linux/kernel.h>
0003 #include <linux/smp.h>
0004 #include <linux/reboot.h>
0005 #include <linux/kexec.h>
0006 #include <linux/memblock.h>
0007 #include <linux/crash_dump.h>
0008 #include <linux/delay.h>
0009 #include <linux/irq.h>
0010 #include <linux/types.h>
0011 #include <linux/sched.h>
0012 #include <linux/sched/task_stack.h>
0013
0014
0015 static int crashing_cpu = -1;
0016 static cpumask_t cpus_in_crash = CPU_MASK_NONE;
0017
0018 #ifdef CONFIG_SMP
0019 static void crash_shutdown_secondary(void *passed_regs)
0020 {
0021 struct pt_regs *regs = passed_regs;
0022 int cpu = smp_processor_id();
0023
0024
0025
0026
0027
0028
0029
0030
0031 if (!regs)
0032 regs = get_irq_regs();
0033 if (!regs)
0034 regs = task_pt_regs(current);
0035
0036 if (!cpu_online(cpu))
0037 return;
0038
0039
0040 set_cpu_online(cpu, false);
0041
0042 local_irq_disable();
0043 if (!cpumask_test_cpu(cpu, &cpus_in_crash))
0044 crash_save_cpu(regs, cpu);
0045 cpumask_set_cpu(cpu, &cpus_in_crash);
0046
0047 while (!atomic_read(&kexec_ready_to_reboot))
0048 cpu_relax();
0049
0050 kexec_reboot();
0051
0052
0053 }
0054
0055 static void crash_kexec_prepare_cpus(void)
0056 {
0057 static int cpus_stopped;
0058 unsigned int msecs;
0059 unsigned int ncpus;
0060
0061 if (cpus_stopped)
0062 return;
0063
0064 ncpus = num_online_cpus() - 1;
0065
0066 smp_call_function(crash_shutdown_secondary, NULL, 0);
0067 smp_wmb();
0068
0069
0070
0071
0072
0073 pr_emerg("Sending IPI to other cpus...\n");
0074 msecs = 10000;
0075 while ((cpumask_weight(&cpus_in_crash) < ncpus) && (--msecs > 0)) {
0076 cpu_relax();
0077 mdelay(1);
0078 }
0079
0080 cpus_stopped = 1;
0081 }
0082
0083
0084 void crash_smp_send_stop(void)
0085 {
0086 if (_crash_smp_send_stop)
0087 _crash_smp_send_stop();
0088
0089 crash_kexec_prepare_cpus();
0090 }
0091
0092 #else
0093 static void crash_kexec_prepare_cpus(void) {}
0094 #endif
0095
0096 void default_machine_crash_shutdown(struct pt_regs *regs)
0097 {
0098 local_irq_disable();
0099 crashing_cpu = smp_processor_id();
0100 crash_save_cpu(regs, crashing_cpu);
0101 crash_kexec_prepare_cpus();
0102 cpumask_set_cpu(crashing_cpu, &cpus_in_crash);
0103 }