xen-vtx-unstable

view linux-2.6-xen-sparse/arch/xen/kernel/devmem.c @ 6774:4d899a738d59

merge?
author cl349@firebug.cl.cam.ac.uk
date Tue Sep 13 15:05:49 2005 +0000 (2005-09-13)
parents dd668f7527cb
children
line source
1 /*
2 * Originally from linux/drivers/char/mem.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 *
6 * Added devfs support.
7 * Jan-11-1998, C. Scott Ananian <cananian@alumni.princeton.edu>
8 * Shared /dev/zero mmaping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com>
9 */
11 #include <linux/config.h>
12 #include <linux/mm.h>
13 #include <linux/miscdevice.h>
14 #include <linux/slab.h>
15 #include <linux/vmalloc.h>
16 #include <linux/mman.h>
17 #include <linux/random.h>
18 #include <linux/init.h>
19 #include <linux/raw.h>
20 #include <linux/tty.h>
21 #include <linux/capability.h>
22 #include <linux/smp_lock.h>
23 #include <linux/devfs_fs_kernel.h>
24 #include <linux/ptrace.h>
25 #include <linux/device.h>
26 #include <asm/pgalloc.h>
27 #include <asm/uaccess.h>
28 #include <asm/io.h>
30 static inline int uncached_access(struct file *file, unsigned long addr)
31 {
32 if (file->f_flags & O_SYNC)
33 return 1;
34 /* Xen sets correct MTRR type on non-RAM for us. */
35 return 0;
36 }
38 /*
39 * This funcion reads the *physical* memory. The f_pos points directly to the
40 * memory location.
41 */
42 static ssize_t read_mem(struct file * file, char __user * buf,
43 size_t count, loff_t *ppos)
44 {
45 unsigned long i, p = *ppos;
46 ssize_t read = -EFAULT;
47 void *v;
49 if ((v = ioremap(p, count)) == NULL) {
50 /*
51 * Some programs (e.g., dmidecode) groove off into weird RAM
52 * areas where no table scan possibly exist (because Xen will
53 * have stomped on them!). These programs get rather upset if
54 * we let them know that Xen failed their access, so we fake
55 * out a read of all zeroes. :-)
56 */
57 for (i = 0; i < count; i++)
58 if (put_user(0, buf+i))
59 return -EFAULT;
60 return count;
61 }
62 if (copy_to_user(buf, v, count))
63 goto out;
65 read = count;
66 *ppos += read;
67 out:
68 iounmap(v);
69 return read;
70 }
72 static ssize_t write_mem(struct file * file, const char __user * buf,
73 size_t count, loff_t *ppos)
74 {
75 unsigned long p = *ppos;
76 ssize_t written = -EFAULT;
77 void *v;
79 if ((v = ioremap(p, count)) == NULL)
80 return -EFAULT;
81 if (copy_to_user(v, buf, count))
82 goto out;
84 written = count;
85 *ppos += written;
86 out:
87 iounmap(v);
88 return written;
89 }
91 static int mmap_mem(struct file * file, struct vm_area_struct * vma)
92 {
93 unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
94 int uncached;
96 uncached = uncached_access(file, offset);
97 if (uncached)
98 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
100 /* Don't try to swap out physical pages.. */
101 vma->vm_flags |= VM_RESERVED;
103 /*
104 * Don't dump addresses that are not real memory to a core file.
105 */
106 if (uncached)
107 vma->vm_flags |= VM_IO;
109 if (io_remap_page_range(vma, vma->vm_start, offset,
110 vma->vm_end-vma->vm_start, vma->vm_page_prot))
111 return -EAGAIN;
113 return 0;
114 }
116 /*
117 * The memory devices use the full 32/64 bits of the offset, and so we cannot
118 * check against negative addresses: they are ok. The return value is weird,
119 * though, in that case (0).
120 *
121 * also note that seeking relative to the "end of file" isn't supported:
122 * it has no meaning, so it returns -EINVAL.
123 */
124 static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
125 {
126 loff_t ret;
128 down(&file->f_dentry->d_inode->i_sem);
129 switch (orig) {
130 case 0:
131 file->f_pos = offset;
132 ret = file->f_pos;
133 force_successful_syscall_return();
134 break;
135 case 1:
136 file->f_pos += offset;
137 ret = file->f_pos;
138 force_successful_syscall_return();
139 break;
140 default:
141 ret = -EINVAL;
142 }
143 up(&file->f_dentry->d_inode->i_sem);
144 return ret;
145 }
147 static int open_mem(struct inode * inode, struct file * filp)
148 {
149 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
150 }
152 struct file_operations mem_fops = {
153 .llseek = memory_lseek,
154 .read = read_mem,
155 .write = write_mem,
156 .mmap = mmap_mem,
157 .open = open_mem,
158 };