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

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
...@@ -14,11 +14,12 @@ ...@@ -14,11 +14,12 @@
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/fncpy.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/smp_plat.h> #include <asm/smp_plat.h>
#include <asm/system_misc.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 const unsigned int relocate_new_kernel_size;
extern unsigned long kexec_start_address; extern unsigned long kexec_start_address;
...@@ -142,6 +143,8 @@ void machine_kexec(struct kimage *image) ...@@ -142,6 +143,8 @@ void machine_kexec(struct kimage *image)
{ {
unsigned long page_list; unsigned long page_list;
unsigned long reboot_code_buffer_phys; unsigned long reboot_code_buffer_phys;
unsigned long reboot_entry = (unsigned long)relocate_new_kernel;
unsigned long reboot_entry_phys;
void *reboot_code_buffer; void *reboot_code_buffer;
/* /*
...@@ -168,16 +171,16 @@ void machine_kexec(struct kimage *image) ...@@ -168,16 +171,16 @@ void machine_kexec(struct kimage *image)
/* copy our kernel relocation code to the control code page */ /* copy our kernel relocation code to the control code page */
memcpy(reboot_code_buffer, reboot_entry = fncpy(reboot_code_buffer,
relocate_new_kernel, relocate_new_kernel_size); 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"); printk(KERN_INFO "Bye!\n");
if (kexec_reinit) if (kexec_reinit)
kexec_reinit(); kexec_reinit();
soft_restart(reboot_code_buffer_phys); soft_restart(reboot_entry_phys);
} }
...@@ -2,10 +2,12 @@ ...@@ -2,10 +2,12 @@
* relocate_kernel.S - put the kernel image in place to boot * relocate_kernel.S - put the kernel image in place to boot
*/ */
#include <linux/linkage.h>
#include <asm/kexec.h> #include <asm/kexec.h>
.globl relocate_new_kernel .align 3 /* not needed for this code, but keeps fncpy() happy */
relocate_new_kernel:
ENTRY(relocate_new_kernel)
ldr r0,kexec_indirection_page ldr r0,kexec_indirection_page
ldr r1,kexec_start_address ldr r1,kexec_start_address
...@@ -79,6 +81,8 @@ kexec_mach_type: ...@@ -79,6 +81,8 @@ kexec_mach_type:
kexec_boot_atags: kexec_boot_atags:
.long 0x0 .long 0x0
ENDPROC(relocate_new_kernel)
relocate_new_kernel_end: relocate_new_kernel_end:
.globl relocate_new_kernel_size .globl relocate_new_kernel_size
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment