aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorVivek Goyal <vgoyal@in.ibm.com>2005-06-25 17:58:23 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-25 19:24:54 -0400
commit50b1fdbd81edcc8bd343ca44aca2b87a29e2f15c (patch)
treefc5da6014f015171574c337be1c3abce5573ec99 /drivers/char
parent72658e9d5004fc0dd807bea9eda49e6a52e40103 (diff)
[PATCH] kdump: Accessing dump file in linear raw format (/dev/oldmem)
Hariprasad Nellitheertha <hari@in.ibm.com> This patch contains the code that enables us to access the previous kernel's memory as /dev/oldmem. Signed-off-by: Eric Biederman <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/mem.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index e3085b22a365..01b3c17ca851 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -23,6 +23,8 @@
23#include <linux/devfs_fs_kernel.h> 23#include <linux/devfs_fs_kernel.h>
24#include <linux/ptrace.h> 24#include <linux/ptrace.h>
25#include <linux/device.h> 25#include <linux/device.h>
26#include <linux/highmem.h>
27#include <linux/crash_dump.h>
26#include <linux/backing-dev.h> 28#include <linux/backing-dev.h>
27 29
28#include <asm/uaccess.h> 30#include <asm/uaccess.h>
@@ -273,6 +275,62 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
273 return mmap_mem(file, vma); 275 return mmap_mem(file, vma);
274} 276}
275 277
278#ifdef CONFIG_CRASH_DUMP
279/*
280 * Read memory corresponding to the old kernel.
281 * If we are reading from the reserved section, which is
282 * actually used by the current kernel, we just return zeroes.
283 * Or if we are reading from the first 640k, we return from the
284 * backed up area.
285 */
286static ssize_t read_oldmem(struct file * file, char * buf,
287 size_t count, loff_t *ppos)
288{
289 unsigned long pfn;
290 unsigned backup_start, backup_end, relocate_start;
291 size_t read=0, csize;
292
293 backup_start = CRASH_BACKUP_BASE / PAGE_SIZE;
294 backup_end = backup_start + (CRASH_BACKUP_SIZE / PAGE_SIZE);
295 relocate_start = (CRASH_BACKUP_BASE + CRASH_BACKUP_SIZE) / PAGE_SIZE;
296
297 while(count) {
298 pfn = *ppos / PAGE_SIZE;
299
300 csize = (count > PAGE_SIZE) ? PAGE_SIZE : count;
301
302 /* Perform translation (see comment above) */
303 if ((pfn >= backup_start) && (pfn < backup_end)) {
304 if (clear_user(buf, csize)) {
305 read = -EFAULT;
306 goto done;
307 }
308
309 goto copy_done;
310 } else if (pfn < (CRASH_RELOCATE_SIZE / PAGE_SIZE))
311 pfn += relocate_start;
312
313 if (pfn > saved_max_pfn) {
314 read = 0;
315 goto done;
316 }
317
318 if (copy_oldmem_page(pfn, buf, csize, 1)) {
319 read = -EFAULT;
320 goto done;
321 }
322
323copy_done:
324 buf += csize;
325 *ppos += csize;
326 read += csize;
327 count -= csize;
328 }
329done:
330 return read;
331}
332#endif
333
276extern long vread(char *buf, char *addr, unsigned long count); 334extern long vread(char *buf, char *addr, unsigned long count);
277extern long vwrite(char *buf, char *addr, unsigned long count); 335extern long vwrite(char *buf, char *addr, unsigned long count);
278 336
@@ -721,6 +779,7 @@ static int open_port(struct inode * inode, struct file * filp)
721#define read_full read_zero 779#define read_full read_zero
722#define open_mem open_port 780#define open_mem open_port
723#define open_kmem open_mem 781#define open_kmem open_mem
782#define open_oldmem open_mem
724 783
725static struct file_operations mem_fops = { 784static struct file_operations mem_fops = {
726 .llseek = memory_lseek, 785 .llseek = memory_lseek,
@@ -770,6 +829,13 @@ static struct file_operations full_fops = {
770 .write = write_full, 829 .write = write_full,
771}; 830};
772 831
832#ifdef CONFIG_CRASH_DUMP
833static struct file_operations oldmem_fops = {
834 .read = read_oldmem,
835 .open = open_oldmem,
836};
837#endif
838
773static ssize_t kmsg_write(struct file * file, const char __user * buf, 839static ssize_t kmsg_write(struct file * file, const char __user * buf,
774 size_t count, loff_t *ppos) 840 size_t count, loff_t *ppos)
775{ 841{
@@ -825,6 +891,11 @@ static int memory_open(struct inode * inode, struct file * filp)
825 case 11: 891 case 11:
826 filp->f_op = &kmsg_fops; 892 filp->f_op = &kmsg_fops;
827 break; 893 break;
894#ifdef CONFIG_CRASH_DUMP
895 case 12:
896 filp->f_op = &oldmem_fops;
897 break;
898#endif
828 default: 899 default:
829 return -ENXIO; 900 return -ENXIO;
830 } 901 }
@@ -854,6 +925,9 @@ static const struct {
854 {8, "random", S_IRUGO | S_IWUSR, &random_fops}, 925 {8, "random", S_IRUGO | S_IWUSR, &random_fops},
855 {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops}, 926 {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops},
856 {11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops}, 927 {11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops},
928#ifdef CONFIG_CRASH_DUMP
929 {12,"oldmem", S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops},
930#endif
857}; 931};
858 932
859static struct class *mem_class; 933static struct class *mem_class;