1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * machine_kexec.c for kexec
4 * Created by <nschichan@corp.free.fr> on Thu Oct 12 15:15:06 2006
5 */
6#include <linux/compiler.h>
7#include <linux/kexec.h>
8#include <linux/mm.h>
9#include <linux/delay.h>
10#include <linux/libfdt.h>
11#include <linux/reboot.h>
12
13#include <asm/cacheflush.h>
14#include <asm/page.h>
15
16extern const unsigned char relocate_new_kernel[];
17extern const size_t relocate_new_kernel_size;
18
19extern unsigned long kexec_start_address;
20extern unsigned long kexec_indirection_page;
21
22static unsigned long reboot_code_buffer;
23
24#ifdef CONFIG_SMP
25static void (*relocated_kexec_smp_wait)(void *);
26
27atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
28void (*_crash_smp_send_stop)(void) = NULL;
29#endif
30
31void (*_machine_kexec_shutdown)(void) = NULL;
32void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;
33
34static void kexec_image_info(const struct kimage *kimage)
35{
36	unsigned long i;
37
38	pr_debug("kexec kimage info:\n");
39	pr_debug("  type:        %d\n", kimage->type);
40	pr_debug("  start:       %lx\n", kimage->start);
41	pr_debug("  head:        %lx\n", kimage->head);
42	pr_debug("  nr_segments: %lu\n", kimage->nr_segments);
43
44	for (i = 0; i < kimage->nr_segments; i++) {
45		pr_debug("    segment[%lu]: %016lx - %016lx, 0x%lx bytes, %lu pages\n",
46			i,
47			kimage->segment[i].mem,
48			kimage->segment[i].mem + kimage->segment[i].memsz,
49			(unsigned long)kimage->segment[i].memsz,
50			(unsigned long)kimage->segment[i].memsz /  PAGE_SIZE);
51	}
52}
53
54#ifdef CONFIG_UHI_BOOT
55
56static int uhi_machine_kexec_prepare(struct kimage *kimage)
57{
58	int i;
59
60	/*
61	 * In case DTB file is not passed to the new kernel, a flat device
62	 * tree will be created by kexec tool. It holds modified command
63	 * line for the new kernel.
64	 */
65	for (i = 0; i < kimage->nr_segments; i++) {
66		struct fdt_header fdt;
67
68		if (kimage->segment[i].memsz <= sizeof(fdt))
69			continue;
70
71		if (copy_from_user(&fdt, kimage->segment[i].buf, sizeof(fdt)))
72			continue;
73
74		if (fdt_check_header(&fdt))
75			continue;
76
77		kexec_args[0] = -2;
78		kexec_args[1] = (unsigned long)
79			phys_to_virt((unsigned long)kimage->segment[i].mem);
80		break;
81	}
82
83	return 0;
84}
85
86int (*_machine_kexec_prepare)(struct kimage *) = uhi_machine_kexec_prepare;
87
88#else
89
90int (*_machine_kexec_prepare)(struct kimage *) = NULL;
91
92#endif /* CONFIG_UHI_BOOT */
93
94int
95machine_kexec_prepare(struct kimage *kimage)
96{
97#ifdef CONFIG_SMP
98	if (!kexec_nonboot_cpu_func())
99		return -EINVAL;
100#endif
101
102	kexec_image_info(kimage);
103
104	if (_machine_kexec_prepare)
105		return _machine_kexec_prepare(kimage);
106
107	return 0;
108}
109
110void
111machine_kexec_cleanup(struct kimage *kimage)
112{
113}
114
115#ifdef CONFIG_SMP
116static void kexec_shutdown_secondary(void *param)
117{
118	int cpu = smp_processor_id();
119
120	if (!cpu_online(cpu))
121		return;
122
123	/* We won't be sent IPIs any more. */
124	set_cpu_online(cpu, false);
125
126	local_irq_disable();
127	while (!atomic_read(&kexec_ready_to_reboot))
128		cpu_relax();
129
130	kexec_reboot();
131
132	/* NOTREACHED */
133}
134#endif
135
136void
137machine_shutdown(void)
138{
139	if (_machine_kexec_shutdown)
140		_machine_kexec_shutdown();
141
142#ifdef CONFIG_SMP
143	smp_call_function(kexec_shutdown_secondary, NULL, 0);
144
145	while (num_online_cpus() > 1) {
146		cpu_relax();
147		mdelay(1);
148	}
149#endif
150}
151
152void
153machine_crash_shutdown(struct pt_regs *regs)
154{
155	if (_machine_crash_shutdown)
156		_machine_crash_shutdown(regs);
157	else
158		default_machine_crash_shutdown(regs);
159}
160
161#ifdef CONFIG_SMP
162void kexec_nonboot_cpu_jump(void)
163{
164	local_flush_icache_range((unsigned long)relocated_kexec_smp_wait,
165				 reboot_code_buffer + relocate_new_kernel_size);
166
167	relocated_kexec_smp_wait(NULL);
168}
169#endif
170
171void kexec_reboot(void)
172{
173	void (*do_kexec)(void) __noreturn;
174
175	/*
176	 * We know we were online, and there will be no incoming IPIs at
177	 * this point. Mark online again before rebooting so that the crash
178	 * analysis tool will see us correctly.
179	 */
180	set_cpu_online(smp_processor_id(), true);
181
182	/* Ensure remote CPUs observe that we're online before rebooting. */
183	smp_mb__after_atomic();
184
185#ifdef CONFIG_SMP
186	if (smp_processor_id() > 0) {
187		/*
188		 * Instead of cpu_relax() or wait, this is needed for kexec
189		 * smp reboot. Kdump usually doesn't require an smp new
190		 * kernel, but kexec may do.
191		 */
192		kexec_nonboot_cpu();
193
194		/* NOTREACHED */
195	}
196#endif
197
198	/*
199	 * Make sure we get correct instructions written by the
200	 * machine_kexec() CPU.
201	 */
202	local_flush_icache_range(reboot_code_buffer,
203				 reboot_code_buffer + relocate_new_kernel_size);
204
205	do_kexec = (void *)reboot_code_buffer;
206	do_kexec();
207}
208
209void
210machine_kexec(struct kimage *image)
211{
212	unsigned long entry;
213	unsigned long *ptr;
214
215	reboot_code_buffer =
216	  (unsigned long)page_address(image->control_code_page);
217
218	kexec_start_address =
219		(unsigned long) phys_to_virt(image->start);
220
221	if (image->type == KEXEC_TYPE_DEFAULT) {
222		kexec_indirection_page =
223			(unsigned long) phys_to_virt(image->head & PAGE_MASK);
224	} else {
225		kexec_indirection_page = (unsigned long)&image->head;
226	}
227
228	memcpy((void*)reboot_code_buffer, relocate_new_kernel,
229	       relocate_new_kernel_size);
230
231	/*
232	 * The generic kexec code builds a page list with physical
233	 * addresses. they are directly accessible through KSEG0 (or
234	 * CKSEG0 or XPHYS if on 64bit system), hence the
235	 * phys_to_virt() call.
236	 */
237	for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE);
238	     ptr = (entry & IND_INDIRECTION) ?
239	       phys_to_virt(entry & PAGE_MASK) : ptr + 1) {
240		if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION ||
241		    *ptr & IND_DESTINATION)
242			*ptr = (unsigned long) phys_to_virt(*ptr);
243	}
244
245	/* Mark offline BEFORE disabling local irq. */
246	set_cpu_online(smp_processor_id(), false);
247
248	/*
249	 * we do not want to be bothered.
250	 */
251	local_irq_disable();
252
253	printk("Will call new kernel at %08lx\n", image->start);
254	printk("Bye ...\n");
255	/* Make reboot code buffer available to the boot CPU. */
256	__flush_cache_all();
257#ifdef CONFIG_SMP
258	/* All secondary cpus now may jump to kexec_wait cycle */
259	relocated_kexec_smp_wait = reboot_code_buffer +
260		(void *)(kexec_smp_wait - relocate_new_kernel);
261	smp_wmb();
262	atomic_set(&kexec_ready_to_reboot, 1);
263#endif
264	kexec_reboot();
265}
266