Commit 6672f76a authored by Simon Horman's avatar Simon Horman Committed by Linus Torvalds

kdump/kexec: calculate note size at compile time

Currently the size of the per-cpu region reserved to save crash notes is
set by the per-architecture value MAX_NOTE_BYTES.  Which in turn is
currently set to 1024 on all supported architectures.

While testing ia64 I recently discovered that this value is in fact too
small.  The particular setup I was using actually needs 1172 bytes.  This
lead to very tedious failure mode where the tail of one elf note would
overwrite the head of another if they ended up being alocated sequentially
by kmalloc, which was often the case.

It seems to me that a far better approach is to caclculate the size that
the area needs to be.  This patch does just that.

If a simpler stop-gap patch for ia64 to be squeezed into 2.6.21(.X) is
needed then this should be as easy as making MAX_NOTE_BYTES larger in
arch/asm-ia64/kexec.h.  Perhaps 2048 would be a good choice.  However, I
think that the approach in this patch is a much more robust idea.
Acked-by: default avatarVivek Goyal <vgoyal@in.ibm.com>
Signed-off-by: default avatarSimon Horman <horms@verge.net.au>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 73285082
...@@ -74,7 +74,7 @@ crash_save_this_cpu(void) ...@@ -74,7 +74,7 @@ crash_save_this_cpu(void)
buf = (u64 *) per_cpu_ptr(crash_notes, cpu); buf = (u64 *) per_cpu_ptr(crash_notes, cpu);
if (!buf) if (!buf)
return; return;
buf = append_elf_note(buf, "CORE", NT_PRSTATUS, prstatus, buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS, prstatus,
sizeof(*prstatus)); sizeof(*prstatus));
final_note(buf); final_note(buf);
} }
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#define MAX_NOTE_BYTES 1024
struct kimage; struct kimage;
/* Provide a dummy definition to avoid build failures. */ /* Provide a dummy definition to avoid build failures. */
static inline void crash_setup_regs(struct pt_regs *newregs, static inline void crash_setup_regs(struct pt_regs *newregs,
......
...@@ -45,8 +45,6 @@ ...@@ -45,8 +45,6 @@
/* We can also handle crash dumps from 64 bit kernel. */ /* We can also handle crash dumps from 64 bit kernel. */
#define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64) #define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64)
#define MAX_NOTE_BYTES 1024
/* CPU does not save ss and esp on stack if execution is already /* CPU does not save ss and esp on stack if execution is already
* running in kernel mode at the time of NMI occurrence. This code * running in kernel mode at the time of NMI occurrence. This code
* fixes it. * fixes it.
......
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
/* The native architecture */ /* The native architecture */
#define KEXEC_ARCH KEXEC_ARCH_IA_64 #define KEXEC_ARCH KEXEC_ARCH_IA_64
#define MAX_NOTE_BYTES 1024
#define kexec_flush_icache_page(page) do { \ #define kexec_flush_icache_page(page) do { \
unsigned long page_addr = (unsigned long)page_address(page); \ unsigned long page_addr = (unsigned long)page_address(page); \
flush_icache_range(page_addr, page_addr + PAGE_SIZE); \ flush_icache_range(page_addr, page_addr + PAGE_SIZE); \
......
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
/* The native architecture */ /* The native architecture */
#define KEXEC_ARCH KEXEC_ARCH_MIPS #define KEXEC_ARCH KEXEC_ARCH_MIPS
#define MAX_NOTE_BYTES 1024
static inline void crash_setup_regs(struct pt_regs *newregs, static inline void crash_setup_regs(struct pt_regs *newregs,
struct pt_regs *oldregs) struct pt_regs *oldregs)
{ {
......
...@@ -108,8 +108,6 @@ static inline void crash_setup_regs(struct pt_regs *newregs, ...@@ -108,8 +108,6 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
struct pt_regs *oldregs) { } struct pt_regs *oldregs) { }
#endif /* !__powerpc64 __ */ #endif /* !__powerpc64 __ */
#define MAX_NOTE_BYTES 1024
extern void kexec_smp_wait(void); /* get and clear naca physid, wait for extern void kexec_smp_wait(void); /* get and clear naca physid, wait for
master to copy new code to 0 */ master to copy new code to 0 */
extern int crashing_cpu; extern int crashing_cpu;
......
...@@ -34,8 +34,6 @@ ...@@ -34,8 +34,6 @@
/* The native architecture */ /* The native architecture */
#define KEXEC_ARCH KEXEC_ARCH_S390 #define KEXEC_ARCH KEXEC_ARCH_S390
#define MAX_NOTE_BYTES 1024
/* Provide a dummy definition to avoid build failures. */ /* Provide a dummy definition to avoid build failures. */
static inline void crash_setup_regs(struct pt_regs *newregs, static inline void crash_setup_regs(struct pt_regs *newregs,
struct pt_regs *oldregs) { } struct pt_regs *oldregs) { }
......
...@@ -26,8 +26,6 @@ ...@@ -26,8 +26,6 @@
/* The native architecture */ /* The native architecture */
#define KEXEC_ARCH KEXEC_ARCH_SH #define KEXEC_ARCH KEXEC_ARCH_SH
#define MAX_NOTE_BYTES 1024
static inline void crash_setup_regs(struct pt_regs *newregs, static inline void crash_setup_regs(struct pt_regs *newregs,
struct pt_regs *oldregs) struct pt_regs *oldregs)
{ {
......
...@@ -48,8 +48,6 @@ ...@@ -48,8 +48,6 @@
/* The native architecture */ /* The native architecture */
#define KEXEC_ARCH KEXEC_ARCH_X86_64 #define KEXEC_ARCH KEXEC_ARCH_X86_64
#define MAX_NOTE_BYTES 1024
/* /*
* Saving the registers of the cpu on which panic occured in * Saving the registers of the cpu on which panic occured in
* crash_kexec to save a valid sp. The registers of other cpus * crash_kexec to save a valid sp. The registers of other cpus
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/elfcore.h>
#include <linux/elf.h>
#include <asm/kexec.h> #include <asm/kexec.h>
/* Verify architecture specific macros are defined */ /* Verify architecture specific macros are defined */
...@@ -31,6 +33,19 @@ ...@@ -31,6 +33,19 @@
#error KEXEC_ARCH not defined #error KEXEC_ARCH not defined
#endif #endif
#define KEXEC_NOTE_HEAD_BYTES ALIGN(sizeof(struct elf_note), 4)
#define KEXEC_CORE_NOTE_NAME "CORE"
#define KEXEC_CORE_NOTE_NAME_BYTES ALIGN(sizeof(KEXEC_CORE_NOTE_NAME), 4)
#define KEXEC_CORE_NOTE_DESC_BYTES ALIGN(sizeof(struct elf_prstatus), 4)
/*
* The per-cpu notes area is a list of notes terminated by a "NULL"
* note header. For kdump, the code in vmcore.c runs in the context
* of the second kernel to combine them into one note.
*/
#define KEXEC_NOTE_BYTES ( (KEXEC_NOTE_HEAD_BYTES * 2) + \
KEXEC_CORE_NOTE_NAME_BYTES + \
KEXEC_CORE_NOTE_DESC_BYTES )
/* /*
* This structure is used to hold the arguments that are used when loading * This structure is used to hold the arguments that are used when loading
* kernel binaries. * kernel binaries.
...@@ -136,7 +151,7 @@ extern struct kimage *kexec_crash_image; ...@@ -136,7 +151,7 @@ extern struct kimage *kexec_crash_image;
/* Location of a reserved region to hold the crash kernel. /* Location of a reserved region to hold the crash kernel.
*/ */
extern struct resource crashk_res; extern struct resource crashk_res;
typedef u32 note_buf_t[MAX_NOTE_BYTES/4]; typedef u32 note_buf_t[KEXEC_NOTE_BYTES/4];
extern note_buf_t *crash_notes; extern note_buf_t *crash_notes;
......
...@@ -1118,8 +1118,8 @@ void crash_save_cpu(struct pt_regs *regs, int cpu) ...@@ -1118,8 +1118,8 @@ void crash_save_cpu(struct pt_regs *regs, int cpu)
memset(&prstatus, 0, sizeof(prstatus)); memset(&prstatus, 0, sizeof(prstatus));
prstatus.pr_pid = current->pid; prstatus.pr_pid = current->pid;
elf_core_copy_regs(&prstatus.pr_reg, regs); elf_core_copy_regs(&prstatus.pr_reg, regs);
buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus, buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS,
sizeof(prstatus)); &prstatus, sizeof(prstatus));
final_note(buf); final_note(buf);
} }
......
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