diff options
Diffstat (limited to 'kernel/kexec.c')
| -rw-r--r-- | kernel/kexec.c | 70 | 
1 files changed, 49 insertions, 21 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c index 296fbc84d65..7b088678670 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -32,7 +32,6 @@  #include <linux/console.h>  #include <linux/vmalloc.h>  #include <linux/swap.h> -#include <linux/kmsg_dump.h>  #include <linux/syscore_ops.h>  #include <asm/page.h> @@ -498,7 +497,7 @@ static struct page *kimage_alloc_crash_control_pages(struct kimage *image,  	while (hole_end <= crashk_res.end) {  		unsigned long i; -		if (hole_end > KEXEC_CONTROL_MEMORY_LIMIT) +		if (hole_end > KEXEC_CRASH_CONTROL_MEMORY_LIMIT)  			break;  		if (hole_end > crashk_res.end)  			break; @@ -999,6 +998,7 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,  			kimage_free(xchg(&kexec_crash_image, NULL));  			result = kimage_crash_alloc(&image, entry,  						     nr_segments, segments); +			crash_map_reserved_pages();  		}  		if (result)  			goto out; @@ -1015,6 +1015,8 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,  				goto out;  		}  		kimage_terminate(image); +		if (flags & KEXEC_ON_CRASH) +			crash_unmap_reserved_pages();  	}  	/* Install the new kernel, and  Uninstall the old */  	image = xchg(dest_image, image); @@ -1026,6 +1028,18 @@ out:  	return result;  } +/* + * Add and remove page tables for crashkernel memory + * + * Provide an empty default implementation here -- architecture + * code may override this + */ +void __weak crash_map_reserved_pages(void) +{} + +void __weak crash_unmap_reserved_pages(void) +{} +  #ifdef CONFIG_COMPAT  asmlinkage long compat_sys_kexec_load(unsigned long entry,  				unsigned long nr_segments, @@ -1079,8 +1093,6 @@ void crash_kexec(struct pt_regs *regs)  		if (kexec_crash_image) {  			struct pt_regs fixed_regs; -			kmsg_dump(KMSG_DUMP_KEXEC); -  			crash_setup_regs(&fixed_regs, regs);  			crash_save_vmcoreinfo();  			machine_crash_shutdown(&fixed_regs); @@ -1117,6 +1129,8 @@ int crash_shrink_memory(unsigned long new_size)  {  	int ret = 0;  	unsigned long start, end; +	unsigned long old_size; +	struct resource *ram_res;  	mutex_lock(&kexec_mutex); @@ -1126,23 +1140,37 @@ int crash_shrink_memory(unsigned long new_size)  	}  	start = crashk_res.start;  	end = crashk_res.end; +	old_size = (end == 0) ? 0 : end - start + 1; +	if (new_size >= old_size) { +		ret = (new_size == old_size) ? 0 : -EINVAL; +		goto unlock; +	} -	if (new_size >= end - start + 1) { -		ret = -EINVAL; -		if (new_size == end - start + 1) -			ret = 0; +	ram_res = kzalloc(sizeof(*ram_res), GFP_KERNEL); +	if (!ram_res) { +		ret = -ENOMEM;  		goto unlock;  	} -	start = roundup(start, PAGE_SIZE); -	end = roundup(start + new_size, PAGE_SIZE); +	start = roundup(start, KEXEC_CRASH_MEM_ALIGN); +	end = roundup(start + new_size, KEXEC_CRASH_MEM_ALIGN); +	crash_map_reserved_pages();  	crash_free_reserved_phys_range(end, crashk_res.end);  	if ((start == end) && (crashk_res.parent != NULL))  		release_resource(&crashk_res); + +	ram_res->start = end; +	ram_res->end = crashk_res.end; +	ram_res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; +	ram_res->name = "System RAM"; +  	crashk_res.end = end - 1; +	insert_resource(&iomem_resource, ram_res); +	crash_unmap_reserved_pages(); +  unlock:  	mutex_unlock(&kexec_mutex);  	return ret; @@ -1380,24 +1408,23 @@ int __init parse_crashkernel(char 		 *cmdline,  } - -void crash_save_vmcoreinfo(void) +static void update_vmcoreinfo_note(void)  { -	u32 *buf; +	u32 *buf = vmcoreinfo_note;  	if (!vmcoreinfo_size)  		return; - -	vmcoreinfo_append_str("CRASHTIME=%ld", get_seconds()); - -	buf = (u32 *)vmcoreinfo_note; -  	buf = append_elf_note(buf, VMCOREINFO_NOTE_NAME, 0, vmcoreinfo_data,  			      vmcoreinfo_size); -  	final_note(buf);  } +void crash_save_vmcoreinfo(void) +{ +	vmcoreinfo_append_str("CRASHTIME=%ld", get_seconds()); +	update_vmcoreinfo_note(); +} +  void vmcoreinfo_append_str(const char *fmt, ...)  {  	va_list args; @@ -1483,6 +1510,7 @@ static int __init crash_save_vmcoreinfo_init(void)  	VMCOREINFO_NUMBER(PG_swapcache);  	arch_crash_save_vmcoreinfo(); +	update_vmcoreinfo_note();  	return 0;  } @@ -1506,7 +1534,7 @@ int kernel_kexec(void)  #ifdef CONFIG_KEXEC_JUMP  	if (kexec_image->preserve_context) { -		mutex_lock(&pm_mutex); +		lock_system_sleep();  		pm_prepare_console();  		error = freeze_processes();  		if (error) { @@ -1559,7 +1587,7 @@ int kernel_kexec(void)  		thaw_processes();   Restore_console:  		pm_restore_console(); -		mutex_unlock(&pm_mutex); +		unlock_system_sleep();  	}  #endif  |