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 @@  #include <linux/hardirq.h>  #include <linux/elf.h>  #include <linux/elfcore.h> -#include <linux/utsrelease.h> +#include <generated/utsrelease.h>  #include <linux/utsname.h>  #include <linux/numa.h>  #include <linux/suspend.h> @@ -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)  { | 
