[PATCH 3.10 066/143] ARM: 7897/1: kexec: Use the right ISA for relocate_new_kernel

From: Greg Kroah-Hartman
Date: Fri Oct 03 2014 - 18:25:34 EST


3.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dave Martin <dave.martin@xxxxxxxxxx>

commit e2ccba49085ab5d71b092de2a5176eb9b19cc876 upstream.

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 <Dave.Martin@xxxxxxx>
Acked-by: Will Deacon <will.deacon@xxxxxxx>
Reported-by: Taras Kondratiuk <taras.kondratiuk@xxxxxxxxxx>
Tested-by: Taras Kondratiuk <taras.kondratiuk@xxxxxxxxxx>
Signed-off-by: Russell King <rmk+kernel@xxxxxxxxxxxxxxxx>
Integrated-by: Liu Hua <sdu.liu@xxxxxxxxxx>
Signed-off-by: Liu Hua <sdu.liu@xxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
arch/arm/kernel/machine_kexec.c | 17 ++++++++++-------
arch/arm/kernel/relocate_kernel.S | 8 ++++++--
2 files changed, 16 insertions(+), 9 deletions(-)

--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -14,10 +14,11 @@
#include <asm/pgalloc.h>
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>
+#include <asm/fncpy.h>
#include <asm/mach-types.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;
@@ -133,6 +134,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;

if (num_online_cpus() > 1) {
@@ -156,18 +159,18 @@ 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);
}

void arch_crash_save_vmcoreinfo(void)
--- a/arch/arm/kernel/relocate_kernel.S
+++ b/arch/arm/kernel/relocate_kernel.S
@@ -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


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/