summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2013-01-24 15:20:11 -0500
committerH. Peter Anvin <hpa@linux.intel.com>2013-01-29 22:32:58 -0500
commit0212f9159694be61c6bc52e925fa76643e0c1abf (patch)
tree21fff008e27df08d3ab650d9c2421b490fcdc926
parent7d41a8a4a2b2438621a9159477bff36a11d79a42 (diff)
x86: Add Crash kernel low reservation
During kdump kernel's booting stage, it need to find low ram for swiotlb buffer when system does not support intel iommu/dmar remapping. kexed-tools is appending memmap=exactmap and range from /proc/iomem with "Crash kernel", and that range is above 4G for 64bit after boot protocol 2.12. We need to add another range in /proc/iomem like "Crash kernel low", so kexec-tools could find that info and append to kdump kernel command line. Try to reserve some under 4G if the normal "Crash kernel" is above 4G. User could specify the size with crashkernel_low=XX[KMG]. -v2: fix warning that is found by Fengguang's test robot. -v3: move out get_mem_size change to another patch, to solve compiling warning that is found by Borislav Petkov <bp@alien8.de> -v4: user must specify crashkernel_low if system does not support intel or amd iommu. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Link: http://lkml.kernel.org/r/1359058816-7615-31-git-send-email-yinghai@kernel.org Cc: Eric Biederman <ebiederm@xmission.com> Cc: Rob Landley <rob@landley.net> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--Documentation/kernel-parameters.txt3
-rw-r--r--arch/x86/kernel/setup.c42
-rw-r--r--include/linux/kexec.h3
-rw-r--r--kernel/kexec.c34
4 files changed, 75 insertions, 7 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 363e348bff9b..da0e0773ca96 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -594,6 +594,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
594 is selected automatically. Check 594 is selected automatically. Check
595 Documentation/kdump/kdump.txt for further details. 595 Documentation/kdump/kdump.txt for further details.
596 596
597 crashkernel_low=size[KMG]
598 [KNL, x86] parts under 4G.
599
597 crashkernel=range1:size1[,range2:size2,...][@offset] 600 crashkernel=range1:size1[,range2:size2,...][@offset]
598 [KNL] Same as above, but depends on the memory 601 [KNL] Same as above, but depends on the memory
599 in the running system. The syntax of range is 602 in the running system. The syntax of range is
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 4778ddeedc8a..5dc47c3e537b 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -508,8 +508,44 @@ static void __init memblock_x86_reserve_range_setup_data(void)
508# define CRASH_KERNEL_ADDR_MAX MAXMEM 508# define CRASH_KERNEL_ADDR_MAX MAXMEM
509#endif 509#endif
510 510
511static void __init reserve_crashkernel_low(void)
512{
513#ifdef CONFIG_X86_64
514 const unsigned long long alignment = 16<<20; /* 16M */
515 unsigned long long low_base = 0, low_size = 0;
516 unsigned long total_low_mem;
517 unsigned long long base;
518 int ret;
519
520 total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT));
521 ret = parse_crashkernel_low(boot_command_line, total_low_mem,
522 &low_size, &base);
523 if (ret != 0 || low_size <= 0)
524 return;
525
526 low_base = memblock_find_in_range(low_size, (1ULL<<32),
527 low_size, alignment);
528
529 if (!low_base) {
530 pr_info("crashkernel low reservation failed - No suitable area found.\n");
531
532 return;
533 }
534
535 memblock_reserve(low_base, low_size);
536 pr_info("Reserving %ldMB of low memory at %ldMB for crashkernel (System low RAM: %ldMB)\n",
537 (unsigned long)(low_size >> 20),
538 (unsigned long)(low_base >> 20),
539 (unsigned long)(total_low_mem >> 20));
540 crashk_low_res.start = low_base;
541 crashk_low_res.end = low_base + low_size - 1;
542 insert_resource(&iomem_resource, &crashk_low_res);
543#endif
544}
545
511static void __init reserve_crashkernel(void) 546static void __init reserve_crashkernel(void)
512{ 547{
548 const unsigned long long alignment = 16<<20; /* 16M */
513 unsigned long long total_mem; 549 unsigned long long total_mem;
514 unsigned long long crash_size, crash_base; 550 unsigned long long crash_size, crash_base;
515 int ret; 551 int ret;
@@ -523,8 +559,6 @@ static void __init reserve_crashkernel(void)
523 559
524 /* 0 means: find the address automatically */ 560 /* 0 means: find the address automatically */
525 if (crash_base <= 0) { 561 if (crash_base <= 0) {
526 const unsigned long long alignment = 16<<20; /* 16M */
527
528 /* 562 /*
529 * kexec want bzImage is below CRASH_KERNEL_ADDR_MAX 563 * kexec want bzImage is below CRASH_KERNEL_ADDR_MAX
530 */ 564 */
@@ -535,6 +569,7 @@ static void __init reserve_crashkernel(void)
535 pr_info("crashkernel reservation failed - No suitable area found.\n"); 569 pr_info("crashkernel reservation failed - No suitable area found.\n");
536 return; 570 return;
537 } 571 }
572
538 } else { 573 } else {
539 unsigned long long start; 574 unsigned long long start;
540 575
@@ -556,6 +591,9 @@ static void __init reserve_crashkernel(void)
556 crashk_res.start = crash_base; 591 crashk_res.start = crash_base;
557 crashk_res.end = crash_base + crash_size - 1; 592 crashk_res.end = crash_base + crash_size - 1;
558 insert_resource(&iomem_resource, &crashk_res); 593 insert_resource(&iomem_resource, &crashk_res);
594
595 if (crash_base >= (1ULL<<32))
596 reserve_crashkernel_low();
559} 597}
560#else 598#else
561static void __init reserve_crashkernel(void) 599static void __init reserve_crashkernel(void)
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index d0b8458a703a..d2e6927bbaae 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -191,6 +191,7 @@ extern struct kimage *kexec_crash_image;
191/* Location of a reserved region to hold the crash kernel. 191/* Location of a reserved region to hold the crash kernel.
192 */ 192 */
193extern struct resource crashk_res; 193extern struct resource crashk_res;
194extern struct resource crashk_low_res;
194typedef u32 note_buf_t[KEXEC_NOTE_BYTES/4]; 195typedef u32 note_buf_t[KEXEC_NOTE_BYTES/4];
195extern note_buf_t __percpu *crash_notes; 196extern note_buf_t __percpu *crash_notes;
196extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4]; 197extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
@@ -199,6 +200,8 @@ extern size_t vmcoreinfo_max_size;
199 200
200int __init parse_crashkernel(char *cmdline, unsigned long long system_ram, 201int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,
201 unsigned long long *crash_size, unsigned long long *crash_base); 202 unsigned long long *crash_size, unsigned long long *crash_base);
203int parse_crashkernel_low(char *cmdline, unsigned long long system_ram,
204 unsigned long long *crash_size, unsigned long long *crash_base);
202int crash_shrink_memory(unsigned long new_size); 205int crash_shrink_memory(unsigned long new_size);
203size_t crash_get_memory_size(void); 206size_t crash_get_memory_size(void);
204void crash_free_reserved_phys_range(unsigned long begin, unsigned long end); 207void crash_free_reserved_phys_range(unsigned long begin, unsigned long end);
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 5e4bd7864c5d..2436ffcec91f 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -54,6 +54,12 @@ struct resource crashk_res = {
54 .end = 0, 54 .end = 0,
55 .flags = IORESOURCE_BUSY | IORESOURCE_MEM 55 .flags = IORESOURCE_BUSY | IORESOURCE_MEM
56}; 56};
57struct resource crashk_low_res = {
58 .name = "Crash kernel low",
59 .start = 0,
60 .end = 0,
61 .flags = IORESOURCE_BUSY | IORESOURCE_MEM
62};
57 63
58int kexec_should_crash(struct task_struct *p) 64int kexec_should_crash(struct task_struct *p)
59{ 65{
@@ -1369,10 +1375,11 @@ static int __init parse_crashkernel_simple(char *cmdline,
1369 * That function is the entry point for command line parsing and should be 1375 * That function is the entry point for command line parsing and should be
1370 * called from the arch-specific code. 1376 * called from the arch-specific code.
1371 */ 1377 */
1372int __init parse_crashkernel(char *cmdline, 1378static int __init __parse_crashkernel(char *cmdline,
1373 unsigned long long system_ram, 1379 unsigned long long system_ram,
1374 unsigned long long *crash_size, 1380 unsigned long long *crash_size,
1375 unsigned long long *crash_base) 1381 unsigned long long *crash_base,
1382 const char *name)
1376{ 1383{
1377 char *p = cmdline, *ck_cmdline = NULL; 1384 char *p = cmdline, *ck_cmdline = NULL;
1378 char *first_colon, *first_space; 1385 char *first_colon, *first_space;
@@ -1382,16 +1389,16 @@ int __init parse_crashkernel(char *cmdline,
1382 *crash_base = 0; 1389 *crash_base = 0;
1383 1390
1384 /* find crashkernel and use the last one if there are more */ 1391 /* find crashkernel and use the last one if there are more */
1385 p = strstr(p, "crashkernel="); 1392 p = strstr(p, name);
1386 while (p) { 1393 while (p) {
1387 ck_cmdline = p; 1394 ck_cmdline = p;
1388 p = strstr(p+1, "crashkernel="); 1395 p = strstr(p+1, name);
1389 } 1396 }
1390 1397
1391 if (!ck_cmdline) 1398 if (!ck_cmdline)
1392 return -EINVAL; 1399 return -EINVAL;
1393 1400
1394 ck_cmdline += 12; /* strlen("crashkernel=") */ 1401 ck_cmdline += strlen(name);
1395 1402
1396 /* 1403 /*
1397 * if the commandline contains a ':', then that's the extended 1404 * if the commandline contains a ':', then that's the extended
@@ -1409,6 +1416,23 @@ int __init parse_crashkernel(char *cmdline,
1409 return 0; 1416 return 0;
1410} 1417}
1411 1418
1419int __init parse_crashkernel(char *cmdline,
1420 unsigned long long system_ram,
1421 unsigned long long *crash_size,
1422 unsigned long long *crash_base)
1423{
1424 return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
1425 "crashkernel=");
1426}
1427
1428int __init parse_crashkernel_low(char *cmdline,
1429 unsigned long long system_ram,
1430 unsigned long long *crash_size,
1431 unsigned long long *crash_base)
1432{
1433 return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
1434 "crashkernel_low=");
1435}
1412 1436
1413static void update_vmcoreinfo_note(void) 1437static void update_vmcoreinfo_note(void)
1414{ 1438{