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 mmaping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com>
11 #include <linux/config.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>
29 #include <asm/hypervisor.h>
31 static inline int uncached_access(struct file *file)
33 if (file->f_flags & O_SYNC)
35 /* Xen sets correct MTRR type on non-RAM for us. */
40 * This funcion reads the *physical* memory. The f_pos points directly to the
43 static ssize_t read_mem(struct file * file, char __user * buf,
44 size_t count, loff_t *ppos)
46 unsigned long p = *ppos, ignored;
52 * Handle first page in case it's not aligned
54 if (-p & (PAGE_SIZE - 1))
55 sz = -p & (PAGE_SIZE - 1);
59 sz = min_t(unsigned long, sz, count);
61 if ((v = ioremap(p, sz)) == NULL) {
63 * Some programs (e.g., dmidecode) groove off into weird RAM
64 * areas where no tables can possibly exist (because Xen will
65 * have stomped on them!). These programs get rather upset if
66 * we let them know that Xen failed their access, so we fake
67 * out a read of all zeroes. :-)
69 if (clear_user(buf, count))
75 ignored = copy_to_user(buf, v, sz);
89 static ssize_t write_mem(struct file * file, const char __user * buf,
90 size_t count, loff_t *ppos)
92 unsigned long p = *ppos, ignored;
93 ssize_t written = 0, sz;
98 * Handle first page in case it's not aligned
100 if (-p & (PAGE_SIZE - 1))
101 sz = -p & (PAGE_SIZE - 1);
105 sz = min_t(unsigned long, sz, count);
107 if ((v = ioremap(p, sz)) == NULL)
110 ignored = copy_from_user(v, buf, sz);
113 written += sz - ignored;
128 static int mmap_mem(struct file * file, struct vm_area_struct * vma)
130 size_t size = vma->vm_end - vma->vm_start;
132 if (uncached_access(file))
133 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
135 /* We want to return the real error code, not EAGAIN. */
136 return direct_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
137 size, vma->vm_page_prot, DOMID_IO);
141 * The memory devices use the full 32/64 bits of the offset, and so we cannot
142 * check against negative addresses: they are ok. The return value is weird,
143 * though, in that case (0).
145 * also note that seeking relative to the "end of file" isn't supported:
146 * it has no meaning, so it returns -EINVAL.
148 static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
152 mutex_lock(&file->f_dentry->d_inode->i_mutex);
155 file->f_pos = offset;
157 force_successful_syscall_return();
160 file->f_pos += offset;
162 force_successful_syscall_return();
167 mutex_unlock(&file->f_dentry->d_inode->i_mutex);
171 static int open_mem(struct inode * inode, struct file * filp)
173 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
176 struct file_operations mem_fops = {
177 .llseek = memory_lseek,