diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 10:06:39 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 10:06:39 -0800 |
commit | 9cfc86249f32d984339c6d1f8a1fd1326989b3b8 (patch) | |
tree | 56428d319483f54949de8d9d0a5b3f715287ed91 /kernel/kexec.c | |
parent | f42647acc4eab1befa9e290691ed7a40f9a7d3cc (diff) | |
parent | 243797f59b748f679ab88d456fcc4f92236d724b (diff) |
Merge branch 'akpm'
* akpm: (173 commits)
genalloc: use bitmap_find_next_zero_area
ia64: use bitmap_find_next_zero_area
sparc: use bitmap_find_next_zero_area
mlx4: use bitmap_find_next_zero_area
isp1362-hcd: use bitmap_find_next_zero_area
iommu-helper: use bitmap library
bitmap: introduce bitmap_set, bitmap_clear, bitmap_find_next_zero_area
qnx4: use hweight8
qnx4fs: remove remains of the (defunct) write support
resource: constify arg to resource_size() and resource_type()
gru: send cross partition interrupts using the gru
gru: function to generate chipset IPI values
gru: update driver version number
gru: improve GRU TLB dropin statistics
gru: fix GRU interrupt race at deallocate
gru: add hugepage support
gru: fix bug in allocation of kernel contexts
gru: update GRU structures to match latest hardware spec
gru: check for correct GRU chiplet assignment
gru: remove stray local_irq_enable
...
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 @@ #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) { |