Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/kernel/crash.c
26439 views
1
// SPDX-License-Identifier: GPL-2.0
2
#include <linux/kernel.h>
3
#include <linux/smp.h>
4
#include <linux/reboot.h>
5
#include <linux/kexec.h>
6
#include <linux/memblock.h>
7
#include <linux/crash_dump.h>
8
#include <linux/delay.h>
9
#include <linux/irq.h>
10
#include <linux/types.h>
11
#include <linux/sched.h>
12
#include <linux/sched/task_stack.h>
13
14
/* This keeps a track of which one is crashing cpu. */
15
static int crashing_cpu = -1;
16
static cpumask_t cpus_in_crash = CPU_MASK_NONE;
17
18
#ifdef CONFIG_SMP
19
static void crash_shutdown_secondary(void *passed_regs)
20
{
21
struct pt_regs *regs = passed_regs;
22
int cpu = smp_processor_id();
23
24
/*
25
* If we are passed registers, use those. Otherwise get the
26
* regs from the last interrupt, which should be correct, as
27
* we are in an interrupt. But if the regs are not there,
28
* pull them from the top of the stack. They are probably
29
* wrong, but we need something to keep from crashing again.
30
*/
31
if (!regs)
32
regs = get_irq_regs();
33
if (!regs)
34
regs = task_pt_regs(current);
35
36
if (!cpu_online(cpu))
37
return;
38
39
/* We won't be sent IPIs any more. */
40
set_cpu_online(cpu, false);
41
42
local_irq_disable();
43
if (!cpumask_test_cpu(cpu, &cpus_in_crash))
44
crash_save_cpu(regs, cpu);
45
cpumask_set_cpu(cpu, &cpus_in_crash);
46
47
while (!atomic_read(&kexec_ready_to_reboot))
48
cpu_relax();
49
50
kexec_reboot();
51
52
/* NOTREACHED */
53
}
54
55
static void crash_kexec_prepare_cpus(void)
56
{
57
static int cpus_stopped;
58
unsigned int msecs;
59
unsigned int ncpus;
60
61
if (cpus_stopped)
62
return;
63
64
ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
65
66
smp_call_function(crash_shutdown_secondary, NULL, 0);
67
smp_wmb();
68
69
/*
70
* The crash CPU sends an IPI and wait for other CPUs to
71
* respond. Delay of at least 10 seconds.
72
*/
73
pr_emerg("Sending IPI to other cpus...\n");
74
msecs = 10000;
75
while ((cpumask_weight(&cpus_in_crash) < ncpus) && (--msecs > 0)) {
76
cpu_relax();
77
mdelay(1);
78
}
79
80
cpus_stopped = 1;
81
}
82
83
/* Override the weak function in kernel/panic.c */
84
void crash_smp_send_stop(void)
85
{
86
if (_crash_smp_send_stop)
87
_crash_smp_send_stop();
88
89
crash_kexec_prepare_cpus();
90
}
91
92
#else /* !defined(CONFIG_SMP) */
93
static void crash_kexec_prepare_cpus(void) {}
94
#endif /* !defined(CONFIG_SMP) */
95
96
void default_machine_crash_shutdown(struct pt_regs *regs)
97
{
98
local_irq_disable();
99
crashing_cpu = smp_processor_id();
100
crash_save_cpu(regs, crashing_cpu);
101
crash_kexec_prepare_cpus();
102
cpumask_set_cpu(crashing_cpu, &cpus_in_crash);
103
}
104
105