diff options
Diffstat (limited to 'target/linux/realtek/files/arch/rlx/kernel/machine_kexec.c')
| -rw-r--r-- | target/linux/realtek/files/arch/rlx/kernel/machine_kexec.c | 85 | 
1 files changed, 85 insertions, 0 deletions
diff --git a/target/linux/realtek/files/arch/rlx/kernel/machine_kexec.c b/target/linux/realtek/files/arch/rlx/kernel/machine_kexec.c new file mode 100644 index 000000000..85beb9b0b --- /dev/null +++ b/target/linux/realtek/files/arch/rlx/kernel/machine_kexec.c @@ -0,0 +1,85 @@ +/* + * machine_kexec.c for kexec + * Created by <nschichan@corp.free.fr> on Thu Oct 12 15:15:06 2006 + * + * 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/delay.h> + +#include <asm/cacheflush.h> +#include <asm/page.h> + +extern const unsigned char relocate_new_kernel[]; +extern const size_t relocate_new_kernel_size; + +extern unsigned long kexec_start_address; +extern unsigned long kexec_indirection_page; + +int +machine_kexec_prepare(struct kimage *kimage) +{ +	return 0; +} + +void +machine_kexec_cleanup(struct kimage *kimage) +{ +} + +void +machine_shutdown(void) +{ +} + +void +machine_crash_shutdown(struct pt_regs *regs) +{ +} + +typedef void (*noretfun_t)(void) __attribute__((noreturn)); + +void +machine_kexec(struct kimage *image) +{ +	unsigned long reboot_code_buffer; +	unsigned long entry; +	unsigned long *ptr; + +	reboot_code_buffer = +	  (unsigned long)page_address(image->control_code_page); + +	kexec_start_address = image->start; +	kexec_indirection_page = +		(unsigned long) phys_to_virt(image->head & PAGE_MASK); + +	memcpy((void*)reboot_code_buffer, relocate_new_kernel, +	       relocate_new_kernel_size); + +	/* +	 * The generic kexec code builds a page list with physical +	 * addresses. they are directly accessible through KSEG0 (or +	 * CKSEG0 or XPHYS if on 64bit system), hence the +	 * pys_to_virt() call. +	 */ +	for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE); +	     ptr = (entry & IND_INDIRECTION) ? +	       phys_to_virt(entry & PAGE_MASK) : ptr + 1) { +		if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION || +		    *ptr & IND_DESTINATION) +			*ptr = (unsigned long) phys_to_virt(*ptr); +	} + +	/* +	 * we do not want to be bothered. +	 */ +	local_irq_disable(); + +	printk("Will call new kernel at %08lx\n", image->start); +	printk("Bye ...\n"); +	__flush_cache_all(); +	((noretfun_t) reboot_code_buffer)(); +}  | 
