diff options
Diffstat (limited to 'kernel/kexec.c')
-rw-r--r-- | kernel/kexec.c | 70 |
1 files changed, 49 insertions, 21 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c index 296fbc84d659..7b0886786701 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/console.h> | 32 | #include <linux/console.h> |
33 | #include <linux/vmalloc.h> | 33 | #include <linux/vmalloc.h> |
34 | #include <linux/swap.h> | 34 | #include <linux/swap.h> |
35 | #include <linux/kmsg_dump.h> | ||
36 | #include <linux/syscore_ops.h> | 35 | #include <linux/syscore_ops.h> |
37 | 36 | ||
38 | #include <asm/page.h> | 37 | #include <asm/page.h> |
@@ -498,7 +497,7 @@ static struct page *kimage_alloc_crash_control_pages(struct kimage *image, | |||
498 | while (hole_end <= crashk_res.end) { | 497 | while (hole_end <= crashk_res.end) { |
499 | unsigned long i; | 498 | unsigned long i; |
500 | 499 | ||
501 | if (hole_end > KEXEC_CONTROL_MEMORY_LIMIT) | 500 | if (hole_end > KEXEC_CRASH_CONTROL_MEMORY_LIMIT) |
502 | break; | 501 | break; |
503 | if (hole_end > crashk_res.end) | 502 | if (hole_end > crashk_res.end) |
504 | break; | 503 | break; |
@@ -999,6 +998,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, | |||
999 | kimage_free(xchg(&kexec_crash_image, NULL)); | 998 | kimage_free(xchg(&kexec_crash_image, NULL)); |
1000 | result = kimage_crash_alloc(&image, entry, | 999 | result = kimage_crash_alloc(&image, entry, |
1001 | nr_segments, segments); | 1000 | nr_segments, segments); |
1001 | crash_map_reserved_pages(); | ||
1002 | } | 1002 | } |
1003 | if (result) | 1003 | if (result) |
1004 | goto out; | 1004 | goto out; |
@@ -1015,6 +1015,8 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, | |||
1015 | goto out; | 1015 | goto out; |
1016 | } | 1016 | } |
1017 | kimage_terminate(image); | 1017 | kimage_terminate(image); |
1018 | if (flags & KEXEC_ON_CRASH) | ||
1019 | crash_unmap_reserved_pages(); | ||
1018 | } | 1020 | } |
1019 | /* Install the new kernel, and Uninstall the old */ | 1021 | /* Install the new kernel, and Uninstall the old */ |
1020 | image = xchg(dest_image, image); | 1022 | image = xchg(dest_image, image); |
@@ -1026,6 +1028,18 @@ out: | |||
1026 | return result; | 1028 | return result; |
1027 | } | 1029 | } |
1028 | 1030 | ||
1031 | /* | ||
1032 | * Add and remove page tables for crashkernel memory | ||
1033 | * | ||
1034 | * Provide an empty default implementation here -- architecture | ||
1035 | * code may override this | ||
1036 | */ | ||
1037 | void __weak crash_map_reserved_pages(void) | ||
1038 | {} | ||
1039 | |||
1040 | void __weak crash_unmap_reserved_pages(void) | ||
1041 | {} | ||
1042 | |||
1029 | #ifdef CONFIG_COMPAT | 1043 | #ifdef CONFIG_COMPAT |
1030 | asmlinkage long compat_sys_kexec_load(unsigned long entry, | 1044 | asmlinkage long compat_sys_kexec_load(unsigned long entry, |
1031 | unsigned long nr_segments, | 1045 | unsigned long nr_segments, |
@@ -1079,8 +1093,6 @@ void crash_kexec(struct pt_regs *regs) | |||
1079 | if (kexec_crash_image) { | 1093 | if (kexec_crash_image) { |
1080 | struct pt_regs fixed_regs; | 1094 | struct pt_regs fixed_regs; |
1081 | 1095 | ||
1082 | kmsg_dump(KMSG_DUMP_KEXEC); | ||
1083 | |||
1084 | crash_setup_regs(&fixed_regs, regs); | 1096 | crash_setup_regs(&fixed_regs, regs); |
1085 | crash_save_vmcoreinfo(); | 1097 | crash_save_vmcoreinfo(); |
1086 | machine_crash_shutdown(&fixed_regs); | 1098 | machine_crash_shutdown(&fixed_regs); |
@@ -1117,6 +1129,8 @@ int crash_shrink_memory(unsigned long new_size) | |||
1117 | { | 1129 | { |
1118 | int ret = 0; | 1130 | int ret = 0; |
1119 | unsigned long start, end; | 1131 | unsigned long start, end; |
1132 | unsigned long old_size; | ||
1133 | struct resource *ram_res; | ||
1120 | 1134 | ||
1121 | mutex_lock(&kexec_mutex); | 1135 | mutex_lock(&kexec_mutex); |
1122 | 1136 | ||
@@ -1126,23 +1140,37 @@ int crash_shrink_memory(unsigned long new_size) | |||
1126 | } | 1140 | } |
1127 | start = crashk_res.start; | 1141 | start = crashk_res.start; |
1128 | end = crashk_res.end; | 1142 | end = crashk_res.end; |
1143 | old_size = (end == 0) ? 0 : end - start + 1; | ||
1144 | if (new_size >= old_size) { | ||
1145 | ret = (new_size == old_size) ? 0 : -EINVAL; | ||
1146 | goto unlock; | ||
1147 | } | ||
1129 | 1148 | ||
1130 | if (new_size >= end - start + 1) { | 1149 | ram_res = kzalloc(sizeof(*ram_res), GFP_KERNEL); |
1131 | ret = -EINVAL; | 1150 | if (!ram_res) { |
1132 | if (new_size == end - start + 1) | 1151 | ret = -ENOMEM; |
1133 | ret = 0; | ||
1134 | goto unlock; | 1152 | goto unlock; |
1135 | } | 1153 | } |
1136 | 1154 | ||
1137 | start = roundup(start, PAGE_SIZE); | 1155 | start = roundup(start, KEXEC_CRASH_MEM_ALIGN); |
1138 | end = roundup(start + new_size, PAGE_SIZE); | 1156 | end = roundup(start + new_size, KEXEC_CRASH_MEM_ALIGN); |
1139 | 1157 | ||
1158 | crash_map_reserved_pages(); | ||
1140 | crash_free_reserved_phys_range(end, crashk_res.end); | 1159 | crash_free_reserved_phys_range(end, crashk_res.end); |
1141 | 1160 | ||
1142 | if ((start == end) && (crashk_res.parent != NULL)) | 1161 | if ((start == end) && (crashk_res.parent != NULL)) |
1143 | release_resource(&crashk_res); | 1162 | release_resource(&crashk_res); |
1163 | |||
1164 | ram_res->start = end; | ||
1165 | ram_res->end = crashk_res.end; | ||
1166 | ram_res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; | ||
1167 | ram_res->name = "System RAM"; | ||
1168 | |||
1144 | crashk_res.end = end - 1; | 1169 | crashk_res.end = end - 1; |
1145 | 1170 | ||
1171 | insert_resource(&iomem_resource, ram_res); | ||
1172 | crash_unmap_reserved_pages(); | ||
1173 | |||
1146 | unlock: | 1174 | unlock: |
1147 | mutex_unlock(&kexec_mutex); | 1175 | mutex_unlock(&kexec_mutex); |
1148 | return ret; | 1176 | return ret; |
@@ -1380,24 +1408,23 @@ int __init parse_crashkernel(char *cmdline, | |||
1380 | } | 1408 | } |
1381 | 1409 | ||
1382 | 1410 | ||
1383 | 1411 | static void update_vmcoreinfo_note(void) | |
1384 | void crash_save_vmcoreinfo(void) | ||
1385 | { | 1412 | { |
1386 | u32 *buf; | 1413 | u32 *buf = vmcoreinfo_note; |
1387 | 1414 | ||
1388 | if (!vmcoreinfo_size) | 1415 | if (!vmcoreinfo_size) |
1389 | return; | 1416 | return; |
1390 | |||
1391 | vmcoreinfo_append_str("CRASHTIME=%ld", get_seconds()); | ||
1392 | |||
1393 | buf = (u32 *)vmcoreinfo_note; | ||
1394 | |||
1395 | buf = append_elf_note(buf, VMCOREINFO_NOTE_NAME, 0, vmcoreinfo_data, | 1417 | buf = append_elf_note(buf, VMCOREINFO_NOTE_NAME, 0, vmcoreinfo_data, |
1396 | vmcoreinfo_size); | 1418 | vmcoreinfo_size); |
1397 | |||
1398 | final_note(buf); | 1419 | final_note(buf); |
1399 | } | 1420 | } |
1400 | 1421 | ||
1422 | void crash_save_vmcoreinfo(void) | ||
1423 | { | ||
1424 | vmcoreinfo_append_str("CRASHTIME=%ld", get_seconds()); | ||
1425 | update_vmcoreinfo_note(); | ||
1426 | } | ||
1427 | |||
1401 | void vmcoreinfo_append_str(const char *fmt, ...) | 1428 | void vmcoreinfo_append_str(const char *fmt, ...) |
1402 | { | 1429 | { |
1403 | va_list args; | 1430 | va_list args; |
@@ -1483,6 +1510,7 @@ static int __init crash_save_vmcoreinfo_init(void) | |||
1483 | VMCOREINFO_NUMBER(PG_swapcache); | 1510 | VMCOREINFO_NUMBER(PG_swapcache); |
1484 | 1511 | ||
1485 | arch_crash_save_vmcoreinfo(); | 1512 | arch_crash_save_vmcoreinfo(); |
1513 | update_vmcoreinfo_note(); | ||
1486 | 1514 | ||
1487 | return 0; | 1515 | return 0; |
1488 | } | 1516 | } |
@@ -1506,7 +1534,7 @@ int kernel_kexec(void) | |||
1506 | 1534 | ||
1507 | #ifdef CONFIG_KEXEC_JUMP | 1535 | #ifdef CONFIG_KEXEC_JUMP |
1508 | if (kexec_image->preserve_context) { | 1536 | if (kexec_image->preserve_context) { |
1509 | mutex_lock(&pm_mutex); | 1537 | lock_system_sleep(); |
1510 | pm_prepare_console(); | 1538 | pm_prepare_console(); |
1511 | error = freeze_processes(); | 1539 | error = freeze_processes(); |
1512 | if (error) { | 1540 | if (error) { |
@@ -1559,7 +1587,7 @@ int kernel_kexec(void) | |||
1559 | thaw_processes(); | 1587 | thaw_processes(); |
1560 | Restore_console: | 1588 | Restore_console: |
1561 | pm_restore_console(); | 1589 | pm_restore_console(); |
1562 | mutex_unlock(&pm_mutex); | 1590 | unlock_system_sleep(); |
1563 | } | 1591 | } |
1564 | #endif | 1592 | #endif |
1565 | 1593 | ||