aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kexec.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/kexec.c')
-rw-r--r--kernel/kexec.c161
1 files changed, 121 insertions, 40 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c
index bddd3d7a74b6..59f7b55ba745 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -55,7 +55,7 @@ struct resource crashk_res = {
55 .flags = IORESOURCE_BUSY | IORESOURCE_MEM 55 .flags = IORESOURCE_BUSY | IORESOURCE_MEM
56}; 56};
57struct resource crashk_low_res = { 57struct resource crashk_low_res = {
58 .name = "Crash kernel low", 58 .name = "Crash kernel",
59 .start = 0, 59 .start = 0,
60 .end = 0, 60 .end = 0,
61 .flags = IORESOURCE_BUSY | IORESOURCE_MEM 61 .flags = IORESOURCE_BUSY | IORESOURCE_MEM
@@ -786,7 +786,7 @@ static int kimage_load_normal_segment(struct kimage *image,
786 struct kexec_segment *segment) 786 struct kexec_segment *segment)
787{ 787{
788 unsigned long maddr; 788 unsigned long maddr;
789 unsigned long ubytes, mbytes; 789 size_t ubytes, mbytes;
790 int result; 790 int result;
791 unsigned char __user *buf; 791 unsigned char __user *buf;
792 792
@@ -819,13 +819,9 @@ static int kimage_load_normal_segment(struct kimage *image,
819 /* Start with a clear page */ 819 /* Start with a clear page */
820 clear_page(ptr); 820 clear_page(ptr);
821 ptr += maddr & ~PAGE_MASK; 821 ptr += maddr & ~PAGE_MASK;
822 mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK); 822 mchunk = min_t(size_t, mbytes,
823 if (mchunk > mbytes) 823 PAGE_SIZE - (maddr & ~PAGE_MASK));
824 mchunk = mbytes; 824 uchunk = min(ubytes, mchunk);
825
826 uchunk = mchunk;
827 if (uchunk > ubytes)
828 uchunk = ubytes;
829 825
830 result = copy_from_user(ptr, buf, uchunk); 826 result = copy_from_user(ptr, buf, uchunk);
831 kunmap(page); 827 kunmap(page);
@@ -850,7 +846,7 @@ static int kimage_load_crash_segment(struct kimage *image,
850 * We do things a page at a time for the sake of kmap. 846 * We do things a page at a time for the sake of kmap.
851 */ 847 */
852 unsigned long maddr; 848 unsigned long maddr;
853 unsigned long ubytes, mbytes; 849 size_t ubytes, mbytes;
854 int result; 850 int result;
855 unsigned char __user *buf; 851 unsigned char __user *buf;
856 852
@@ -871,13 +867,10 @@ static int kimage_load_crash_segment(struct kimage *image,
871 } 867 }
872 ptr = kmap(page); 868 ptr = kmap(page);
873 ptr += maddr & ~PAGE_MASK; 869 ptr += maddr & ~PAGE_MASK;
874 mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK); 870 mchunk = min_t(size_t, mbytes,
875 if (mchunk > mbytes) 871 PAGE_SIZE - (maddr & ~PAGE_MASK));
876 mchunk = mbytes; 872 uchunk = min(ubytes, mchunk);
877 873 if (mchunk > uchunk) {
878 uchunk = mchunk;
879 if (uchunk > ubytes) {
880 uchunk = ubytes;
881 /* Zero the trailing part of the page */ 874 /* Zero the trailing part of the page */
882 memset(ptr + uchunk, 0, mchunk - uchunk); 875 memset(ptr + uchunk, 0, mchunk - uchunk);
883 } 876 }
@@ -1118,12 +1111,8 @@ void __weak crash_free_reserved_phys_range(unsigned long begin,
1118{ 1111{
1119 unsigned long addr; 1112 unsigned long addr;
1120 1113
1121 for (addr = begin; addr < end; addr += PAGE_SIZE) { 1114 for (addr = begin; addr < end; addr += PAGE_SIZE)
1122 ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT)); 1115 free_reserved_page(pfn_to_page(addr >> PAGE_SHIFT));
1123 init_page_count(pfn_to_page(addr >> PAGE_SHIFT));
1124 free_page((unsigned long)__va(addr));
1125 totalram_pages++;
1126 }
1127} 1116}
1128 1117
1129int crash_shrink_memory(unsigned long new_size) 1118int crash_shrink_memory(unsigned long new_size)
@@ -1368,35 +1357,114 @@ static int __init parse_crashkernel_simple(char *cmdline,
1368 return 0; 1357 return 0;
1369} 1358}
1370 1359
1360#define SUFFIX_HIGH 0
1361#define SUFFIX_LOW 1
1362#define SUFFIX_NULL 2
1363static __initdata char *suffix_tbl[] = {
1364 [SUFFIX_HIGH] = ",high",
1365 [SUFFIX_LOW] = ",low",
1366 [SUFFIX_NULL] = NULL,
1367};
1368
1371/* 1369/*
1372 * That function is the entry point for command line parsing and should be 1370 * That function parses "suffix" crashkernel command lines like
1373 * called from the arch-specific code. 1371 *
1372 * crashkernel=size,[high|low]
1373 *
1374 * It returns 0 on success and -EINVAL on failure.
1374 */ 1375 */
1376static int __init parse_crashkernel_suffix(char *cmdline,
1377 unsigned long long *crash_size,
1378 unsigned long long *crash_base,
1379 const char *suffix)
1380{
1381 char *cur = cmdline;
1382
1383 *crash_size = memparse(cmdline, &cur);
1384 if (cmdline == cur) {
1385 pr_warn("crashkernel: memory value expected\n");
1386 return -EINVAL;
1387 }
1388
1389 /* check with suffix */
1390 if (strncmp(cur, suffix, strlen(suffix))) {
1391 pr_warn("crashkernel: unrecognized char\n");
1392 return -EINVAL;
1393 }
1394 cur += strlen(suffix);
1395 if (*cur != ' ' && *cur != '\0') {
1396 pr_warn("crashkernel: unrecognized char\n");
1397 return -EINVAL;
1398 }
1399
1400 return 0;
1401}
1402
1403static __init char *get_last_crashkernel(char *cmdline,
1404 const char *name,
1405 const char *suffix)
1406{
1407 char *p = cmdline, *ck_cmdline = NULL;
1408
1409 /* find crashkernel and use the last one if there are more */
1410 p = strstr(p, name);
1411 while (p) {
1412 char *end_p = strchr(p, ' ');
1413 char *q;
1414
1415 if (!end_p)
1416 end_p = p + strlen(p);
1417
1418 if (!suffix) {
1419 int i;
1420
1421 /* skip the one with any known suffix */
1422 for (i = 0; suffix_tbl[i]; i++) {
1423 q = end_p - strlen(suffix_tbl[i]);
1424 if (!strncmp(q, suffix_tbl[i],
1425 strlen(suffix_tbl[i])))
1426 goto next;
1427 }
1428 ck_cmdline = p;
1429 } else {
1430 q = end_p - strlen(suffix);
1431 if (!strncmp(q, suffix, strlen(suffix)))
1432 ck_cmdline = p;
1433 }
1434next:
1435 p = strstr(p+1, name);
1436 }
1437
1438 if (!ck_cmdline)
1439 return NULL;
1440
1441 return ck_cmdline;
1442}
1443
1375static int __init __parse_crashkernel(char *cmdline, 1444static int __init __parse_crashkernel(char *cmdline,
1376 unsigned long long system_ram, 1445 unsigned long long system_ram,
1377 unsigned long long *crash_size, 1446 unsigned long long *crash_size,
1378 unsigned long long *crash_base, 1447 unsigned long long *crash_base,
1379 const char *name) 1448 const char *name,
1449 const char *suffix)
1380{ 1450{
1381 char *p = cmdline, *ck_cmdline = NULL;
1382 char *first_colon, *first_space; 1451 char *first_colon, *first_space;
1452 char *ck_cmdline;
1383 1453
1384 BUG_ON(!crash_size || !crash_base); 1454 BUG_ON(!crash_size || !crash_base);
1385 *crash_size = 0; 1455 *crash_size = 0;
1386 *crash_base = 0; 1456 *crash_base = 0;
1387 1457
1388 /* find crashkernel and use the last one if there are more */ 1458 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 1459
1395 if (!ck_cmdline) 1460 if (!ck_cmdline)
1396 return -EINVAL; 1461 return -EINVAL;
1397 1462
1398 ck_cmdline += strlen(name); 1463 ck_cmdline += strlen(name);
1399 1464
1465 if (suffix)
1466 return parse_crashkernel_suffix(ck_cmdline, crash_size,
1467 crash_base, suffix);
1400 /* 1468 /*
1401 * if the commandline contains a ':', then that's the extended 1469 * if the commandline contains a ':', then that's the extended
1402 * syntax -- if not, it must be the classic syntax 1470 * syntax -- if not, it must be the classic syntax
@@ -1413,13 +1481,26 @@ static int __init __parse_crashkernel(char *cmdline,
1413 return 0; 1481 return 0;
1414} 1482}
1415 1483
1484/*
1485 * That function is the entry point for command line parsing and should be
1486 * called from the arch-specific code.
1487 */
1416int __init parse_crashkernel(char *cmdline, 1488int __init parse_crashkernel(char *cmdline,
1417 unsigned long long system_ram, 1489 unsigned long long system_ram,
1418 unsigned long long *crash_size, 1490 unsigned long long *crash_size,
1419 unsigned long long *crash_base) 1491 unsigned long long *crash_base)
1420{ 1492{
1421 return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base, 1493 return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
1422 "crashkernel="); 1494 "crashkernel=", NULL);
1495}
1496
1497int __init parse_crashkernel_high(char *cmdline,
1498 unsigned long long system_ram,
1499 unsigned long long *crash_size,
1500 unsigned long long *crash_base)
1501{
1502 return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
1503 "crashkernel=", suffix_tbl[SUFFIX_HIGH]);
1423} 1504}
1424 1505
1425int __init parse_crashkernel_low(char *cmdline, 1506int __init parse_crashkernel_low(char *cmdline,
@@ -1428,7 +1509,7 @@ int __init parse_crashkernel_low(char *cmdline,
1428 unsigned long long *crash_base) 1509 unsigned long long *crash_base)
1429{ 1510{
1430 return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base, 1511 return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
1431 "crashkernel_low="); 1512 "crashkernel=", suffix_tbl[SUFFIX_LOW]);
1432} 1513}
1433 1514
1434static void update_vmcoreinfo_note(void) 1515static void update_vmcoreinfo_note(void)
@@ -1452,14 +1533,13 @@ void vmcoreinfo_append_str(const char *fmt, ...)
1452{ 1533{
1453 va_list args; 1534 va_list args;
1454 char buf[0x50]; 1535 char buf[0x50];
1455 int r; 1536 size_t r;
1456 1537
1457 va_start(args, fmt); 1538 va_start(args, fmt);
1458 r = vsnprintf(buf, sizeof(buf), fmt, args); 1539 r = vsnprintf(buf, sizeof(buf), fmt, args);
1459 va_end(args); 1540 va_end(args);
1460 1541
1461 if (r + vmcoreinfo_size > vmcoreinfo_max_size) 1542 r = min(r, vmcoreinfo_max_size - vmcoreinfo_size);
1462 r = vmcoreinfo_max_size - vmcoreinfo_size;
1463 1543
1464 memcpy(&vmcoreinfo_data[vmcoreinfo_size], buf, r); 1544 memcpy(&vmcoreinfo_data[vmcoreinfo_size], buf, r);
1465 1545
@@ -1489,7 +1569,7 @@ static int __init crash_save_vmcoreinfo_init(void)
1489 VMCOREINFO_SYMBOL(swapper_pg_dir); 1569 VMCOREINFO_SYMBOL(swapper_pg_dir);
1490#endif 1570#endif
1491 VMCOREINFO_SYMBOL(_stext); 1571 VMCOREINFO_SYMBOL(_stext);
1492 VMCOREINFO_SYMBOL(vmlist); 1572 VMCOREINFO_SYMBOL(vmap_area_list);
1493 1573
1494#ifndef CONFIG_NEED_MULTIPLE_NODES 1574#ifndef CONFIG_NEED_MULTIPLE_NODES
1495 VMCOREINFO_SYMBOL(mem_map); 1575 VMCOREINFO_SYMBOL(mem_map);
@@ -1527,7 +1607,8 @@ static int __init crash_save_vmcoreinfo_init(void)
1527 VMCOREINFO_OFFSET(free_area, free_list); 1607 VMCOREINFO_OFFSET(free_area, free_list);
1528 VMCOREINFO_OFFSET(list_head, next); 1608 VMCOREINFO_OFFSET(list_head, next);
1529 VMCOREINFO_OFFSET(list_head, prev); 1609 VMCOREINFO_OFFSET(list_head, prev);
1530 VMCOREINFO_OFFSET(vm_struct, addr); 1610 VMCOREINFO_OFFSET(vmap_area, va_start);
1611 VMCOREINFO_OFFSET(vmap_area, list);
1531 VMCOREINFO_LENGTH(zone.free_area, MAX_ORDER); 1612 VMCOREINFO_LENGTH(zone.free_area, MAX_ORDER);
1532 log_buf_kexec_setup(); 1613 log_buf_kexec_setup();
1533 VMCOREINFO_LENGTH(free_area.free_list, MIGRATE_TYPES); 1614 VMCOREINFO_LENGTH(free_area.free_list, MIGRATE_TYPES);