Add extended crashkernel command line syntax
Subsystems (8)
cover Add extended crashkernel command line syntax
This patch adds a extended crashkernel syntax that makes the value of reserved system RAM dependent on the system RAM itself:
crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset]
range=start-[end]For example:
crashkernel=512M-2G:64M,2G-:128M
The motivation comes from distributors that configure their crashkernel command line automatically with some configuration tool (YaST, you know ;)). Of course that tool knows the value of System RAM, but if the user removes RAM, then the system becomes unbootable or at least unusable and error handling is very difficult.
This series implements this change for i386, x86_64, ia64, ppc64 and sh. That should be all platforms that support kdump in current mainline. I tested all platforms except sh due to the lack of a sh processor.
The patch series is against 2.6.23-rc4-mm1.
Modifications compared to last submit:
- put functions in __init
- print message when no base address is specified on i386/x86_64/sh
PATCH 1/7 Extended crashkernel command line
This is the generic part of the patch. It adds a parse_crashkernel() function in kernel/kexec.c that is called by the architecture specific code that actually reserves the memory. That function takes the whole command line and looks itself for "crashkernel=" in it.
If there are multiple occurrences, then the last one is taken. The advantage is that if you have a bootloader like lilo or elilo which allows you to append a command line parameter but not to remove one (like in GRUB), then you can add another crashkernel value for testing at the boot command line and this one overwrites the command line in the configuration then.
--- include/linux/kexec.h | 2 kernel/kexec.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+)
include/linux/kexec.h +2 -0
@@ -179,6 +179,8 @@ extern note_buf_t *crash_notes;extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE /4 ];extern unsigned int vmcoreinfo_size;extern unsigned int vmcoreinfo_max_size; +int __init parse_crashkernel (char *cmdline,unsigned long long system_ram, +unsigned long long *crash_size,unsigned long long *crash_base);#else /* !CONFIG_KEXEC */
kernel/kexec.c +141 -0
147 lines not on this page · raw message
PATCH 2/7 Use extended crashkernel command line on i386
In reply to Bernhard WalleThis patch removes the crashkernel parsing from arch/i386/kernel/machine_kexec.c and calls the generic function, introduced in the last patch, in setup_bootmem_allocator().
This is necessary because the amount of System RAM must be known in this function now because of the new syntax.
--- arch/i386/kernel/e820.c | 3 ++- arch/i386/kernel/machine_kexec.c | 22 ---------------------- arch/i386/kernel/setup.c | 37 ++++++++++++++++++++++++++++++++----- 3 files changed, 34 insertions(+), 28 deletions(-)
arch/i386/kernel/e820.c +2 -1
@@ -288,7 +288,8 @@ legacy_init_iomem_resources(struct resourequest_resource (res, code_resource);request_resource (res, data_resource);#ifdef CONFIG_KEXEC -request_resource (res, &crashk_res); +if (crashk_res.start != crashk_res.end) +request_resource (res, &crashk_res);#endif } }
arch/i386/kernel/machine_kexec.c +0 -22
@@ -149,28 +149,6 @@ NORET_TYPE void machine_kexec(struct kim image->start, cpu_has_pae); } -/* crashkernel=size@addr specifies the location to reserve for -* a crash kernel. By reserving this memory we guarantee -* that linux never sets it up as a DMA target. -* Useful for holding code to do something appropriate -* after a kernel panic. -*/ -static int __init parse_crashkernel (char *arg) -{ -unsigned long size, base; - size =memparse (arg, &arg); -if (*arg =='@' ) { - base =memparse (arg+1 , &arg); -/* FIXME: Do I want a sanity check -* to validate the memory range? -*/ - crashk_res.start = base; - crashk_res.end = base + size -1 ; - } -return 0 ; -} -early_param ("crashkernel" , parse_crashkernel); -void arch_crash_save_vmcoreinfo (void ) {#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
arch/i386/kernel/setup.c +32 -5
@@ -381,6 +381,37 @@ extern unsigned long __init setup_memoryextern void zone_sizes_init (void );#endif /* !CONFIG_NEED_MULTIPLE_NODES */ +#ifdef CONFIG_KEXEC +static void __init reserve_crashkernel (void ) +{ +unsigned long long free_mem; +unsigned long long crash_size, crash_base; +int ret; + + free_mem = (max_low_pfn + highend_pfn - highstart_pfn) <<PAGE_SHIFT ; + + ret =parse_crashkernel (boot_command_line, free_mem, + &crash_size, &crash_base); +if (ret ==0 && crash_size >0 ) { +if (crash_base >0 ) { +printk (KERN_INFO "Reserving %ldMB of memory at %ldMB " +"for crashkernel (System RAM: %ldMB)\n" , + (unsigned long )(crash_size >>20 ), + (unsigned long )(crash_base >>20 ), + (unsigned long )(free_mem >>20 )); + crashk_res.start = crash_base; + crashk_res.end = crash_base + crash_size -1 ; +reserve_bootmem (crash_base, crash_size); + }else +printk (KERN_INFO "crashkernel reservation failed - " +"you have to specify a base address\n" ); + } +} +#else +static inline void __init reserve_crashkernel (void ) +{} +#endif +void __init setup_bootmem_allocator (void ) {unsigned long bootmap_size;
@@ -456,11 +487,7 @@ void __init setup_bootmem_allocator(void } }#endif -#ifdef CONFIG_KEXEC -if (crashk_res.start != crashk_res.end) -reserve_bootmem (crashk_res.start, - crashk_res.end - crashk_res.start +1 ); -#endif +reserve_crashkernel (); }/*
PATCH 3/7 Use extended crashkernel command line on x86_64
In reply to Bernhard WalleThis patch removes the crashkernel parsing from arch/x86_64/kernel/machine_kexec.c and calls the generic function, introduced in the last patch, in setup_bootmem_allocator().
This is necessary because the amount of System RAM must be known in this function now because of the new syntax.
--- arch/x86_64/kernel/e820.c | 3 +- arch/x86_64/kernel/machine_kexec.c | 27 ------------------------- arch/x86_64/kernel/setup.c | 39 ++++++++++++++++++++++++++++++------- 3 files changed, 34 insertions(+), 35 deletions(-)
arch/x86_64/kernel/e820.c +2 -1
@@ -226,7 +226,8 @@ void __init e820_reserve_resources(void)request_resource (res, &code_resource);request_resource (res, &data_resource);#ifdef CONFIG_KEXEC -request_resource (res, &crashk_res); +if (crashk_res.start != crashk_res.end) +request_resource (res, &crashk_res);#endif } }
arch/x86_64/kernel/machine_kexec.c +0 -27
@@ -231,33 +231,6 @@ NORET_TYPE void machine_kexec(struct kim image->start); } -/* crashkernel=size@addr specifies the location to reserve for -* a crash kernel. By reserving this memory we guarantee -* that linux never set's it up as a DMA target. -* Useful for holding code to do something appropriate -* after a kernel panic. -*/ -static int __init setup_crashkernel (char *arg) -{ -unsigned long size, base; -char *p; -if (!arg) -return -EINVAL ; - size =memparse (arg, &p); -if (arg == p) -return -EINVAL ; -if (*p =='@' ) { - base =memparse (p+1 , &p); -/* FIXME: Do I want a sanity check to validate the -* memory range? Yes you do, but it's too early for -* e820 -AK */ - crashk_res.start = base; - crashk_res.end = base + size -1 ; - } -return 0 ; -} -early_param ("crashkernel" , setup_crashkernel); -void arch_crash_save_vmcoreinfo (void ) {#ifdef CONFIG_ARCH_DISCONTIGMEM_ENABLE
arch/x86_64/kernel/setup.c +32 -7
@@ -196,6 +196,37 @@ static inline void copy_edd(void) }#endif +#ifdef CONFIG_KEXEC +static void __init reserve_crashkernel (void ) +{ +unsigned long long free_mem; +unsigned long long crash_size, crash_base; +int ret; + + free_mem = max_low_pfn <<PAGE_SHIFT ; + + ret =parse_crashkernel (boot_command_line, free_mem, + &crash_size, &crash_base); +if (ret ==0 && crash_size) { +if (crash_base >0 ) { +printk (KERN_INFO "Reserving %ldMB of memory at %ldMB " +"for crashkernel (System RAM: %ldMB)\n" , + (unsigned long )(crash_size >>20 ), + (unsigned long )(crash_base >>20 ), + (unsigned long )(free_mem >>20 )); + crashk_res.start = crash_base; + crashk_res.end = crash_base + crash_size -1 ; +reserve_bootmem (crash_base, crash_size); + }else +printk (KERN_INFO "crashkernel reservation failed - " +"you have to specify a base address\n" ); + } +} +#else +static inline void __init reserve_crashkernel (void ) +{} +#endif +#define EBDA_ADDR_POINTER 0x40Eunsigned __initdata ebda_addr;
@@ -388,13 +419,7 @@ void __init setup_arch(char **cmdline_p) } }#endif -#ifdef CONFIG_KEXEC -if (crashk_res.start != crashk_res.end) { -reserve_bootmem_generic (crashk_res.start, - crashk_res.end - crashk_res.start +1 ); - } -#endif - +reserve_crashkernel ();paging_init ();#ifdef CONFIG_PCI
PATCH 4/7 Use extended crashkernel command line on ia64
In reply to Bernhard WalleThis patch adapts IA64 to use the generic parse_crashkernel() function instead of its own parsing for the crashkernel command line.
Because the total amount of System RAM must be known when calling this function, efi_memmap_init() is modified to return its accumulated total_memory variable.
Also, the crashkernel handling is moved in an own function in arch/ia64/kernel/setup.c to make the code more readable.
--- arch/ia64/kernel/efi.c | 4 +- arch/ia64/kernel/setup.c | 88 +++++++++++++++++++++++---------------------- include/asm-ia64/meminit.h | 2 - 3 files changed, 50 insertions(+), 44 deletions(-)
arch/ia64/kernel/efi.c +3 -1
@@ -967,7 +967,7 @@ find_memmap_space (void)* to use. We can allocate partial granules only if the unavailable * parts exist, and are WB. */ -void +unsigned long efi_memmap_init (unsigned long *s,unsigned long *e) {struct kern_memdesc *k, *prev =NULL ;
@@ -1084,6 +1084,8 @@ efi_memmap_init(unsigned long *s, unsign/* reserve the memory we are using for kern_memmap */ *s = (u64 )kern_memmap; *e = (u64 )++k; + +return total_memory; }void
arch/ia64/kernel/setup.c +46 -42
108 lines not on this page · raw message
include/asm-ia64/meminit.h +1 -1
@@ -35,7 +35,7 @@ extern void find_memory (void);extern void reserve_memory (void );extern void find_initrd (void );extern int filter_rsvd_memory (unsigned long start,unsigned long end,void *arg); -extern void efi_memmap_init (unsigned long *,unsigned long *); +extern unsigned long efi_memmap_init (unsigned long *s,unsigned long *e);extern int find_max_min_low_pfn (unsigned long ,unsigned long ,void *);extern unsigned long vmcore_find_descriptor_size (unsigned long address);
PATCH 5/7 Use extended crashkernel command line on ppc64
In reply to Bernhard WalleThis patch adapts the ppc64 code to use the generic parse_crashkernel() function introduced in the generic patch of that series.
--- arch/powerpc/kernel/machine_kexec.c | 52 ++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-)
arch/powerpc/kernel/machine_kexec.c +26 -26
@@ -61,45 +61,39 @@ NORET_TYPE void machine_kexec(struct kimfor (;;); } -static int __init early_parse_crashk (char *p) +void __init reserve_crashkernel (void ) { -unsigned long size; - -if (!p) -return 1 ; - - size =memparse (p, &p); +unsigned long long crash_size =0 , crash_base; +int ret; -if (*p =='@' ) - crashk_res.start =memparse (p +1 , &p); -else - crashk_res.start =KDUMP_KERNELBASE ; - - crashk_res.end = crashk_res.start + size -1 ; - -return 0 ; -} -early_param ("crashkernel" , early_parse_crashk); +/* this is necessary because of lmb_phys_mem_size() */ +lmb_analyze (); -void __init reserve_crashkernel (void ) -{ -unsigned long size; +/* use common parsing */ + ret =parse_crashkernel (boot_command_line,lmb_phys_mem_size (), + &crash_size, &crash_base); +if (ret ==0 && crash_size >0 ) { +if (crash_base ==0 ) + crash_base =KDUMP_KERNELBASE ; + crashk_res.start = crash_base; + }else { +/* handle the device tree */ + crash_size = crashk_res.end - crashk_res.start +1 ; + } -if (crashk_res.start ==0 ) +if (crash_size ==0 )return ;/* We might have got these values via the command line or the * device tree, either way sanitise them now. */ - size = crashk_res.end - crashk_res.start +1 ; -if (crashk_res.start !=KDUMP_KERNELBASE )printk ("Crash kernel location must be 0x%x\n" ,KDUMP_KERNELBASE ); crashk_res.start =KDUMP_KERNELBASE ; - size =PAGE_ALIGN (size); - crashk_res.end = crashk_res.start + size -1 ; + crash_size =PAGE_ALIGN (crash_size); + crashk_res.end = crashk_res.start + crash_size -1 ;/* Crash kernel trumps memory limit */ if (memory_limit && memory_limit <= crashk_res.end) {
@@ -108,7 +102,13 @@ void __init reserve_crashkernel(void) memory_limit); } -lmb_reserve (crashk_res.start, size); +printk (KERN_INFO "Reserving %ldMB of memory at %ldMB " +"for crashkernel (System RAM: %ldMB)\n" , + (unsigned long )(crash_size >>20 ), + (unsigned long )(crashk_res.start >>20 ), + (unsigned long )(lmb_phys_mem_size () >>20 )); + +lmb_reserve (crashk_res.start, crash_size); }int overlaps_crashkernel (unsigned long start,unsigned long size)
PATCH 6/7 Use extended crashkernel command line on sh
In reply to Bernhard WalleThis patch removes the crashkernel parsing from arch/sh/kernel/machine_kexec.c and calls the generic function, introduced in the generic patch, in setup_bootmem_allocator().
This is necessary because the amount of System RAM must be known in this function now because of the new syntax.
NOTE: Due to the lack of a SH processor, this patch is untested (and uncompiled). Because the code in that area is quite similar as i386/x86_64 (contrary to PPC and IA64), it should compile and work. However, if someone of the SH people could test for me and provide feedback, that would be very nice.
--- arch/sh/kernel/machine_kexec.c | 21 --------------------- arch/sh/kernel/setup.c | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 26 deletions(-)
arch/sh/kernel/machine_kexec.c +0 -21
@@ -104,24 +104,3 @@ NORET_TYPE void machine_kexec(struct kim (*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg); } -/* crashkernel=size@addr specifies the location to reserve for -* a crash kernel. By reserving this memory we guarantee -* that linux never sets it up as a DMA target. -* Useful for holding code to do something appropriate -* after a kernel panic. -*/ -static int __init parse_crashkernel (char *arg) -{ -unsigned long size, base; - size =memparse (arg, &arg); -if (*arg =='@' ) { - base =memparse (arg+1 , &arg); -/* FIXME: Do I want a sanity check -* to validate the memory range? -*/ - crashk_res.start = base; - crashk_res.end = base + size -1 ; - } -return 0 ; -} -early_param ("crashkernel" , parse_crashkernel);
arch/sh/kernel/setup.c +33 -5
@@ -121,6 +121,37 @@ static void __init register_bootmem_low_free_bootmem (PFN_PHYS (curr_pfn),PFN_PHYS (pages)); } +#ifdef CONFIG_KEXEC +static void __init reserve_crashkernel (void ) +{ +unsigned long long free_mem; +unsigned long long crash_size, crash_base; +int ret; + + free_mem = (max_low_pfn - min_low_pfn) <<PAGE_SHIFT ; + + ret =parse_crashkernel (boot_command_line, free_mem, + &crash_size, &crash_base); +if (ret ==0 && crash_size) { +if (crash_base >0 ) { +printk (KERN_INFO "Reserving %ldMB of memory at %ldMB " +"for crashkernel (System RAM: %ldMB)\n" , + (unsigned long )(crash_size >>20 ), + (unsigned long )(crash_base >>20 ), + (unsigned long )(free_mem >>20 )); + crashk_res.start = crash_base; + crashk_res.end = crash_base + crash_size -1 ; +reserve_bootmem (crash_base, crash_size); + }else +printk (KERN_INFO "crashkernel reservation failed - " +"you have to specify a base address\n" ); + } +} +#else +static inline void __init reserve_crashkernel (void ) +{} +#endif +void __init setup_bootmem_allocator (unsigned long free_pfn) {unsigned long bootmap_size;
@@ -182,11 +213,8 @@ void __init setup_bootmem_allocator(unsi } }#endif -#ifdef CONFIG_KEXEC -if (crashk_res.start != crashk_res.end) -reserve_bootmem (crashk_res.start, - crashk_res.end - crashk_res.start +1 ); -#endif + +reserve_crashkernel (); }#ifndef CONFIG_NEED_MULTIPLE_NODES
PATCH 7/7 Add documentation for extended crashkernel syntax
In reply to Bernhard WalleThis adds the documentation for the extended crashkernel syntax into Documentation/kdump/kdump.txt.
--- Documentation/kdump/kdump.txt | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
Documentation/kdump/kdump.txt +26 -0
@@ -231,6 +231,32 @@ Dump-capture kernel config options (Arch any space below the alignment point will be wasted. +Extended crashkernel syntax +=========================== + +While the "crashkernel=size[@offset]" syntax is sufficient for most +configurations, sometimes it's handy to have the reserved memory dependent +on the value of System RAM -- that's mostly for distributors that pre-setup +the kernel command line to avoid a unbootable system after some memory has +been removed from the machine. + +The syntax is: + + crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset] + range=start-[end] + +For example: + + crashkernel=512M-2G:64M,2G-:128M + +This would mean: + + 1) if the RAM is smaller than 512M, then don't reserve anything + (this is the "rescue" case) + 2) if the RAM size is between 512M and 2G, then reserve 64M + 3) if the RAM size is larger than 2G, then reserve 128M + + Boot into System Kernel =======================
Re: [patch 1/7] Extended crashkernel command line
In reply to Bernhard Walle* Thu, 20 Sep 2007 19:18:46 +0200
[]
include/linux/kexec.h extern note_buf_t *crash_notes; · line 183
Quoted 5 lines
extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4]; extern unsigned int
vmcoreinfo_size;
extern unsigned intvmcoreinfo_max_size;include/linux/kexec.h +2
-0+int __init parse_crashkernel (char *cmdline,unsigned long long system_ram, +unsigned long long *crash_size,unsigned long long *crash_base);
(BTW, why system_ram' is unsigned long' in parse_crashkernel_mem() but `unsigned long long' in parse_crashkernel()?)
kernel/kexec.c static int __init crash_notes_memory_ini · line 1174
Quoted 11 lines
kernel/kexec.c +11
-0+static int __init parse_crashkernel_mem (char *cmdline, +unsigned long system_ram, +unsigned long long *crash_size, +unsigned long long *crash_base) +{ +char *cur = cmdline; + +/* for each entry of the comma-separated list */ + do { + unsigned long long start = 0, end = ULLONG_MAX; + unsigned long long size = -1;
[]
What is the point of not using ulong' and u64'?
What about another names?
+int __init get_crashkernel_params(u64 *memsize, u64 *addrbase, char *cmdline, u64 ram);
_____
Re: [patch 1/7] Extended crashkernel command line
Quoted 11 lines · Oleg Verych
* Thu, 20 Sep 2007 19:18:46 +0200
[]
include/linux/kexec.h extern note_buf_t *crash_notes; · line 183
Quoted 5 lines
extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4]; extern unsigned int
vmcoreinfo_size;
extern unsigned intvmcoreinfo_max_size;include/linux/kexec.h +2
-0+int __init parse_crashkernel (char *cmdline,unsigned long long system_ram, +unsigned long long *crash_size,unsigned long long *crash_base);(BTW, why
system_ram' isunsigned long' inparse_crashkernel_mem()but `unsigned long long' inparse_crashkernel()?)
Because that's a bug, thanks for spotting that out. I will sent an updated version of this patch until the issue below has been clarified:
Quoted 5 lines
What is the point of not using
ulong' andu64'?What about another names?
+int
__initget_crashkernel_params(u64 *memsize, u64 *addrbase, char *cmdline, u64 ram);
Andrew, what's your opinion on this? Whould I resend the patch with shorter type names?
Thanks,
Bernhard
Re: [patch 1/7] Extended crashkernel command line
On Sun, Sep 23, 2007 at 10:19:43PM +0200, Bernhard Walle wrote:
[]
Quoted 4 lines
Quoted 1 line
+int
__initget_crashkernel_params(u64 *memsize, u64 *addrbase, char *cmdline, u64 ram);Andrew, what's your opinion on this? Whould I resend the patch with shorter type names?
Also, maybe it will be better to extend linux/lib/cmdline.c->{get_range(), get_range()} to handle that stuff? And maybe new functionality can be built up-on the current one:
- crashkernel=512M-2G:64M,2G-:128M@offset
+ crashkernel=512M-2G,64M,2G-,128M,,offset
?
OK, OK, you are already using and maintaining new syntax, but still.
_____
(`Mail-Followup-To' ignored)
Re: [patch 1/7] Extended crashkernel command line
Quoted 4 lines · Oleg Verych
- crashkernel=512M-2G:64M,2G-:128M@offset
+ crashkernel=512M-2G,64M,2G-,128M,,offset
?
I don't like this syntax.
Thanks,
Bernhard