initial import
[ps3linux_kernel_patches_41.git] / 0130-ps3physmem.patch
blobce89f5a705a3a3f02d9b0bc50ec06c01b038177c
1 --- a/drivers/char/Makefile 2014-10-28 15:37:31.132151654 +0100
2 +++ b/drivers/char/Makefile 2014-10-28 15:37:44.898819121 +0100
3 @@ -62,3 +62,5 @@
5 obj-$(CONFIG_TILE_SROM) += tile-srom.o
6 obj-$(CONFIG_XILLYBUS) += xillybus/
8 +obj-$(CONFIG_PS3_PHYSMEM) += ps3physmem.o
9 --- a/arch/powerpc/platforms/ps3/Kconfig 2012-02-04 21:13:42.539806178 +0100
10 +++ b/arch/powerpc/platforms/ps3/Kconfig 2012-02-05 17:54:38.698430717 +0100
11 @@ -179,6 +179,12 @@
12 profiling support of the Cell processor with programs like
13 oprofile and perfmon2, then say Y or M, otherwise say N.
15 +config PS3_PHYSMEM
16 + tristate "PS3 Physical Memory Driver"
17 + depends on PPC_PS3
18 + help
19 + This driver allows you direct access to the PS3 physical memory.
21 config PS3GELIC_UDBG
22 bool "PS3 udbg output via UDP broadcasts on Ethernet"
23 depends on PPC_PS3
24 --- /dev/null 2014-05-18 16:58:36.900768386 +0200
25 +++ b/drivers/char/ps3physmem.c 2014-05-19 00:35:46.782364178 +0200
26 @@ -0,0 +1,217 @@
27 +/*
28 + * PS3 Physical Memory Driver
29 + *
30 + * Copyright (C) 2011 graf_chokolo <grafchokolo@gmail.com>
31 + * Copyright (C) 2011, 2012 glevand <geoffrey.levand@mail.ru>
32 + * All rights reserved.
33 + *
34 + * This program is free software; you can redistribute it and/or modify it
35 + * under the terms of the GNU General Public License as published
36 + * by the Free Software Foundation; version 2 of the License.
37 + *
38 + * This program is distributed in the hope that it will be useful, but
39 + * WITHOUT ANY WARRANTY; without even the implied warranty of
40 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41 + * General Public License for more details.
42 + *
43 + * You should have received a copy of the GNU General Public License along
44 + * with this program; if not, write to the Free Software Foundation, Inc.,
45 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
46 + */
48 +#include <linux/module.h>
49 +#include <linux/kernel.h>
50 +#include <linux/version.h>
51 +#include <linux/init.h>
52 +#include <linux/mm.h>
53 +#include <linux/fs.h>
54 +#include <linux/uaccess.h>
55 +#include <linux/miscdevice.h>
57 +#include <asm/io.h>
58 +#include <asm/ps3.h>
59 +#include <asm/lv1call.h>
61 +static unsigned long ps3physmem_start = 0;
62 +module_param(ps3physmem_start, ulong, 0);
64 +static unsigned long ps3physmem_size = 256 * 1024 * 1024;
65 +module_param(ps3physmem_size, ulong, 0);
67 +static unsigned long ps3physmem_pagesize = 24; /* 16MB */
68 +module_param(ps3physmem_pagesize, ulong, 0);
70 +static u64 ps3physmem_lpar;
71 +static char *ps3physmem_virt;
73 +static ssize_t ps3physmem_read(struct file *file, char __user *usrbuf,
74 + size_t count, loff_t *pos)
76 + if (*pos + count > ps3physmem_size)
77 + count = ps3physmem_size - *pos;
79 + if (!count)
80 + return (0);
82 + if (copy_to_user(usrbuf, ps3physmem_virt + *pos, count))
83 + return (-EFAULT);
85 + *pos += count;
87 + return (count);
90 +static ssize_t ps3physmem_write(struct file *file, const char __user *usrbuf,
91 + size_t count, loff_t *pos)
93 + if (*pos + count > ps3physmem_size)
94 + count = ps3physmem_size - *pos;
96 + if (!count)
97 + return (0);
99 + if (copy_from_user(ps3physmem_virt + *pos, usrbuf, count))
100 + return (-EFAULT);
102 + *pos += count;
104 + return (count);
107 +static loff_t ps3physmem_llseek(struct file *file, loff_t off, int whence)
109 + loff_t newpos;
111 + switch(whence) {
112 + case 0: /* SEEK_SET */
113 + newpos = off;
114 + break;
115 + case 1: /* SEEK_CUR */
116 + newpos = file->f_pos + off;
117 + break;
118 + case 2: /* SEEK_END */
119 + newpos = ps3physmem_size + off;
120 + break;
121 + default: /* can't happen */
122 + return (-EINVAL);
125 + if (newpos < 0)
126 + return (-EINVAL);
128 + file->f_pos = newpos;
130 + return (newpos);
133 +static void ps3physmem_vma_open(struct vm_area_struct *vma)
137 +static void ps3physmem_vma_close(struct vm_area_struct *vma)
141 +static struct vm_operations_struct ps3physmem_vm_ops = {
142 + .open = ps3physmem_vma_open,
143 + .close = ps3physmem_vma_close,
146 +static int ps3physmem_mmap(struct file *file, struct vm_area_struct *vma)
148 + unsigned long size, pfn;
149 + int res;
151 + size = vma->vm_end - vma->vm_start;
153 + if (((vma->vm_pgoff << PAGE_SHIFT) + size) > ps3physmem_size)
154 + return (-EINVAL);
156 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
157 + vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP | VM_IO;
158 +#else
159 + vma->vm_flags |= VM_RESERVED | VM_IO;
160 +#endif
161 + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
163 + pfn = (ps3physmem_lpar >> PAGE_SHIFT) + vma->vm_pgoff;
165 + res = io_remap_pfn_range(vma, vma->vm_start, pfn, size,
166 + vma->vm_page_prot);
167 + if (res)
168 + return (res);
170 + vma->vm_ops = &ps3physmem_vm_ops;
172 + ps3physmem_vma_open(vma);
174 + return (0);
177 +static const struct file_operations ps3physmem_fops = {
178 + .owner = THIS_MODULE,
179 + .read = ps3physmem_read,
180 + .write = ps3physmem_write,
181 + .llseek = ps3physmem_llseek,
182 + .mmap = ps3physmem_mmap,
185 +static struct miscdevice ps3physmem_misc = {
186 + .minor = MISC_DYNAMIC_MINOR,
187 + .name = "ps3physmem",
188 + .fops = &ps3physmem_fops,
191 +static int __init ps3physmem_init(void)
193 + int res;
195 + res = lv1_undocumented_function_114(ps3physmem_start,
196 + ps3physmem_pagesize, ps3physmem_size, &ps3physmem_lpar);
197 + if (res) {
198 + pr_info("%s:%u: lv1_undocumented_function_114 failed %d\n",
199 + __func__, __LINE__, res);
200 + return (-ENXIO);
203 + ps3physmem_virt = ioremap_nocache(ps3physmem_lpar, ps3physmem_size);
204 + if (!ps3physmem_virt) {
205 + pr_info("%s:%u: ioremap_nocache failed\n", __func__, __LINE__);
206 + goto destroy_lpar;
209 + res = misc_register(&ps3physmem_misc);
210 + if (res) {
211 + pr_info("%s:%u: misc_register failed %d\n",
212 + __func__, __LINE__, res);
213 + goto unmap_lpar;
216 + return (0);
218 +unmap_lpar:
220 + iounmap((void *) ps3physmem_virt);
222 +destroy_lpar:
224 + lv1_undocumented_function_115(ps3physmem_lpar);
226 + return (res);
229 +static void __exit ps3physmem_exit(void)
231 + misc_deregister(&ps3physmem_misc);
233 + iounmap((void *) ps3physmem_virt);
235 + lv1_undocumented_function_115(ps3physmem_lpar);
238 +module_init(ps3physmem_init);
239 +module_exit(ps3physmem_exit);
241 +MODULE_AUTHOR("glevand");
242 +MODULE_DESCRIPTION("PS3 Physical Memory Driver");
243 +MODULE_LICENSE("GPL");