diff options
| author | Vivek Goyal <vgoyal@in.ibm.com> | 2005-06-25 17:58:23 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-25 19:24:54 -0400 |
| commit | 50b1fdbd81edcc8bd343ca44aca2b87a29e2f15c (patch) | |
| tree | fc5da6014f015171574c337be1c3abce5573ec99 /drivers/char/mem.c | |
| parent | 72658e9d5004fc0dd807bea9eda49e6a52e40103 (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/mem.c')
| -rw-r--r-- | drivers/char/mem.c | 74 |
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 | */ | ||
| 286 | static 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 | |||
| 323 | copy_done: | ||
| 324 | buf += csize; | ||
| 325 | *ppos += csize; | ||
| 326 | read += csize; | ||
| 327 | count -= csize; | ||
| 328 | } | ||
| 329 | done: | ||
| 330 | return read; | ||
| 331 | } | ||
| 332 | #endif | ||
| 333 | |||
| 276 | extern long vread(char *buf, char *addr, unsigned long count); | 334 | extern long vread(char *buf, char *addr, unsigned long count); |
| 277 | extern long vwrite(char *buf, char *addr, unsigned long count); | 335 | extern 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 | ||
| 725 | static struct file_operations mem_fops = { | 784 | static 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 | ||
| 833 | static struct file_operations oldmem_fops = { | ||
| 834 | .read = read_oldmem, | ||
| 835 | .open = open_oldmem, | ||
| 836 | }; | ||
| 837 | #endif | ||
| 838 | |||
| 773 | static ssize_t kmsg_write(struct file * file, const char __user * buf, | 839 | static 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 | ||
| 859 | static struct class *mem_class; | 933 | static struct class *mem_class; |
