Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e2ccba49 authored by Dave Martin's avatar Dave Martin Committed by Russell King
Browse files

ARM: 7897/1: kexec: Use the right ISA for relocate_new_kernel



Copying a function with memcpy() and then trying to execute the
result isn't trivially portable to Thumb.

This patch modifies the kexec soft restart code to copy its
assembler trampoline relocate_new_kernel() using fncpy() instead,
so that relocate_new_kernel can be in the same ISA as the rest of
the kernel without problems.

Signed-off-by: default avatarDave Martin <Dave.Martin@arm.com>
Acked-by: default avatarWill Deacon <will.deacon@arm.com>
Reported-by: default avatarTaras Kondratiuk <taras.kondratiuk@linaro.org>
Tested-by: default avatarTaras Kondratiuk <taras.kondratiuk@linaro.org>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 50913336
Loading
Loading
Loading
Loading
+10 −7
Original line number Diff line number Diff line
@@ -14,11 +14,12 @@
#include <asm/pgalloc.h>
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>
#include <asm/fncpy.h>
#include <asm/mach-types.h>
#include <asm/smp_plat.h>
#include <asm/system_misc.h>

extern const unsigned char relocate_new_kernel[];
extern void relocate_new_kernel(void);
extern const unsigned int relocate_new_kernel_size;

extern unsigned long kexec_start_address;
@@ -142,6 +143,8 @@ void machine_kexec(struct kimage *image)
{
	unsigned long page_list;
	unsigned long reboot_code_buffer_phys;
	unsigned long reboot_entry = (unsigned long)relocate_new_kernel;
	unsigned long reboot_entry_phys;
	void *reboot_code_buffer;

	/*
@@ -168,16 +171,16 @@ void machine_kexec(struct kimage *image)


	/* copy our kernel relocation code to the control code page */
	memcpy(reboot_code_buffer,
	       relocate_new_kernel, relocate_new_kernel_size);
	reboot_entry = fncpy(reboot_code_buffer,
			     reboot_entry,
			     relocate_new_kernel_size);
	reboot_entry_phys = (unsigned long)reboot_entry +
		(reboot_code_buffer_phys - (unsigned long)reboot_code_buffer);


	flush_icache_range((unsigned long) reboot_code_buffer,
			   (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
	printk(KERN_INFO "Bye!\n");

	if (kexec_reinit)
		kexec_reinit();

	soft_restart(reboot_code_buffer_phys);
	soft_restart(reboot_entry_phys);
}
+6 −2
Original line number Diff line number Diff line
@@ -2,10 +2,12 @@
 * relocate_kernel.S - put the kernel image in place to boot
 */

#include <linux/linkage.h>
#include <asm/kexec.h>

	.globl relocate_new_kernel
relocate_new_kernel:
	.align	3	/* not needed for this code, but keeps fncpy() happy */

ENTRY(relocate_new_kernel)

	ldr	r0,kexec_indirection_page
	ldr	r1,kexec_start_address
@@ -79,6 +81,8 @@ kexec_mach_type:
kexec_boot_atags:
	.long	0x0

ENDPROC(relocate_new_kernel)

relocate_new_kernel_end:

	.globl relocate_new_kernel_size