Commit 6672f76a5a1878d42264c1deba8f1ab52b4618d9

Authored by Simon Horman
Committed by Linus Torvalds
1 parent 7328508274

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:  Vivek Goyal <vgoyal@in.ibm.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 11 changed files with 19 additions and 20 deletions Side-by-side Diff

arch/ia64/kernel/crash.c
... ... @@ -74,7 +74,7 @@
74 74 buf = (u64 *) per_cpu_ptr(crash_notes, cpu);
75 75 if (!buf)
76 76 return;
77   - buf = append_elf_note(buf, "CORE", NT_PRSTATUS, prstatus,
  77 + buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS, prstatus,
78 78 sizeof(*prstatus));
79 79 final_note(buf);
80 80 }
include/asm-arm/kexec.h
... ... @@ -16,8 +16,6 @@
16 16  
17 17 #ifndef __ASSEMBLY__
18 18  
19   -#define MAX_NOTE_BYTES 1024
20   -
21 19 struct kimage;
22 20 /* Provide a dummy definition to avoid build failures. */
23 21 static inline void crash_setup_regs(struct pt_regs *newregs,
include/asm-i386/kexec.h
... ... @@ -45,8 +45,6 @@
45 45 /* We can also handle crash dumps from 64 bit kernel. */
46 46 #define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64)
47 47  
48   -#define MAX_NOTE_BYTES 1024
49   -
50 48 /* CPU does not save ss and esp on stack if execution is already
51 49 * running in kernel mode at the time of NMI occurrence. This code
52 50 * fixes it.
include/asm-ia64/kexec.h
... ... @@ -14,8 +14,6 @@
14 14 /* The native architecture */
15 15 #define KEXEC_ARCH KEXEC_ARCH_IA_64
16 16  
17   -#define MAX_NOTE_BYTES 1024
18   -
19 17 #define kexec_flush_icache_page(page) do { \
20 18 unsigned long page_addr = (unsigned long)page_address(page); \
21 19 flush_icache_range(page_addr, page_addr + PAGE_SIZE); \
include/asm-mips/kexec.h
... ... @@ -21,8 +21,6 @@
21 21 /* The native architecture */
22 22 #define KEXEC_ARCH KEXEC_ARCH_MIPS
23 23  
24   -#define MAX_NOTE_BYTES 1024
25   -
26 24 static inline void crash_setup_regs(struct pt_regs *newregs,
27 25 struct pt_regs *oldregs)
28 26 {
include/asm-powerpc/kexec.h
... ... @@ -108,8 +108,6 @@
108 108 struct pt_regs *oldregs) { }
109 109 #endif /* !__powerpc64 __ */
110 110  
111   -#define MAX_NOTE_BYTES 1024
112   -
113 111 extern void kexec_smp_wait(void); /* get and clear naca physid, wait for
114 112 master to copy new code to 0 */
115 113 extern int crashing_cpu;
include/asm-s390/kexec.h
... ... @@ -34,8 +34,6 @@
34 34 /* The native architecture */
35 35 #define KEXEC_ARCH KEXEC_ARCH_S390
36 36  
37   -#define MAX_NOTE_BYTES 1024
38   -
39 37 /* Provide a dummy definition to avoid build failures. */
40 38 static inline void crash_setup_regs(struct pt_regs *newregs,
41 39 struct pt_regs *oldregs) { }
include/asm-sh/kexec.h
... ... @@ -26,8 +26,6 @@
26 26 /* The native architecture */
27 27 #define KEXEC_ARCH KEXEC_ARCH_SH
28 28  
29   -#define MAX_NOTE_BYTES 1024
30   -
31 29 static inline void crash_setup_regs(struct pt_regs *newregs,
32 30 struct pt_regs *oldregs)
33 31 {
include/asm-x86_64/kexec.h
... ... @@ -48,8 +48,6 @@
48 48 /* The native architecture */
49 49 #define KEXEC_ARCH KEXEC_ARCH_X86_64
50 50  
51   -#define MAX_NOTE_BYTES 1024
52   -
53 51 /*
54 52 * Saving the registers of the cpu on which panic occured in
55 53 * crash_kexec to save a valid sp. The registers of other cpus
include/linux/kexec.h
... ... @@ -7,6 +7,8 @@
7 7 #include <linux/linkage.h>
8 8 #include <linux/compat.h>
9 9 #include <linux/ioport.h>
  10 +#include <linux/elfcore.h>
  11 +#include <linux/elf.h>
10 12 #include <asm/kexec.h>
11 13  
12 14 /* Verify architecture specific macros are defined */
13 15  
... ... @@ -31,7 +33,20 @@
31 33 #error KEXEC_ARCH not defined
32 34 #endif
33 35  
  36 +#define KEXEC_NOTE_HEAD_BYTES ALIGN(sizeof(struct elf_note), 4)
  37 +#define KEXEC_CORE_NOTE_NAME "CORE"
  38 +#define KEXEC_CORE_NOTE_NAME_BYTES ALIGN(sizeof(KEXEC_CORE_NOTE_NAME), 4)
  39 +#define KEXEC_CORE_NOTE_DESC_BYTES ALIGN(sizeof(struct elf_prstatus), 4)
34 40 /*
  41 + * The per-cpu notes area is a list of notes terminated by a "NULL"
  42 + * note header. For kdump, the code in vmcore.c runs in the context
  43 + * of the second kernel to combine them into one note.
  44 + */
  45 +#define KEXEC_NOTE_BYTES ( (KEXEC_NOTE_HEAD_BYTES * 2) + \
  46 + KEXEC_CORE_NOTE_NAME_BYTES + \
  47 + KEXEC_CORE_NOTE_DESC_BYTES )
  48 +
  49 +/*
35 50 * This structure is used to hold the arguments that are used when loading
36 51 * kernel binaries.
37 52 */
... ... @@ -136,7 +151,7 @@
136 151 /* Location of a reserved region to hold the crash kernel.
137 152 */
138 153 extern struct resource crashk_res;
139   -typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
  154 +typedef u32 note_buf_t[KEXEC_NOTE_BYTES/4];
140 155 extern note_buf_t *crash_notes;
141 156  
142 157  
... ... @@ -1118,8 +1118,8 @@
1118 1118 memset(&prstatus, 0, sizeof(prstatus));
1119 1119 prstatus.pr_pid = current->pid;
1120 1120 elf_core_copy_regs(&prstatus.pr_reg, regs);
1121   - buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
1122   - sizeof(prstatus));
  1121 + buf = append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS,
  1122 + &prstatus, sizeof(prstatus));
1123 1123 final_note(buf);
1124 1124 }
1125 1125