aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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{