forked from Minki/linux
ff2d8b19a3
Use the more commonly used __noreturn instead of ATTRIB_NORETURN. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Joe Perches <joe@perches.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Haavard Skinnemoen <hskinnemoen@gmail.com> Cc: Hans-Christian Egtvedt <egtvedt@samfundet.no> Cc: Tony Luck <tony.luck@intel.com> Cc: Fenghua Yu <fenghua.yu@intel.com> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Ralf Baechle <ralf@linux-mips.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Chris Metcalf <cmetcalf@tilera.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
70 lines
2.0 KiB
C
70 lines
2.0 KiB
C
/*
|
|
* PPC32 code to handle Linux booting another kernel.
|
|
*
|
|
* Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
|
|
* GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
|
|
* Copyright (C) 2005 IBM Corporation.
|
|
*
|
|
* This source code is licensed under the GNU General Public License,
|
|
* Version 2. See the file COPYING for more details.
|
|
*/
|
|
|
|
#include <linux/kexec.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/string.h>
|
|
#include <asm/cacheflush.h>
|
|
#include <asm/hw_irq.h>
|
|
#include <asm/io.h>
|
|
|
|
typedef void (*relocate_new_kernel_t)(
|
|
unsigned long indirection_page,
|
|
unsigned long reboot_code_buffer,
|
|
unsigned long start_address) __noreturn;
|
|
|
|
/*
|
|
* This is a generic machine_kexec function suitable at least for
|
|
* non-OpenFirmware embedded platforms.
|
|
* It merely copies the image relocation code to the control page and
|
|
* jumps to it.
|
|
* A platform specific function may just call this one.
|
|
*/
|
|
void default_machine_kexec(struct kimage *image)
|
|
{
|
|
extern const unsigned char relocate_new_kernel[];
|
|
extern const unsigned int relocate_new_kernel_size;
|
|
unsigned long page_list;
|
|
unsigned long reboot_code_buffer, reboot_code_buffer_phys;
|
|
relocate_new_kernel_t rnk;
|
|
|
|
/* Interrupts aren't acceptable while we reboot */
|
|
local_irq_disable();
|
|
|
|
/* mask each interrupt so we are in a more sane state for the
|
|
* kexec kernel */
|
|
machine_kexec_mask_interrupts();
|
|
|
|
page_list = image->head;
|
|
|
|
/* we need both effective and real address here */
|
|
reboot_code_buffer =
|
|
(unsigned long)page_address(image->control_code_page);
|
|
reboot_code_buffer_phys = virt_to_phys((void *)reboot_code_buffer);
|
|
|
|
/* copy our kernel relocation code to the control code page */
|
|
memcpy((void *)reboot_code_buffer, relocate_new_kernel,
|
|
relocate_new_kernel_size);
|
|
|
|
flush_icache_range(reboot_code_buffer,
|
|
reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
|
|
printk(KERN_INFO "Bye!\n");
|
|
|
|
/* now call it */
|
|
rnk = (relocate_new_kernel_t) reboot_code_buffer;
|
|
(*rnk)(page_list, reboot_code_buffer_phys, image->start);
|
|
}
|
|
|
|
int default_machine_kexec_prepare(struct kimage *image)
|
|
{
|
|
return 0;
|
|
}
|