11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2188917e1SBenjamin Herrenschmidt /* 3188917e1SBenjamin Herrenschmidt * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation 4188917e1SBenjamin Herrenschmidt */ 5188917e1SBenjamin Herrenschmidt 6188917e1SBenjamin Herrenschmidt #include <linux/init.h> 7188917e1SBenjamin Herrenschmidt #include <linux/mm.h> 8188917e1SBenjamin Herrenschmidt #include <linux/proc_fs.h> 9188917e1SBenjamin Herrenschmidt #include <linux/kernel.h> 10188917e1SBenjamin Herrenschmidt 11188917e1SBenjamin Herrenschmidt #include <asm/machdep.h> 12188917e1SBenjamin Herrenschmidt #include <asm/vdso_datapage.h> 13188917e1SBenjamin Herrenschmidt #include <asm/rtas.h> 147c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 15188917e1SBenjamin Herrenschmidt #include <asm/prom.h> 16188917e1SBenjamin Herrenschmidt 17188917e1SBenjamin Herrenschmidt #ifdef CONFIG_PPC64 18188917e1SBenjamin Herrenschmidt 19188917e1SBenjamin Herrenschmidt static loff_t page_map_seek(struct file *file, loff_t off, int whence) 20188917e1SBenjamin Herrenschmidt { 21b33159b7SAl Viro return fixed_size_llseek(file, off, whence, PAGE_SIZE); 22188917e1SBenjamin Herrenschmidt } 23188917e1SBenjamin Herrenschmidt 24188917e1SBenjamin Herrenschmidt static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes, 25188917e1SBenjamin Herrenschmidt loff_t *ppos) 26188917e1SBenjamin Herrenschmidt { 27d9dda78bSAl Viro return simple_read_from_buffer(buf, nbytes, ppos, 28*359745d7SMuchun Song pde_data(file_inode(file)), PAGE_SIZE); 29188917e1SBenjamin Herrenschmidt } 30188917e1SBenjamin Herrenschmidt 31188917e1SBenjamin Herrenschmidt static int page_map_mmap( struct file *file, struct vm_area_struct *vma ) 32188917e1SBenjamin Herrenschmidt { 33d9dda78bSAl Viro if ((vma->vm_end - vma->vm_start) > PAGE_SIZE) 34188917e1SBenjamin Herrenschmidt return -EINVAL; 35188917e1SBenjamin Herrenschmidt 36d9dda78bSAl Viro remap_pfn_range(vma, vma->vm_start, 37*359745d7SMuchun Song __pa(pde_data(file_inode(file))) >> PAGE_SHIFT, 38d9dda78bSAl Viro PAGE_SIZE, vma->vm_page_prot); 39188917e1SBenjamin Herrenschmidt return 0; 40188917e1SBenjamin Herrenschmidt } 41188917e1SBenjamin Herrenschmidt 4297a32539SAlexey Dobriyan static const struct proc_ops page_map_proc_ops = { 4397a32539SAlexey Dobriyan .proc_lseek = page_map_seek, 4497a32539SAlexey Dobriyan .proc_read = page_map_read, 4597a32539SAlexey Dobriyan .proc_mmap = page_map_mmap, 46188917e1SBenjamin Herrenschmidt }; 47188917e1SBenjamin Herrenschmidt 48188917e1SBenjamin Herrenschmidt 49188917e1SBenjamin Herrenschmidt static int __init proc_ppc64_init(void) 50188917e1SBenjamin Herrenschmidt { 51188917e1SBenjamin Herrenschmidt struct proc_dir_entry *pde; 52188917e1SBenjamin Herrenschmidt 5357ad583fSRussell Currey pde = proc_create_data("powerpc/systemcfg", S_IFREG | 0444, NULL, 5497a32539SAlexey Dobriyan &page_map_proc_ops, vdso_data); 55188917e1SBenjamin Herrenschmidt if (!pde) 56188917e1SBenjamin Herrenschmidt return 1; 57271a15eaSDavid Howells proc_set_size(pde, PAGE_SIZE); 58188917e1SBenjamin Herrenschmidt 59188917e1SBenjamin Herrenschmidt return 0; 60188917e1SBenjamin Herrenschmidt } 61188917e1SBenjamin Herrenschmidt __initcall(proc_ppc64_init); 62188917e1SBenjamin Herrenschmidt 63188917e1SBenjamin Herrenschmidt #endif /* CONFIG_PPC64 */ 64188917e1SBenjamin Herrenschmidt 65188917e1SBenjamin Herrenschmidt /* 66188917e1SBenjamin Herrenschmidt * Create the ppc64 and ppc64/rtas directories early. This allows us to 67188917e1SBenjamin Herrenschmidt * assume that they have been previously created in drivers. 68188917e1SBenjamin Herrenschmidt */ 69188917e1SBenjamin Herrenschmidt static int __init proc_ppc64_create(void) 70188917e1SBenjamin Herrenschmidt { 71188917e1SBenjamin Herrenschmidt struct proc_dir_entry *root; 72188917e1SBenjamin Herrenschmidt 73188917e1SBenjamin Herrenschmidt root = proc_mkdir("powerpc", NULL); 74188917e1SBenjamin Herrenschmidt if (!root) 75188917e1SBenjamin Herrenschmidt return 1; 76188917e1SBenjamin Herrenschmidt 77188917e1SBenjamin Herrenschmidt #ifdef CONFIG_PPC64 78188917e1SBenjamin Herrenschmidt if (!proc_symlink("ppc64", NULL, "powerpc")) 79188917e1SBenjamin Herrenschmidt pr_err("Failed to create link /proc/ppc64 -> /proc/powerpc\n"); 80188917e1SBenjamin Herrenschmidt #endif 81188917e1SBenjamin Herrenschmidt 82188917e1SBenjamin Herrenschmidt if (!of_find_node_by_path("/rtas")) 83188917e1SBenjamin Herrenschmidt return 0; 84188917e1SBenjamin Herrenschmidt 85188917e1SBenjamin Herrenschmidt if (!proc_mkdir("rtas", root)) 86188917e1SBenjamin Herrenschmidt return 1; 87188917e1SBenjamin Herrenschmidt 88188917e1SBenjamin Herrenschmidt if (!proc_symlink("rtas", NULL, "powerpc/rtas")) 89188917e1SBenjamin Herrenschmidt return 1; 90188917e1SBenjamin Herrenschmidt 91188917e1SBenjamin Herrenschmidt return 0; 92188917e1SBenjamin Herrenschmidt } 93188917e1SBenjamin Herrenschmidt core_initcall(proc_ppc64_create); 94