Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * PPC32 code to handle Linux booting another kernel.
0004  *
0005  * Copyright (C) 2002-2003 Eric Biederman  <ebiederm@xmission.com>
0006  * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
0007  * Copyright (C) 2005 IBM Corporation.
0008  */
0009 
0010 #include <linux/kexec.h>
0011 #include <linux/mm.h>
0012 #include <linux/string.h>
0013 #include <asm/cacheflush.h>
0014 #include <asm/hw_irq.h>
0015 #include <asm/io.h>
0016 
0017 typedef void (*relocate_new_kernel_t)(
0018                 unsigned long indirection_page,
0019                 unsigned long reboot_code_buffer,
0020                 unsigned long start_address) __noreturn;
0021 
0022 /*
0023  * This is a generic machine_kexec function suitable at least for
0024  * non-OpenFirmware embedded platforms.
0025  * It merely copies the image relocation code to the control page and
0026  * jumps to it.
0027  * A platform specific function may just call this one.
0028  */
0029 void default_machine_kexec(struct kimage *image)
0030 {
0031     extern const unsigned int relocate_new_kernel_size;
0032     unsigned long page_list;
0033     unsigned long reboot_code_buffer, reboot_code_buffer_phys;
0034     relocate_new_kernel_t rnk;
0035 
0036     /* Interrupts aren't acceptable while we reboot */
0037     local_irq_disable();
0038 
0039     /* mask each interrupt so we are in a more sane state for the
0040      * kexec kernel */
0041     machine_kexec_mask_interrupts();
0042 
0043     page_list = image->head;
0044 
0045     /* we need both effective and real address here */
0046     reboot_code_buffer =
0047             (unsigned long)page_address(image->control_code_page);
0048     reboot_code_buffer_phys = virt_to_phys((void *)reboot_code_buffer);
0049 
0050     /* copy our kernel relocation code to the control code page */
0051     memcpy((void *)reboot_code_buffer, relocate_new_kernel,
0052                         relocate_new_kernel_size);
0053 
0054     flush_icache_range(reboot_code_buffer,
0055                 reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
0056     printk(KERN_INFO "Bye!\n");
0057 
0058     if (!IS_ENABLED(CONFIG_FSL_BOOKE) && !IS_ENABLED(CONFIG_44x))
0059         relocate_new_kernel(page_list, reboot_code_buffer_phys, image->start);
0060 
0061     /* now call it */
0062     rnk = (relocate_new_kernel_t) reboot_code_buffer;
0063     (*rnk)(page_list, reboot_code_buffer_phys, image->start);
0064 }
0065 
0066 int machine_kexec_prepare(struct kimage *image)
0067 {
0068     return 0;
0069 }