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