ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/char/mem.c @ 14100:e47738923a05

[LINUX] Purge include <linux/config.h>. It has been obsolete for some time now.

Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
author Ian Campbell <ian.campbell@xensource.com>
date Fri Feb 23 16:56:45 2007 +0000 (2007-02-23)
parents 3adf00179a63
children 2caed72258e8
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/mm.h>
12 #include <linux/miscdevice.h>
13 #include <linux/slab.h>
14 #include <linux/vmalloc.h>
15 #include <linux/mman.h>
16 #include <linux/random.h>
17 #include <linux/init.h>
18 #include <linux/raw.h>
19 #include <linux/tty.h>
20 #include <linux/capability.h>
21 #include <linux/smp_lock.h>
22 #include <linux/ptrace.h>
23 #include <linux/device.h>
24 #include <asm/pgalloc.h>
25 #include <asm/uaccess.h>
26 #include <asm/io.h>
27 #include <asm/hypervisor.h>
29 #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE
30 static inline int valid_phys_addr_range(unsigned long addr, size_t *count)
31 {
32 return 1;
33 }
34 #endif
36 /*
37 * This funcion reads the *physical* memory. The f_pos points directly to the
38 * memory location.
39 */
40 static ssize_t read_mem(struct file * file, char __user * buf,
41 size_t count, loff_t *ppos)
42 {
43 unsigned long p = *ppos, ignored;
44 ssize_t read = 0, sz;
45 void __iomem *v;
47 if (!valid_phys_addr_range(p, &count))
48 return -EFAULT;
50 while (count > 0) {
51 /*
52 * Handle first page in case it's not aligned
53 */
54 if (-p & (PAGE_SIZE - 1))
55 sz = -p & (PAGE_SIZE - 1);
56 else
57 sz = PAGE_SIZE;
59 sz = min_t(unsigned long, sz, count);
61 v = xlate_dev_mem_ptr(p, sz);
62 if (IS_ERR(v) || v == NULL) {
63 /*
64 * Some programs (e.g., dmidecode) groove off into
65 * weird RAM areas where no tables can possibly exist
66 * (because Xen will have stomped on them!). These
67 * programs get rather upset if we let them know that
68 * Xen failed their access, so we fake out a read of
69 * all zeroes.
70 */
71 if (clear_user(buf, count))
72 return -EFAULT;
73 read += count;
74 break;
75 }
77 ignored = copy_to_user(buf, v, sz);
78 xlate_dev_mem_ptr_unmap(v);
79 if (ignored)
80 return -EFAULT;
81 buf += sz;
82 p += sz;
83 count -= sz;
84 read += sz;
85 }
87 *ppos += read;
88 return read;
89 }
91 static ssize_t write_mem(struct file * file, const char __user * buf,
92 size_t count, loff_t *ppos)
93 {
94 unsigned long p = *ppos, ignored;
95 ssize_t written = 0, sz;
96 void __iomem *v;
98 if (!valid_phys_addr_range(p, &count))
99 return -EFAULT;
101 while (count > 0) {
102 /*
103 * Handle first page in case it's not aligned
104 */
105 if (-p & (PAGE_SIZE - 1))
106 sz = -p & (PAGE_SIZE - 1);
107 else
108 sz = PAGE_SIZE;
110 sz = min_t(unsigned long, sz, count);
112 v = xlate_dev_mem_ptr(p, sz);
113 if (v == NULL)
114 break;
115 if (IS_ERR(v)) {
116 if (written == 0)
117 return PTR_ERR(v);
118 break;
119 }
121 ignored = copy_from_user(v, buf, sz);
122 xlate_dev_mem_ptr_unmap(v);
123 if (ignored) {
124 written += sz - ignored;
125 if (written)
126 break;
127 return -EFAULT;
128 }
129 buf += sz;
130 p += sz;
131 count -= sz;
132 written += sz;
133 }
135 *ppos += written;
136 return written;
137 }
139 #ifndef ARCH_HAS_DEV_MEM_MMAP_MEM
140 static inline int uncached_access(struct file *file)
141 {
142 if (file->f_flags & O_SYNC)
143 return 1;
144 /* Xen sets correct MTRR type on non-RAM for us. */
145 return 0;
146 }
148 static int xen_mmap_mem(struct file * file, struct vm_area_struct * vma)
149 {
150 size_t size = vma->vm_end - vma->vm_start;
152 if (uncached_access(file))
153 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
155 /* We want to return the real error code, not EAGAIN. */
156 return direct_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
157 size, vma->vm_page_prot, DOMID_IO);
158 }
159 #endif
161 /*
162 * The memory devices use the full 32/64 bits of the offset, and so we cannot
163 * check against negative addresses: they are ok. The return value is weird,
164 * though, in that case (0).
165 *
166 * also note that seeking relative to the "end of file" isn't supported:
167 * it has no meaning, so it returns -EINVAL.
168 */
169 static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
170 {
171 loff_t ret;
173 mutex_lock(&file->f_dentry->d_inode->i_mutex);
174 switch (orig) {
175 case 0:
176 file->f_pos = offset;
177 ret = file->f_pos;
178 force_successful_syscall_return();
179 break;
180 case 1:
181 file->f_pos += offset;
182 ret = file->f_pos;
183 force_successful_syscall_return();
184 break;
185 default:
186 ret = -EINVAL;
187 }
188 mutex_unlock(&file->f_dentry->d_inode->i_mutex);
189 return ret;
190 }
192 static int open_mem(struct inode * inode, struct file * filp)
193 {
194 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
195 }
197 struct file_operations mem_fops = {
198 .llseek = memory_lseek,
199 .read = read_mem,
200 .write = write_mem,
201 .mmap = xen_mmap_mem,
202 .open = open_mem,
203 };