diff options
Diffstat (limited to 'kernel/kexec.c')
| -rw-r--r-- | kernel/kexec.c | 61 |
1 files changed, 60 insertions, 1 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c index f336e2107f98..a9a93d9ee7a7 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,7 @@ | |||
| 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> | ||
| 34 | 35 | ||
| 35 | #include <asm/page.h> | 36 | #include <asm/page.h> |
| 36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
| @@ -1082,6 +1083,64 @@ void crash_kexec(struct pt_regs *regs) | |||
| 1082 | } | 1083 | } |
| 1083 | } | 1084 | } |
| 1084 | 1085 | ||
| 1086 | size_t crash_get_memory_size(void) | ||
| 1087 | { | ||
| 1088 | size_t size; | ||
| 1089 | mutex_lock(&kexec_mutex); | ||
| 1090 | size = crashk_res.end - crashk_res.start + 1; | ||
| 1091 | mutex_unlock(&kexec_mutex); | ||
| 1092 | return size; | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | static void free_reserved_phys_range(unsigned long begin, unsigned long end) | ||
| 1096 | { | ||
| 1097 | unsigned long addr; | ||
| 1098 | |||
| 1099 | for (addr = begin; addr < end; addr += PAGE_SIZE) { | ||
| 1100 | ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT)); | ||
| 1101 | init_page_count(pfn_to_page(addr >> PAGE_SHIFT)); | ||
| 1102 | free_page((unsigned long)__va(addr)); | ||
| 1103 | totalram_pages++; | ||
| 1104 | } | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | int crash_shrink_memory(unsigned long new_size) | ||
| 1108 | { | ||
| 1109 | int ret = 0; | ||
| 1110 | unsigned long start, end; | ||
| 1111 | |||
| 1112 | mutex_lock(&kexec_mutex); | ||
| 1113 | |||
| 1114 | if (kexec_crash_image) { | ||
| 1115 | ret = -ENOENT; | ||
| 1116 | goto unlock; | ||
| 1117 | } | ||
| 1118 | start = crashk_res.start; | ||
| 1119 | end = crashk_res.end; | ||
| 1120 | |||
| 1121 | if (new_size >= end - start + 1) { | ||
| 1122 | ret = -EINVAL; | ||
| 1123 | if (new_size == end - start + 1) | ||
| 1124 | ret = 0; | ||
| 1125 | goto unlock; | ||
| 1126 | } | ||
| 1127 | |||
| 1128 | start = roundup(start, PAGE_SIZE); | ||
| 1129 | end = roundup(start + new_size, PAGE_SIZE); | ||
| 1130 | |||
| 1131 | free_reserved_phys_range(end, crashk_res.end); | ||
| 1132 | |||
| 1133 | if (start == end) { | ||
| 1134 | crashk_res.end = end; | ||
| 1135 | release_resource(&crashk_res); | ||
| 1136 | } else | ||
| 1137 | crashk_res.end = end - 1; | ||
| 1138 | |||
| 1139 | unlock: | ||
| 1140 | mutex_unlock(&kexec_mutex); | ||
| 1141 | return ret; | ||
| 1142 | } | ||
| 1143 | |||
| 1085 | static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data, | 1144 | static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data, |
| 1086 | size_t data_len) | 1145 | size_t data_len) |
| 1087 | { | 1146 | { |
