diff options
Diffstat (limited to 'kernel/kexec.c')
-rw-r--r-- | kernel/kexec.c | 65 |
1 files changed, 63 insertions, 2 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c index f336e2107f98..474a84715eac 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <linux/hardirq.h> | 21 | #include <linux/hardirq.h> |
22 | #include <linux/elf.h> | 22 | #include <linux/elf.h> |
23 | #include <linux/elfcore.h> | 23 | #include <linux/elfcore.h> |
24 | #include <linux/utsrelease.h> | 24 | #include <generated/utsrelease.h> |
25 | #include <linux/utsname.h> | 25 | #include <linux/utsname.h> |
26 | #include <linux/numa.h> | 26 | #include <linux/numa.h> |
27 | #include <linux/suspend.h> | 27 | #include <linux/suspend.h> |
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/cpu.h> | 31 | #include <linux/cpu.h> |
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> | ||
35 | #include <linux/kmsg_dump.h> | ||
34 | 36 | ||
35 | #include <asm/page.h> | 37 | #include <asm/page.h> |
36 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
@@ -39,7 +41,7 @@ | |||
39 | #include <asm/sections.h> | 41 | #include <asm/sections.h> |
40 | 42 | ||
41 | /* Per cpu memory for storing cpu states in case of system crash. */ | 43 | /* Per cpu memory for storing cpu states in case of system crash. */ |
42 | note_buf_t* crash_notes; | 44 | note_buf_t __percpu *crash_notes; |
43 | 45 | ||
44 | /* vmcoreinfo stuff */ | 46 | /* vmcoreinfo stuff */ |
45 | static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES]; | 47 | static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES]; |
@@ -1073,6 +1075,9 @@ void crash_kexec(struct pt_regs *regs) | |||
1073 | if (mutex_trylock(&kexec_mutex)) { | 1075 | if (mutex_trylock(&kexec_mutex)) { |
1074 | if (kexec_crash_image) { | 1076 | if (kexec_crash_image) { |
1075 | struct pt_regs fixed_regs; | 1077 | struct pt_regs fixed_regs; |
1078 | |||
1079 | kmsg_dump(KMSG_DUMP_KEXEC); | ||
1080 | |||
1076 | crash_setup_regs(&fixed_regs, regs); | 1081 | crash_setup_regs(&fixed_regs, regs); |
1077 | crash_save_vmcoreinfo(); | 1082 | crash_save_vmcoreinfo(); |
1078 | machine_crash_shutdown(&fixed_regs); | 1083 | machine_crash_shutdown(&fixed_regs); |
@@ -1082,6 +1087,62 @@ void crash_kexec(struct pt_regs *regs) | |||
1082 | } | 1087 | } |
1083 | } | 1088 | } |
1084 | 1089 | ||
1090 | size_t crash_get_memory_size(void) | ||
1091 | { | ||
1092 | size_t size; | ||
1093 | mutex_lock(&kexec_mutex); | ||
1094 | size = crashk_res.end - crashk_res.start + 1; | ||
1095 | mutex_unlock(&kexec_mutex); | ||
1096 | return size; | ||
1097 | } | ||
1098 | |||
1099 | static void free_reserved_phys_range(unsigned long begin, unsigned long end) | ||
1100 | { | ||
1101 | unsigned long addr; | ||
1102 | |||
1103 | for (addr = begin; addr < end; addr += PAGE_SIZE) { | ||
1104 | ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT)); | ||
1105 | init_page_count(pfn_to_page(addr >> PAGE_SHIFT)); | ||
1106 | free_page((unsigned long)__va(addr)); | ||
1107 | totalram_pages++; | ||
1108 | } | ||
1109 | } | ||
1110 | |||
1111 | int crash_shrink_memory(unsigned long new_size) | ||
1112 | { | ||
1113 | int ret = 0; | ||
1114 | unsigned long start, end; | ||
1115 | |||
1116 | mutex_lock(&kexec_mutex); | ||
1117 | |||
1118 | if (kexec_crash_image) { | ||
1119 | ret = -ENOENT; | ||
1120 | goto unlock; | ||
1121 | } | ||
1122 | start = crashk_res.start; | ||
1123 | end = crashk_res.end; | ||
1124 | |||
1125 | if (new_size >= end - start + 1) { | ||
1126 | ret = -EINVAL; | ||
1127 | if (new_size == end - start + 1) | ||
1128 | ret = 0; | ||
1129 | goto unlock; | ||
1130 | } | ||
1131 | |||
1132 | start = roundup(start, PAGE_SIZE); | ||
1133 | end = roundup(start + new_size, PAGE_SIZE); | ||
1134 | |||
1135 | free_reserved_phys_range(end, crashk_res.end); | ||
1136 | |||
1137 | if (start == end) | ||
1138 | release_resource(&crashk_res); | ||
1139 | crashk_res.end = end - 1; | ||
1140 | |||
1141 | unlock: | ||
1142 | mutex_unlock(&kexec_mutex); | ||
1143 | return ret; | ||
1144 | } | ||
1145 | |||
1085 | static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data, | 1146 | static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data, |
1086 | size_t data_len) | 1147 | size_t data_len) |
1087 | { | 1148 | { |