xref: /openbmc/linux/arch/powerpc/kexec/core_32.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1793b08e2SChristophe Leroy // SPDX-License-Identifier: GPL-2.0-only
2793b08e2SChristophe Leroy /*
3793b08e2SChristophe Leroy  * PPC32 code to handle Linux booting another kernel.
4793b08e2SChristophe Leroy  *
5793b08e2SChristophe Leroy  * Copyright (C) 2002-2003 Eric Biederman  <ebiederm@xmission.com>
6793b08e2SChristophe Leroy  * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
7793b08e2SChristophe Leroy  * Copyright (C) 2005 IBM Corporation.
8793b08e2SChristophe Leroy  */
9793b08e2SChristophe Leroy 
10793b08e2SChristophe Leroy #include <linux/kexec.h>
11793b08e2SChristophe Leroy #include <linux/mm.h>
12793b08e2SChristophe Leroy #include <linux/string.h>
13793b08e2SChristophe Leroy #include <asm/cacheflush.h>
14793b08e2SChristophe Leroy #include <asm/hw_irq.h>
15793b08e2SChristophe Leroy #include <asm/io.h>
16793b08e2SChristophe Leroy 
17793b08e2SChristophe Leroy typedef void (*relocate_new_kernel_t)(
18793b08e2SChristophe Leroy 				unsigned long indirection_page,
19793b08e2SChristophe Leroy 				unsigned long reboot_code_buffer,
20793b08e2SChristophe Leroy 				unsigned long start_address) __noreturn;
21793b08e2SChristophe Leroy 
22793b08e2SChristophe Leroy /*
23793b08e2SChristophe Leroy  * This is a generic machine_kexec function suitable at least for
24793b08e2SChristophe Leroy  * non-OpenFirmware embedded platforms.
25793b08e2SChristophe Leroy  * It merely copies the image relocation code to the control page and
26793b08e2SChristophe Leroy  * jumps to it.
27793b08e2SChristophe Leroy  * A platform specific function may just call this one.
28793b08e2SChristophe Leroy  */
default_machine_kexec(struct kimage * image)29793b08e2SChristophe Leroy void default_machine_kexec(struct kimage *image)
30793b08e2SChristophe Leroy {
31793b08e2SChristophe Leroy 	extern const unsigned int relocate_new_kernel_size;
32793b08e2SChristophe Leroy 	unsigned long page_list;
33793b08e2SChristophe Leroy 	unsigned long reboot_code_buffer, reboot_code_buffer_phys;
34793b08e2SChristophe Leroy 	relocate_new_kernel_t rnk;
35793b08e2SChristophe Leroy 
36793b08e2SChristophe Leroy 	/* Interrupts aren't acceptable while we reboot */
37793b08e2SChristophe Leroy 	local_irq_disable();
38793b08e2SChristophe Leroy 
39793b08e2SChristophe Leroy 	/* mask each interrupt so we are in a more sane state for the
40793b08e2SChristophe Leroy 	 * kexec kernel */
41793b08e2SChristophe Leroy 	machine_kexec_mask_interrupts();
42793b08e2SChristophe Leroy 
43793b08e2SChristophe Leroy 	page_list = image->head;
44793b08e2SChristophe Leroy 
45793b08e2SChristophe Leroy 	/* we need both effective and real address here */
46793b08e2SChristophe Leroy 	reboot_code_buffer =
47793b08e2SChristophe Leroy 			(unsigned long)page_address(image->control_code_page);
48793b08e2SChristophe Leroy 	reboot_code_buffer_phys = virt_to_phys((void *)reboot_code_buffer);
49793b08e2SChristophe Leroy 
50793b08e2SChristophe Leroy 	/* copy our kernel relocation code to the control code page */
51793b08e2SChristophe Leroy 	memcpy((void *)reboot_code_buffer, relocate_new_kernel,
52793b08e2SChristophe Leroy 						relocate_new_kernel_size);
53793b08e2SChristophe Leroy 
54793b08e2SChristophe Leroy 	flush_icache_range(reboot_code_buffer,
55793b08e2SChristophe Leroy 				reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
56793b08e2SChristophe Leroy 	printk(KERN_INFO "Bye!\n");
57793b08e2SChristophe Leroy 
58*dfc3095cSChristophe Leroy 	if (!IS_ENABLED(CONFIG_PPC_85xx) && !IS_ENABLED(CONFIG_44x))
59793b08e2SChristophe Leroy 		relocate_new_kernel(page_list, reboot_code_buffer_phys, image->start);
60793b08e2SChristophe Leroy 
61793b08e2SChristophe Leroy 	/* now call it */
62793b08e2SChristophe Leroy 	rnk = (relocate_new_kernel_t) reboot_code_buffer;
63793b08e2SChristophe Leroy 	(*rnk)(page_list, reboot_code_buffer_phys, image->start);
64793b08e2SChristophe Leroy }
65793b08e2SChristophe Leroy 
machine_kexec_prepare(struct kimage * image)668f7fadb4SChristophe Leroy int machine_kexec_prepare(struct kimage *image)
67793b08e2SChristophe Leroy {
68793b08e2SChristophe Leroy 	return 0;
69793b08e2SChristophe Leroy }
70