aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt10
-rw-r--r--arch/x86/kernel/setup.c6
-rw-r--r--kernel/kexec.c109
3 files changed, 104 insertions, 21 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 709eb3edc6b2..a1ac1f1d6d34 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -603,16 +603,16 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
603 a memory unit (amount[KMG]). See also 603 a memory unit (amount[KMG]). See also
604 Documentation/kdump/kdump.txt for an example. 604 Documentation/kdump/kdump.txt for an example.
605 605
606 crashkernel_high=size[KMG] 606 crashkernel=size[KMG],high
607 [KNL, x86_64] range could be above 4G. Allow kernel 607 [KNL, x86_64] range could be above 4G. Allow kernel
608 to allocate physical memory region from top, so could 608 to allocate physical memory region from top, so could
609 be above 4G if system have more than 4G ram installed. 609 be above 4G if system have more than 4G ram installed.
610 Otherwise memory region will be allocated below 4G, if 610 Otherwise memory region will be allocated below 4G, if
611 available. 611 available.
612 It will be ignored if crashkernel=X is specified. 612 It will be ignored if crashkernel=X is specified.
613 crashkernel_low=size[KMG] 613 crashkernel=size[KMG],low
614 [KNL, x86_64] range under 4G. When crashkernel_high= is 614 [KNL, x86_64] range under 4G. When crashkernel=X,high
615 passed, kernel could allocate physical memory region 615 is passed, kernel could allocate physical memory region
616 above 4G, that cause second kernel crash on system 616 above 4G, that cause second kernel crash on system
617 that require some amount of low memory, e.g. swiotlb 617 that require some amount of low memory, e.g. swiotlb
618 requires at least 64M+32K low memory. Kernel would 618 requires at least 64M+32K low memory. Kernel would
@@ -620,7 +620,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
620 This one let user to specify own low range under 4G 620 This one let user to specify own low range under 4G
621 for second kernel instead. 621 for second kernel instead.
622 0: to disable low allocation. 622 0: to disable low allocation.
623 It will be ignored when crashkernel_high=X is not used 623 It will be ignored when crashkernel=X,high is not used
624 or memory reserved is below 4G. 624 or memory reserved is below 4G.
625 625
626 cs89x0_dma= [HW,NET] 626 cs89x0_dma= [HW,NET]
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index a85a144f2052..fae9134a2de9 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -528,7 +528,7 @@ static void __init reserve_crashkernel_low(void)
528 int ret; 528 int ret;
529 529
530 total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT)); 530 total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT));
531 /* crashkernel_low=YM */ 531 /* crashkernel=Y,low */
532 ret = parse_crashkernel_low(boot_command_line, total_low_mem, 532 ret = parse_crashkernel_low(boot_command_line, total_low_mem,
533 &low_size, &base); 533 &low_size, &base);
534 if (ret != 0) { 534 if (ret != 0) {
@@ -542,7 +542,7 @@ static void __init reserve_crashkernel_low(void)
542 low_size = swiotlb_size_or_default() + (8UL<<20); 542 low_size = swiotlb_size_or_default() + (8UL<<20);
543 auto_set = true; 543 auto_set = true;
544 } else { 544 } else {
545 /* passed with crashkernel_low=0 ? */ 545 /* passed with crashkernel=0,low ? */
546 if (!low_size) 546 if (!low_size)
547 return; 547 return;
548 } 548 }
@@ -582,7 +582,7 @@ static void __init reserve_crashkernel(void)
582 ret = parse_crashkernel(boot_command_line, total_mem, 582 ret = parse_crashkernel(boot_command_line, total_mem,
583 &crash_size, &crash_base); 583 &crash_size, &crash_base);
584 if (ret != 0 || crash_size <= 0) { 584 if (ret != 0 || crash_size <= 0) {
585 /* crashkernel_high=XM */ 585 /* crashkernel=X,high */
586 ret = parse_crashkernel_high(boot_command_line, total_mem, 586 ret = parse_crashkernel_high(boot_command_line, total_mem,
587 &crash_size, &crash_base); 587 &crash_size, &crash_base);
588 if (ret != 0 || crash_size <= 0) 588 if (ret != 0 || crash_size <= 0)
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 1b2f73f5f9b9..401fdb041f35 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1368,35 +1368,114 @@ static int __init parse_crashkernel_simple(char *cmdline,
1368 return 0; 1368 return 0;
1369} 1369}
1370 1370
1371#define SUFFIX_HIGH 0
1372#define SUFFIX_LOW 1
1373#define SUFFIX_NULL 2
1374static __initdata char *suffix_tbl[] = {
1375 [SUFFIX_HIGH] = ",high",
1376 [SUFFIX_LOW] = ",low",
1377 [SUFFIX_NULL] = NULL,
1378};
1379
1371/* 1380/*
1372 * That function is the entry point for command line parsing and should be 1381 * That function parses "suffix" crashkernel command lines like
1373 * called from the arch-specific code. 1382 *
1383 * crashkernel=size,[high|low]
1384 *
1385 * It returns 0 on success and -EINVAL on failure.
1374 */ 1386 */
1387static int __init parse_crashkernel_suffix(char *cmdline,
1388 unsigned long long *crash_size,
1389 unsigned long long *crash_base,
1390 const char *suffix)
1391{
1392 char *cur = cmdline;
1393
1394 *crash_size = memparse(cmdline, &cur);
1395 if (cmdline == cur) {
1396 pr_warn("crashkernel: memory value expected\n");
1397 return -EINVAL;
1398 }
1399
1400 /* check with suffix */
1401 if (strncmp(cur, suffix, strlen(suffix))) {
1402 pr_warn("crashkernel: unrecognized char\n");
1403 return -EINVAL;
1404 }
1405 cur += strlen(suffix);
1406 if (*cur != ' ' && *cur != '\0') {
1407 pr_warn("crashkernel: unrecognized char\n");
1408 return -EINVAL;
1409 }
1410
1411 return 0;
1412}
1413
1414static __init char *get_last_crashkernel(char *cmdline,
1415 const char *name,
1416 const char *suffix)
1417{
1418 char *p = cmdline, *ck_cmdline = NULL;
1419
1420 /* find crashkernel and use the last one if there are more */
1421 p = strstr(p, name);
1422 while (p) {
1423 char *end_p = strchr(p, ' ');
1424 char *q;
1425
1426 if (!end_p)
1427 end_p = p + strlen(p);
1428
1429 if (!suffix) {
1430 int i;
1431
1432 /* skip the one with any known suffix */
1433 for (i = 0; suffix_tbl[i]; i++) {
1434 q = end_p - strlen(suffix_tbl[i]);
1435 if (!strncmp(q, suffix_tbl[i],
1436 strlen(suffix_tbl[i])))
1437 goto next;
1438 }
1439 ck_cmdline = p;
1440 } else {
1441 q = end_p - strlen(suffix);
1442 if (!strncmp(q, suffix, strlen(suffix)))
1443 ck_cmdline = p;
1444 }
1445next:
1446 p = strstr(p+1, name);
1447 }
1448
1449 if (!ck_cmdline)
1450 return NULL;
1451
1452 return ck_cmdline;
1453}
1454
1375static int __init __parse_crashkernel(char *cmdline, 1455static int __init __parse_crashkernel(char *cmdline,
1376 unsigned long long system_ram, 1456 unsigned long long system_ram,
1377 unsigned long long *crash_size, 1457 unsigned long long *crash_size,
1378 unsigned long long *crash_base, 1458 unsigned long long *crash_base,
1379 const char *name) 1459 const char *name,
1460 const char *suffix)
1380{ 1461{
1381 char *p = cmdline, *ck_cmdline = NULL;
1382 char *first_colon, *first_space; 1462 char *first_colon, *first_space;
1463 char *ck_cmdline;
1383 1464
1384 BUG_ON(!crash_size || !crash_base); 1465 BUG_ON(!crash_size || !crash_base);
1385 *crash_size = 0; 1466 *crash_size = 0;
1386 *crash_base = 0; 1467 *crash_base = 0;
1387 1468
1388 /* find crashkernel and use the last one if there are more */ 1469 ck_cmdline = get_last_crashkernel(cmdline, name, suffix);
1389 p = strstr(p, name);
1390 while (p) {
1391 ck_cmdline = p;
1392 p = strstr(p+1, name);
1393 }
1394 1470
1395 if (!ck_cmdline) 1471 if (!ck_cmdline)
1396 return -EINVAL; 1472 return -EINVAL;
1397 1473
1398 ck_cmdline += strlen(name); 1474 ck_cmdline += strlen(name);
1399 1475
1476 if (suffix)
1477 return parse_crashkernel_suffix(ck_cmdline, crash_size,
1478 crash_base, suffix);
1400 /* 1479 /*
1401 * if the commandline contains a ':', then that's the extended 1480 * if the commandline contains a ':', then that's the extended
1402 * syntax -- if not, it must be the classic syntax 1481 * syntax -- if not, it must be the classic syntax
@@ -1413,13 +1492,17 @@ static int __init __parse_crashkernel(char *cmdline,
1413 return 0; 1492 return 0;
1414} 1493}
1415 1494
1495/*
1496 * That function is the entry point for command line parsing and should be
1497 * called from the arch-specific code.
1498 */
1416int __init parse_crashkernel(char *cmdline, 1499int __init parse_crashkernel(char *cmdline,
1417 unsigned long long system_ram, 1500 unsigned long long system_ram,
1418 unsigned long long *crash_size, 1501 unsigned long long *crash_size,
1419 unsigned long long *crash_base) 1502 unsigned long long *crash_base)
1420{ 1503{
1421 return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base, 1504 return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
1422 "crashkernel="); 1505 "crashkernel=", NULL);
1423} 1506}
1424 1507
1425int __init parse_crashkernel_high(char *cmdline, 1508int __init parse_crashkernel_high(char *cmdline,
@@ -1428,7 +1511,7 @@ int __init parse_crashkernel_high(char *cmdline,
1428 unsigned long long *crash_base) 1511 unsigned long long *crash_base)
1429{ 1512{
1430 return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base, 1513 return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
1431 "crashkernel_high="); 1514 "crashkernel=", suffix_tbl[SUFFIX_HIGH]);
1432} 1515}
1433 1516
1434int __init parse_crashkernel_low(char *cmdline, 1517int __init parse_crashkernel_low(char *cmdline,
@@ -1437,7 +1520,7 @@ int __init parse_crashkernel_low(char *cmdline,
1437 unsigned long long *crash_base) 1520 unsigned long long *crash_base)
1438{ 1521{
1439 return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base, 1522 return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
1440 "crashkernel_low="); 1523 "crashkernel=", suffix_tbl[SUFFIX_LOW]);
1441} 1524}
1442 1525
1443static void update_vmcoreinfo_note(void) 1526static void update_vmcoreinfo_note(void)