2 * kernel/crash.c - Memory preserving reboot related code.
4 * Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
5 * Copyright (C) IBM Corporation, 2004. All rights reserved
8 #include <linux/smp_lock.h>
9 #include <linux/kexec.h>
10 #include <linux/errno.h>
11 #include <linux/proc_fs.h>
12 #include <linux/bootmem.h>
13 #include <linux/highmem.h>
14 #include <linux/crash_dump.h>
17 #include <asm/uaccess.h>
21 * Enable kexec reboot upon panic; for dumping
23 static ssize_t write_crash_dump_on(struct file *file, const char __user *buf,
24 size_t count, loff_t *ppos)
27 if (get_user(crash_dump_on, buf))
33 static struct file_operations proc_crash_dump_on_operations = {
34 .write = write_crash_dump_on,
37 extern struct file_operations proc_vmcore_operations;
38 extern struct proc_dir_entry *proc_vmcore;
40 void crash_enable_by_proc(void)
42 struct proc_dir_entry *entry;
44 entry = create_proc_entry("kexec-dump", S_IWUSR, NULL);
46 entry->proc_fops = &proc_crash_dump_on_operations;
49 void crash_create_proc_entry(void)
52 proc_vmcore = create_proc_entry("vmcore", S_IRUSR, NULL);
54 proc_vmcore->proc_fops = &proc_vmcore_operations;
56 (size_t)(saved_max_pfn << PAGE_SHIFT);
61 #endif /* CONFIG_PROC_FS */
63 void __crash_machine_kexec(void)
67 if ((!crash_dump_on) || (crashed))
70 image = xchg(&kexec_crash_image, 0);
73 printk(KERN_EMERG "kexec: opening parachute\n");
74 crash_dump_stop_cpus();
75 crash_dump_save_registers();
77 /* If we are here to do a crash dump, save the memory from
78 * 0-640k before we copy over the kexec kernel image. Otherwise
79 * our dump will show the wrong kernel entirely.
85 printk(KERN_EMERG "kexec: No kernel image loaded!\n");
90 * Copy a page from "oldmem". For this page, there is no pte mapped
91 * in the current kernel. We stitch up a pte, similar to kmap_atomic.
93 ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
94 size_t csize, int userbuf)
101 page = kmalloc(PAGE_SIZE, GFP_KERNEL);
103 vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
104 copy_page(page, vaddr);
105 kunmap_atomic(vaddr, KM_PTE0);
108 if (copy_to_user(buf, page, csize)) {
113 memcpy(buf, page, csize);