|
@@ -31,6 +31,7 @@
|
|
|
#include <linux/cpu.h>
|
|
|
#include <linux/console.h>
|
|
|
#include <linux/vmalloc.h>
|
|
|
+#include <linux/swap.h>
|
|
|
|
|
|
#include <asm/page.h>
|
|
|
#include <asm/uaccess.h>
|
|
@@ -1082,6 +1083,64 @@ void crash_kexec(struct pt_regs *regs)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+size_t crash_get_memory_size(void)
|
|
|
+{
|
|
|
+ size_t size;
|
|
|
+ mutex_lock(&kexec_mutex);
|
|
|
+ size = crashk_res.end - crashk_res.start + 1;
|
|
|
+ mutex_unlock(&kexec_mutex);
|
|
|
+ return size;
|
|
|
+}
|
|
|
+
|
|
|
+static void free_reserved_phys_range(unsigned long begin, unsigned long end)
|
|
|
+{
|
|
|
+ unsigned long addr;
|
|
|
+
|
|
|
+ for (addr = begin; addr < end; addr += PAGE_SIZE) {
|
|
|
+ ClearPageReserved(pfn_to_page(addr >> PAGE_SHIFT));
|
|
|
+ init_page_count(pfn_to_page(addr >> PAGE_SHIFT));
|
|
|
+ free_page((unsigned long)__va(addr));
|
|
|
+ totalram_pages++;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int crash_shrink_memory(unsigned long new_size)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+ unsigned long start, end;
|
|
|
+
|
|
|
+ mutex_lock(&kexec_mutex);
|
|
|
+
|
|
|
+ if (kexec_crash_image) {
|
|
|
+ ret = -ENOENT;
|
|
|
+ goto unlock;
|
|
|
+ }
|
|
|
+ start = crashk_res.start;
|
|
|
+ end = crashk_res.end;
|
|
|
+
|
|
|
+ if (new_size >= end - start + 1) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ if (new_size == end - start + 1)
|
|
|
+ ret = 0;
|
|
|
+ goto unlock;
|
|
|
+ }
|
|
|
+
|
|
|
+ start = roundup(start, PAGE_SIZE);
|
|
|
+ end = roundup(start + new_size, PAGE_SIZE);
|
|
|
+
|
|
|
+ free_reserved_phys_range(end, crashk_res.end);
|
|
|
+
|
|
|
+ if (start == end) {
|
|
|
+ crashk_res.end = end;
|
|
|
+ release_resource(&crashk_res);
|
|
|
+ } else
|
|
|
+ crashk_res.end = end - 1;
|
|
|
+
|
|
|
+unlock:
|
|
|
+ mutex_unlock(&kexec_mutex);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
|
|
|
size_t data_len)
|
|
|
{
|