Skip to content

Commit

Permalink
ARM: kexec: fix failure to boot crash kernel
Browse files Browse the repository at this point in the history
When kexec was converted to DTB, the dtb address was passed between
machine_kexec_prepare() and machine_kexec() using a static variable.
This is bad news if you load a crash kernel followed by a normal
kernel or vice versa - the last loaded kernel overwrites the dtb
address.

This can result in kexec failures, as (eg) we try to boot the crash
kernel with the last loaded dtb.  For example, with:

the crash kernel fails to find the dtb.

Avoid this by defining a kimage architecture structure, and store
the address to be passed in r2 there, which will either be the ATAGs
or the dtb blob.

Fixes: 4cabd1d ("ARM: 7539/1: kexec: scan for dtb magic in segments")
Fixes: 42d720d ("ARM: kexec: Make .text R/W in machine_kexec")
Reported-by: Keerthy <j-keerthy@ti.com>
Tested-by: Keerthy <j-keerthy@ti.com>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
  • Loading branch information
Russell King committed Jul 20, 2017
1 parent 67556d7 commit 0d70262
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 5 deletions.
5 changes: 5 additions & 0 deletions arch/arm/include/asm/kexec.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@

#ifndef __ASSEMBLY__

#define ARCH_HAS_KIMAGE_ARCH
struct kimage_arch {
u32 kernel_r2;
};

/**
* crash_setup_regs() - save registers for the panic kernel
* @newregs: registers are saved here
Expand Down
11 changes: 6 additions & 5 deletions arch/arm/kernel/machine_kexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ extern unsigned long kexec_boot_atags;

static atomic_t waiting_for_crash_ipi;

static unsigned long dt_mem;
/*
* Provide a dummy crash_notes definition while crash dump arrives to arm.
* This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
Expand All @@ -42,6 +41,9 @@ int machine_kexec_prepare(struct kimage *image)
__be32 header;
int i, err;

image->arch.kernel_r2 = image->start - KEXEC_ARM_ZIMAGE_OFFSET
+ KEXEC_ARM_ATAGS_OFFSET;

/*
* Validate that if the current HW supports SMP, then the SW supports
* and implements CPU hotplug for the current HW. If not, we won't be
Expand All @@ -66,8 +68,8 @@ int machine_kexec_prepare(struct kimage *image)
if (err)
return err;

if (be32_to_cpu(header) == OF_DT_HEADER)
dt_mem = current_segment->mem;
if (header == cpu_to_be32(OF_DT_HEADER))
image->arch.kernel_r2 = current_segment->mem;
}
return 0;
}
Expand Down Expand Up @@ -165,8 +167,7 @@ void machine_kexec(struct kimage *image)
kexec_start_address = image->start;
kexec_indirection_page = page_list;
kexec_mach_type = machine_arch_type;
kexec_boot_atags = dt_mem ?: image->start - KEXEC_ARM_ZIMAGE_OFFSET
+ KEXEC_ARM_ATAGS_OFFSET;
kexec_boot_atags = image->arch.kernel_r2;

/* copy our kernel relocation code to the control code page */
reboot_entry = fncpy(reboot_code_buffer,
Expand Down

0 comments on commit 0d70262

Please sign in to comment.