hc
2024-05-11 04dd17822334871b23ea2862f7798fb0e0007777
kernel/arch/mips/kernel/machine_kexec.c
....@@ -1,14 +1,13 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * machine_kexec.c for kexec
34 * Created by <nschichan@corp.free.fr> on Thu Oct 12 15:15:06 2006
4
- *
5
- * This source code is licensed under the GNU General Public License,
6
- * Version 2. See the file COPYING for more details.
75 */
86 #include <linux/compiler.h>
97 #include <linux/kexec.h>
108 #include <linux/mm.h>
119 #include <linux/delay.h>
10
+#include <linux/libfdt.h>
1211
1312 #include <asm/cacheflush.h>
1413 #include <asm/page.h>
....@@ -19,14 +18,17 @@
1918 extern unsigned long kexec_start_address;
2019 extern unsigned long kexec_indirection_page;
2120
22
-int (*_machine_kexec_prepare)(struct kimage *) = NULL;
23
-void (*_machine_kexec_shutdown)(void) = NULL;
24
-void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;
21
+static unsigned long reboot_code_buffer;
22
+
2523 #ifdef CONFIG_SMP
26
-void (*relocated_kexec_smp_wait) (void *);
24
+static void (*relocated_kexec_smp_wait)(void *);
25
+
2726 atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
2827 void (*_crash_smp_send_stop)(void) = NULL;
2928 #endif
29
+
30
+void (*_machine_kexec_shutdown)(void) = NULL;
31
+void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;
3032
3133 static void kexec_image_info(const struct kimage *kimage)
3234 {
....@@ -48,13 +50,59 @@
4850 }
4951 }
5052
53
+#ifdef CONFIG_UHI_BOOT
54
+
55
+static int uhi_machine_kexec_prepare(struct kimage *kimage)
56
+{
57
+ int i;
58
+
59
+ /*
60
+ * In case DTB file is not passed to the new kernel, a flat device
61
+ * tree will be created by kexec tool. It holds modified command
62
+ * line for the new kernel.
63
+ */
64
+ for (i = 0; i < kimage->nr_segments; i++) {
65
+ struct fdt_header fdt;
66
+
67
+ if (kimage->segment[i].memsz <= sizeof(fdt))
68
+ continue;
69
+
70
+ if (copy_from_user(&fdt, kimage->segment[i].buf, sizeof(fdt)))
71
+ continue;
72
+
73
+ if (fdt_check_header(&fdt))
74
+ continue;
75
+
76
+ kexec_args[0] = -2;
77
+ kexec_args[1] = (unsigned long)
78
+ phys_to_virt((unsigned long)kimage->segment[i].mem);
79
+ break;
80
+ }
81
+
82
+ return 0;
83
+}
84
+
85
+int (*_machine_kexec_prepare)(struct kimage *) = uhi_machine_kexec_prepare;
86
+
87
+#else
88
+
89
+int (*_machine_kexec_prepare)(struct kimage *) = NULL;
90
+
91
+#endif /* CONFIG_UHI_BOOT */
92
+
5193 int
5294 machine_kexec_prepare(struct kimage *kimage)
5395 {
96
+#ifdef CONFIG_SMP
97
+ if (!kexec_nonboot_cpu_func())
98
+ return -EINVAL;
99
+#endif
100
+
54101 kexec_image_info(kimage);
55102
56103 if (_machine_kexec_prepare)
57104 return _machine_kexec_prepare(kimage);
105
+
58106 return 0;
59107 }
60108
....@@ -63,11 +111,41 @@
63111 {
64112 }
65113
114
+#ifdef CONFIG_SMP
115
+static void kexec_shutdown_secondary(void *param)
116
+{
117
+ int cpu = smp_processor_id();
118
+
119
+ if (!cpu_online(cpu))
120
+ return;
121
+
122
+ /* We won't be sent IPIs any more. */
123
+ set_cpu_online(cpu, false);
124
+
125
+ local_irq_disable();
126
+ while (!atomic_read(&kexec_ready_to_reboot))
127
+ cpu_relax();
128
+
129
+ kexec_reboot();
130
+
131
+ /* NOTREACHED */
132
+}
133
+#endif
134
+
66135 void
67136 machine_shutdown(void)
68137 {
69138 if (_machine_kexec_shutdown)
70139 _machine_kexec_shutdown();
140
+
141
+#ifdef CONFIG_SMP
142
+ smp_call_function(kexec_shutdown_secondary, NULL, 0);
143
+
144
+ while (num_online_cpus() > 1) {
145
+ cpu_relax();
146
+ mdelay(1);
147
+ }
148
+#endif
71149 }
72150
73151 void
....@@ -79,12 +157,57 @@
79157 default_machine_crash_shutdown(regs);
80158 }
81159
82
-typedef void (*noretfun_t)(void) __noreturn;
160
+#ifdef CONFIG_SMP
161
+void kexec_nonboot_cpu_jump(void)
162
+{
163
+ local_flush_icache_range((unsigned long)relocated_kexec_smp_wait,
164
+ reboot_code_buffer + relocate_new_kernel_size);
165
+
166
+ relocated_kexec_smp_wait(NULL);
167
+}
168
+#endif
169
+
170
+void kexec_reboot(void)
171
+{
172
+ void (*do_kexec)(void) __noreturn;
173
+
174
+ /*
175
+ * We know we were online, and there will be no incoming IPIs at
176
+ * this point. Mark online again before rebooting so that the crash
177
+ * analysis tool will see us correctly.
178
+ */
179
+ set_cpu_online(smp_processor_id(), true);
180
+
181
+ /* Ensure remote CPUs observe that we're online before rebooting. */
182
+ smp_mb__after_atomic();
183
+
184
+#ifdef CONFIG_SMP
185
+ if (smp_processor_id() > 0) {
186
+ /*
187
+ * Instead of cpu_relax() or wait, this is needed for kexec
188
+ * smp reboot. Kdump usually doesn't require an smp new
189
+ * kernel, but kexec may do.
190
+ */
191
+ kexec_nonboot_cpu();
192
+
193
+ /* NOTREACHED */
194
+ }
195
+#endif
196
+
197
+ /*
198
+ * Make sure we get correct instructions written by the
199
+ * machine_kexec() CPU.
200
+ */
201
+ local_flush_icache_range(reboot_code_buffer,
202
+ reboot_code_buffer + relocate_new_kernel_size);
203
+
204
+ do_kexec = (void *)reboot_code_buffer;
205
+ do_kexec();
206
+}
83207
84208 void
85209 machine_kexec(struct kimage *image)
86210 {
87
- unsigned long reboot_code_buffer;
88211 unsigned long entry;
89212 unsigned long *ptr;
90213
....@@ -128,6 +251,7 @@
128251
129252 printk("Will call new kernel at %08lx\n", image->start);
130253 printk("Bye ...\n");
254
+ /* Make reboot code buffer available to the boot CPU. */
131255 __flush_cache_all();
132256 #ifdef CONFIG_SMP
133257 /* All secondary cpus now may jump to kexec_wait cycle */
....@@ -136,5 +260,5 @@
136260 smp_wmb();
137261 atomic_set(&kexec_ready_to_reboot, 1);
138262 #endif
139
- ((noretfun_t) reboot_code_buffer)();
263
+ kexec_reboot();
140264 }