diff options
Diffstat (limited to 'kernel/kexec.c')
-rw-r--r-- | kernel/kexec.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c index f336e2107f98..433e9fcc1fc5 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
@@ -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 | { |