at v2.6.15 126 lines 3.2 kB view raw
1/* 2 * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 */ 18 19#include <linux/config.h> 20#include <linux/init.h> 21#include <linux/mm.h> 22#include <linux/proc_fs.h> 23#include <linux/slab.h> 24#include <linux/kernel.h> 25 26#include <asm/vdso_datapage.h> 27#include <asm/rtas.h> 28#include <asm/uaccess.h> 29#include <asm/prom.h> 30 31static loff_t page_map_seek( struct file *file, loff_t off, int whence); 32static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes, 33 loff_t *ppos); 34static int page_map_mmap( struct file *file, struct vm_area_struct *vma ); 35 36static struct file_operations page_map_fops = { 37 .llseek = page_map_seek, 38 .read = page_map_read, 39 .mmap = page_map_mmap 40}; 41 42/* 43 * Create the ppc64 and ppc64/rtas directories early. This allows us to 44 * assume that they have been previously created in drivers. 45 */ 46static int __init proc_ppc64_create(void) 47{ 48 struct proc_dir_entry *root; 49 50 root = proc_mkdir("ppc64", NULL); 51 if (!root) 52 return 1; 53 54 if (!(platform_is_pseries() || _machine == PLATFORM_CELL)) 55 return 0; 56 57 if (!proc_mkdir("rtas", root)) 58 return 1; 59 60 if (!proc_symlink("rtas", NULL, "ppc64/rtas")) 61 return 1; 62 63 return 0; 64} 65core_initcall(proc_ppc64_create); 66 67static int __init proc_ppc64_init(void) 68{ 69 struct proc_dir_entry *pde; 70 71 pde = create_proc_entry("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL); 72 if (!pde) 73 return 1; 74 pde->nlink = 1; 75 pde->data = vdso_data; 76 pde->size = PAGE_SIZE; 77 pde->proc_fops = &page_map_fops; 78 79 return 0; 80} 81__initcall(proc_ppc64_init); 82 83static loff_t page_map_seek( struct file *file, loff_t off, int whence) 84{ 85 loff_t new; 86 struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); 87 88 switch(whence) { 89 case 0: 90 new = off; 91 break; 92 case 1: 93 new = file->f_pos + off; 94 break; 95 case 2: 96 new = dp->size + off; 97 break; 98 default: 99 return -EINVAL; 100 } 101 if ( new < 0 || new > dp->size ) 102 return -EINVAL; 103 return (file->f_pos = new); 104} 105 106static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes, 107 loff_t *ppos) 108{ 109 struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); 110 return simple_read_from_buffer(buf, nbytes, ppos, dp->data, dp->size); 111} 112 113static int page_map_mmap( struct file *file, struct vm_area_struct *vma ) 114{ 115 struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); 116 117 vma->vm_flags |= VM_SHM | VM_LOCKED; 118 119 if ((vma->vm_end - vma->vm_start) > dp->size) 120 return -EINVAL; 121 122 remap_pfn_range(vma, vma->vm_start, __pa(dp->data) >> PAGE_SHIFT, 123 dp->size, vma->vm_page_prot); 124 return 0; 125} 126