Skip to content

Commit

Permalink
ARM: 7897/1: kexec: Use the right ISA for relocate_new_kernel
Browse files Browse the repository at this point in the history
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: Dave Martin <[email protected]>
Acked-by: Will Deacon <[email protected]>
Reported-by: Taras Kondratiuk <[email protected]>
Tested-by: Taras Kondratiuk <[email protected]>
Signed-off-by: Russell King <[email protected]>
  • Loading branch information
Dave Martin authored and Russell King committed Nov 30, 2013
1 parent 5091333 commit e2ccba4
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 9 deletions.
17 changes: 10 additions & 7 deletions arch/arm/kernel/machine_kexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

/*
Expand All @@ -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);
}
8 changes: 6 additions & 2 deletions arch/arm/kernel/relocate_kernel.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit e2ccba4

Please sign in to comment.