diff options
Diffstat (limited to 'drivers/char/mem.c')
| -rw-r--r-- | drivers/char/mem.c | 68 |
1 files changed, 60 insertions, 8 deletions
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 947cb3cef816..42187381506b 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
| @@ -23,7 +23,10 @@ | |||
| 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> |
| 29 | #include <linux/bootmem.h> | ||
| 27 | 30 | ||
| 28 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
| 29 | #include <asm/io.h> | 32 | #include <asm/io.h> |
| @@ -273,6 +276,40 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma) | |||
| 273 | return mmap_mem(file, vma); | 276 | return mmap_mem(file, vma); |
| 274 | } | 277 | } |
| 275 | 278 | ||
| 279 | #ifdef CONFIG_CRASH_DUMP | ||
| 280 | /* | ||
| 281 | * Read memory corresponding to the old kernel. | ||
| 282 | */ | ||
| 283 | static ssize_t read_oldmem(struct file *file, char __user *buf, | ||
| 284 | size_t count, loff_t *ppos) | ||
| 285 | { | ||
| 286 | unsigned long pfn, offset; | ||
| 287 | size_t read = 0, csize; | ||
| 288 | int rc = 0; | ||
| 289 | |||
| 290 | while (count) { | ||
| 291 | pfn = *ppos / PAGE_SIZE; | ||
| 292 | if (pfn > saved_max_pfn) | ||
| 293 | return read; | ||
| 294 | |||
| 295 | offset = (unsigned long)(*ppos % PAGE_SIZE); | ||
| 296 | if (count > PAGE_SIZE - offset) | ||
| 297 | csize = PAGE_SIZE - offset; | ||
| 298 | else | ||
| 299 | csize = count; | ||
| 300 | |||
| 301 | rc = copy_oldmem_page(pfn, buf, csize, offset, 1); | ||
| 302 | if (rc < 0) | ||
| 303 | return rc; | ||
| 304 | buf += csize; | ||
| 305 | *ppos += csize; | ||
| 306 | read += csize; | ||
| 307 | count -= csize; | ||
| 308 | } | ||
| 309 | return read; | ||
| 310 | } | ||
| 311 | #endif | ||
| 312 | |||
| 276 | extern long vread(char *buf, char *addr, unsigned long count); | 313 | extern long vread(char *buf, char *addr, unsigned long count); |
| 277 | extern long vwrite(char *buf, char *addr, unsigned long count); | 314 | extern long vwrite(char *buf, char *addr, unsigned long count); |
| 278 | 315 | ||
| @@ -484,7 +521,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, | |||
| 484 | return virtr + wrote; | 521 | return virtr + wrote; |
| 485 | } | 522 | } |
| 486 | 523 | ||
| 487 | #if defined(CONFIG_ISA) || !defined(__mc68000__) | 524 | #if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)) |
| 488 | static ssize_t read_port(struct file * file, char __user * buf, | 525 | static ssize_t read_port(struct file * file, char __user * buf, |
| 489 | size_t count, loff_t *ppos) | 526 | size_t count, loff_t *ppos) |
| 490 | { | 527 | { |
| @@ -721,6 +758,7 @@ static int open_port(struct inode * inode, struct file * filp) | |||
| 721 | #define read_full read_zero | 758 | #define read_full read_zero |
| 722 | #define open_mem open_port | 759 | #define open_mem open_port |
| 723 | #define open_kmem open_mem | 760 | #define open_kmem open_mem |
| 761 | #define open_oldmem open_mem | ||
| 724 | 762 | ||
| 725 | static struct file_operations mem_fops = { | 763 | static struct file_operations mem_fops = { |
| 726 | .llseek = memory_lseek, | 764 | .llseek = memory_lseek, |
| @@ -744,7 +782,7 @@ static struct file_operations null_fops = { | |||
| 744 | .write = write_null, | 782 | .write = write_null, |
| 745 | }; | 783 | }; |
| 746 | 784 | ||
| 747 | #if defined(CONFIG_ISA) || !defined(__mc68000__) | 785 | #if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)) |
| 748 | static struct file_operations port_fops = { | 786 | static struct file_operations port_fops = { |
| 749 | .llseek = memory_lseek, | 787 | .llseek = memory_lseek, |
| 750 | .read = read_port, | 788 | .read = read_port, |
| @@ -770,6 +808,13 @@ static struct file_operations full_fops = { | |||
| 770 | .write = write_full, | 808 | .write = write_full, |
| 771 | }; | 809 | }; |
| 772 | 810 | ||
| 811 | #ifdef CONFIG_CRASH_DUMP | ||
| 812 | static struct file_operations oldmem_fops = { | ||
| 813 | .read = read_oldmem, | ||
| 814 | .open = open_oldmem, | ||
| 815 | }; | ||
| 816 | #endif | ||
| 817 | |||
| 773 | static ssize_t kmsg_write(struct file * file, const char __user * buf, | 818 | static ssize_t kmsg_write(struct file * file, const char __user * buf, |
| 774 | size_t count, loff_t *ppos) | 819 | size_t count, loff_t *ppos) |
| 775 | { | 820 | { |
| @@ -804,7 +849,7 @@ static int memory_open(struct inode * inode, struct file * filp) | |||
| 804 | case 3: | 849 | case 3: |
| 805 | filp->f_op = &null_fops; | 850 | filp->f_op = &null_fops; |
| 806 | break; | 851 | break; |
| 807 | #if defined(CONFIG_ISA) || !defined(__mc68000__) | 852 | #if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)) |
| 808 | case 4: | 853 | case 4: |
| 809 | filp->f_op = &port_fops; | 854 | filp->f_op = &port_fops; |
| 810 | break; | 855 | break; |
| @@ -825,6 +870,11 @@ static int memory_open(struct inode * inode, struct file * filp) | |||
| 825 | case 11: | 870 | case 11: |
| 826 | filp->f_op = &kmsg_fops; | 871 | filp->f_op = &kmsg_fops; |
| 827 | break; | 872 | break; |
| 873 | #ifdef CONFIG_CRASH_DUMP | ||
| 874 | case 12: | ||
| 875 | filp->f_op = &oldmem_fops; | ||
| 876 | break; | ||
| 877 | #endif | ||
| 828 | default: | 878 | default: |
| 829 | return -ENXIO; | 879 | return -ENXIO; |
| 830 | } | 880 | } |
| @@ -846,7 +896,7 @@ static const struct { | |||
| 846 | {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, | 896 | {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, |
| 847 | {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, | 897 | {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, |
| 848 | {3, "null", S_IRUGO | S_IWUGO, &null_fops}, | 898 | {3, "null", S_IRUGO | S_IWUGO, &null_fops}, |
| 849 | #if defined(CONFIG_ISA) || !defined(__mc68000__) | 899 | #if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)) |
| 850 | {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, | 900 | {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, |
| 851 | #endif | 901 | #endif |
| 852 | {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, | 902 | {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, |
| @@ -854,9 +904,12 @@ static const struct { | |||
| 854 | {8, "random", S_IRUGO | S_IWUSR, &random_fops}, | 904 | {8, "random", S_IRUGO | S_IWUSR, &random_fops}, |
| 855 | {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops}, | 905 | {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops}, |
| 856 | {11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops}, | 906 | {11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops}, |
| 907 | #ifdef CONFIG_CRASH_DUMP | ||
| 908 | {12,"oldmem", S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops}, | ||
| 909 | #endif | ||
| 857 | }; | 910 | }; |
| 858 | 911 | ||
| 859 | static struct class_simple *mem_class; | 912 | static struct class *mem_class; |
| 860 | 913 | ||
| 861 | static int __init chr_dev_init(void) | 914 | static int __init chr_dev_init(void) |
| 862 | { | 915 | { |
| @@ -865,10 +918,9 @@ static int __init chr_dev_init(void) | |||
| 865 | if (register_chrdev(MEM_MAJOR,"mem",&memory_fops)) | 918 | if (register_chrdev(MEM_MAJOR,"mem",&memory_fops)) |
| 866 | printk("unable to get major %d for memory devs\n", MEM_MAJOR); | 919 | printk("unable to get major %d for memory devs\n", MEM_MAJOR); |
| 867 | 920 | ||
| 868 | mem_class = class_simple_create(THIS_MODULE, "mem"); | 921 | mem_class = class_create(THIS_MODULE, "mem"); |
| 869 | for (i = 0; i < ARRAY_SIZE(devlist); i++) { | 922 | for (i = 0; i < ARRAY_SIZE(devlist); i++) { |
| 870 | class_simple_device_add(mem_class, | 923 | class_device_create(mem_class, MKDEV(MEM_MAJOR, devlist[i].minor), |
| 871 | MKDEV(MEM_MAJOR, devlist[i].minor), | ||
| 872 | NULL, devlist[i].name); | 924 | NULL, devlist[i].name); |
| 873 | devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor), | 925 | devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor), |
| 874 | S_IFCHR | devlist[i].mode, devlist[i].name); | 926 | S_IFCHR | devlist[i].mode, devlist[i].name); |
