Browse Source

x86, kdump: Retore crashkernel= to allocate under 896M

Vivek found old kexec-tools does not work new kernel anymore.

So change back crashkernel= back to old behavoir, and add crashkernel_high=
to let user decide if buffer could be above 4G, and also new kexec-tools will
be needed.

-v2: let crashkernel=X override crashkernel_high=
    update description about _high will be ignored by crashkernel=X
-v3: update description about kernel-parameters.txt according to Vivek.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1366089828-19692-4-git-send-email-yinghai@kernel.org
Acked-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Yinghai Lu 12 years ago
parent
commit
55a20ee780
4 changed files with 41 additions and 7 deletions
  1. 11 2
      Documentation/kernel-parameters.txt
  2. 19 5
      arch/x86/kernel/setup.c
  3. 2 0
      include/linux/kexec.h
  4. 9 0
      kernel/kexec.c

+ 11 - 2
Documentation/kernel-parameters.txt

@@ -603,9 +603,16 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			a memory unit (amount[KMG]). See also
 			a memory unit (amount[KMG]). See also
 			Documentation/kdump/kdump.txt for an example.
 			Documentation/kdump/kdump.txt for an example.
 
 
+	crashkernel_high=size[KMG]
+			[KNL, x86_64] range could be above 4G. Allow kernel
+			to allocate physical memory region from top, so could
+			be above 4G if system have more than 4G ram installed.
+			Otherwise memory region will be allocated below 4G, if
+			available.
+			It will be ignored if crashkernel=X is specified.
 	crashkernel_low=size[KMG]
 	crashkernel_low=size[KMG]
-			[KNL, x86_64] range under 4G. When crashkernel= is
-			passed, kernel allocate physical memory region
+			[KNL, x86_64] range under 4G. When crashkernel_high= is
+			passed, kernel could allocate physical memory region
 			above 4G, that cause second kernel crash on system
 			above 4G, that cause second kernel crash on system
 			that require some amount of low memory, e.g. swiotlb
 			that require some amount of low memory, e.g. swiotlb
 			requires at least 64M+32K low memory.  Kernel would
 			requires at least 64M+32K low memory.  Kernel would
@@ -613,6 +620,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			This one let user to specify own low range under 4G
 			This one let user to specify own low range under 4G
 			for second kernel instead.
 			for second kernel instead.
 			0: to disable low allocation.
 			0: to disable low allocation.
+			It will be ignored when crashkernel_high=X is not used
+			or memory reserved is below 4G.
 
 
 	cs89x0_dma=	[HW,NET]
 	cs89x0_dma=	[HW,NET]
 			Format: <dma>
 			Format: <dma>

+ 19 - 5
arch/x86/kernel/setup.c

@@ -507,11 +507,14 @@ static void __init memblock_x86_reserve_range_setup_data(void)
 /*
 /*
  * Keep the crash kernel below this limit.  On 32 bits earlier kernels
  * Keep the crash kernel below this limit.  On 32 bits earlier kernels
  * would limit the kernel to the low 512 MiB due to mapping restrictions.
  * would limit the kernel to the low 512 MiB due to mapping restrictions.
+ * On 64bit, old kexec-tools need to under 896MiB.
  */
  */
 #ifdef CONFIG_X86_32
 #ifdef CONFIG_X86_32
-# define CRASH_KERNEL_ADDR_MAX	(512 << 20)
+# define CRASH_KERNEL_ADDR_LOW_MAX	(512 << 20)
+# define CRASH_KERNEL_ADDR_HIGH_MAX	(512 << 20)
 #else
 #else
-# define CRASH_KERNEL_ADDR_MAX	MAXMEM
+# define CRASH_KERNEL_ADDR_LOW_MAX	(896UL<<20)
+# define CRASH_KERNEL_ADDR_HIGH_MAX	MAXMEM
 #endif
 #endif
 
 
 static void __init reserve_crashkernel_low(void)
 static void __init reserve_crashkernel_low(void)
@@ -525,6 +528,7 @@ static void __init reserve_crashkernel_low(void)
 	int ret;
 	int ret;
 
 
 	total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT));
 	total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT));
+	/* crashkernel_low=YM */
 	ret = parse_crashkernel_low(boot_command_line, total_low_mem,
 	ret = parse_crashkernel_low(boot_command_line, total_low_mem,
 						&low_size, &base);
 						&low_size, &base);
 	if (ret != 0) {
 	if (ret != 0) {
@@ -569,14 +573,22 @@ static void __init reserve_crashkernel(void)
 	const unsigned long long alignment = 16<<20;	/* 16M */
 	const unsigned long long alignment = 16<<20;	/* 16M */
 	unsigned long long total_mem;
 	unsigned long long total_mem;
 	unsigned long long crash_size, crash_base;
 	unsigned long long crash_size, crash_base;
+	bool high = false;
 	int ret;
 	int ret;
 
 
 	total_mem = memblock_phys_mem_size();
 	total_mem = memblock_phys_mem_size();
 
 
+	/* crashkernel=XM */
 	ret = parse_crashkernel(boot_command_line, total_mem,
 	ret = parse_crashkernel(boot_command_line, total_mem,
 			&crash_size, &crash_base);
 			&crash_size, &crash_base);
-	if (ret != 0 || crash_size <= 0)
-		return;
+	if (ret != 0 || crash_size <= 0) {
+		/* crashkernel_high=XM */
+		ret = parse_crashkernel_high(boot_command_line, total_mem,
+				&crash_size, &crash_base);
+		if (ret != 0 || crash_size <= 0)
+			return;
+		high = true;
+	}
 
 
 	/* 0 means: find the address automatically */
 	/* 0 means: find the address automatically */
 	if (crash_base <= 0) {
 	if (crash_base <= 0) {
@@ -584,7 +596,9 @@ static void __init reserve_crashkernel(void)
 		 *  kexec want bzImage is below CRASH_KERNEL_ADDR_MAX
 		 *  kexec want bzImage is below CRASH_KERNEL_ADDR_MAX
 		 */
 		 */
 		crash_base = memblock_find_in_range(alignment,
 		crash_base = memblock_find_in_range(alignment,
-			       CRASH_KERNEL_ADDR_MAX, crash_size, alignment);
+					high ? CRASH_KERNEL_ADDR_HIGH_MAX :
+					       CRASH_KERNEL_ADDR_LOW_MAX,
+					crash_size, alignment);
 
 
 		if (!crash_base) {
 		if (!crash_base) {
 			pr_info("crashkernel reservation failed - No suitable area found.\n");
 			pr_info("crashkernel reservation failed - No suitable area found.\n");

+ 2 - 0
include/linux/kexec.h

@@ -200,6 +200,8 @@ extern size_t vmcoreinfo_max_size;
 
 
 int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,
 int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,
 		unsigned long long *crash_size, unsigned long long *crash_base);
 		unsigned long long *crash_size, unsigned long long *crash_base);
+int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
+		unsigned long long *crash_size, unsigned long long *crash_base);
 int parse_crashkernel_low(char *cmdline, unsigned long long system_ram,
 int parse_crashkernel_low(char *cmdline, unsigned long long system_ram,
 		unsigned long long *crash_size, unsigned long long *crash_base);
 		unsigned long long *crash_size, unsigned long long *crash_base);
 int crash_shrink_memory(unsigned long new_size);
 int crash_shrink_memory(unsigned long new_size);

+ 9 - 0
kernel/kexec.c

@@ -1422,6 +1422,15 @@ int __init parse_crashkernel(char *cmdline,
 					"crashkernel=");
 					"crashkernel=");
 }
 }
 
 
+int __init parse_crashkernel_high(char *cmdline,
+			     unsigned long long system_ram,
+			     unsigned long long *crash_size,
+			     unsigned long long *crash_base)
+{
+	return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
+					"crashkernel_high=");
+}
+
 int __init parse_crashkernel_low(char *cmdline,
 int __init parse_crashkernel_low(char *cmdline,
 			     unsigned long long system_ram,
 			     unsigned long long system_ram,
 			     unsigned long long *crash_size,
 			     unsigned long long *crash_size,