2 * Originally from linux/drivers/char/mem.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
7 * Jan-11-1998, C. Scott Ananian <cananian@alumni.princeton.edu>
8 * Shared /dev/zero mmapping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com>
12 #include <linux/init.h>
14 #include <linux/capability.h>
15 #include <linux/ptrace.h>
16 #include <asm/uaccess.h>
18 #include <asm/hypervisor.h>
20 static inline unsigned long size_inside_page(unsigned long start,
25 sz = PAGE_SIZE - (start & (PAGE_SIZE - 1));
30 static inline int uncached_access(struct file *file)
32 if (file->f_flags & O_DSYNC)
34 /* Xen sets correct MTRR type on non-RAM for us. */
38 static inline int range_is_allowed(unsigned long pfn, unsigned long size)
40 #ifdef CONFIG_STRICT_DEVMEM
41 u64 from = ((u64)pfn) << PAGE_SHIFT;
46 if (!devmem_is_allowed(pfn)) {
48 "Program %s tried to access /dev/mem between %Lx->%Lx.\n",
49 current->comm, from, to);
60 * This funcion reads the *physical* memory. The f_pos points directly to the
63 static ssize_t read_mem(struct file *file, char __user *buf,
64 size_t count, loff_t *ppos)
66 unsigned long p = *ppos;
71 unsigned long remaining;
73 sz = size_inside_page(p, count);
75 if (!range_is_allowed(p >> PAGE_SHIFT, count))
79 if (IS_ERR(v) || v == NULL) {
81 * Some programs (e.g., dmidecode) groove off into
82 * weird RAM areas where no tables can possibly exist
83 * (because Xen will have stomped on them!). These
84 * programs get rather upset if we let them know that
85 * Xen failed their access, so we fake out a read of
88 if (clear_user(buf, count))
94 remaining = copy_to_user(buf, v, sz);
109 static ssize_t write_mem(struct file *file, const char __user *buf,
110 size_t count, loff_t *ppos)
112 unsigned long p = *ppos, ignored;
113 ssize_t written = 0, sz;
117 sz = size_inside_page(p, count);
119 if (!range_is_allowed(p >> PAGE_SHIFT, sz))
131 ignored = copy_from_user(v, buf, sz);
134 written += sz - ignored;
149 #ifndef ARCH_HAS_DEV_MEM_MMAP_MEM
150 static struct vm_operations_struct mmap_mem_ops = {
151 #ifdef CONFIG_HAVE_IOREMAP_PROT
152 .access = generic_access_phys
156 static int xen_mmap_mem(struct file *file, struct vm_area_struct *vma)
158 size_t size = vma->vm_end - vma->vm_start;
160 if (uncached_access(file))
161 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
163 if (!range_is_allowed(vma->vm_pgoff, size))
166 if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size,
170 vma->vm_ops = &mmap_mem_ops;
172 /* We want to return the real error code, not EAGAIN. */
173 return direct_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
174 size, vma->vm_page_prot, DOMID_IO);
179 * The memory devices use the full 32/64 bits of the offset, and so we cannot
180 * check against negative addresses: they are ok. The return value is weird,
181 * though, in that case (0).
183 * also note that seeking relative to the "end of file" isn't supported:
184 * it has no meaning, so it returns -EINVAL.
186 static loff_t memory_lseek(struct file *file, loff_t offset, int orig)
190 mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
193 offset += file->f_pos;
195 /* to avoid userland mistaking f_pos=-9 as -EBADF=-9 */
196 if ((unsigned long long)offset >= ~0xFFFULL) {
200 file->f_pos = offset;
202 force_successful_syscall_return();
207 mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
211 static int open_mem(struct inode * inode, struct file * filp)
213 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
216 const struct file_operations mem_fops = {
217 .llseek = memory_lseek,
220 .mmap = xen_mmap_mem,