1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* nommu.c: mmu-less memory info files 3 * 4 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8 #include <linux/init.h> 9 #include <linux/module.h> 10 #include <linux/errno.h> 11 #include <linux/time.h> 12 #include <linux/kernel.h> 13 #include <linux/string.h> 14 #include <linux/mman.h> 15 #include <linux/proc_fs.h> 16 #include <linux/mm.h> 17 #include <linux/mmzone.h> 18 #include <linux/pagemap.h> 19 #include <linux/swap.h> 20 #include <linux/smp.h> 21 #include <linux/seq_file.h> 22 #include <linux/hugetlb.h> 23 #include <linux/vmalloc.h> 24 #include <asm/tlb.h> 25 #include <asm/div64.h> 26 #include "internal.h" 27 28 /* 29 * display a single region to a sequenced file 30 */ 31 static int nommu_region_show(struct seq_file *m, struct vm_region *region) 32 { 33 unsigned long ino = 0; 34 struct file *file; 35 dev_t dev = 0; 36 int flags; 37 38 flags = region->vm_flags; 39 file = region->vm_file; 40 41 if (file) { 42 struct inode *inode = file_inode(region->vm_file); 43 dev = inode->i_sb->s_dev; 44 ino = inode->i_ino; 45 } 46 47 seq_setwidth(m, 25 + sizeof(void *) * 6 - 1); 48 seq_printf(m, 49 "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ", 50 region->vm_start, 51 region->vm_end, 52 flags & VM_READ ? 'r' : '-', 53 flags & VM_WRITE ? 'w' : '-', 54 flags & VM_EXEC ? 'x' : '-', 55 flags & VM_MAYSHARE ? flags & VM_SHARED ? 'S' : 's' : 'p', 56 ((loff_t)region->vm_pgoff) << PAGE_SHIFT, 57 MAJOR(dev), MINOR(dev), ino); 58 59 if (file) { 60 seq_pad(m, ' '); 61 seq_file_path(m, file, ""); 62 } 63 64 seq_putc(m, '\n'); 65 return 0; 66 } 67 68 /* 69 * display a list of all the REGIONs the kernel knows about 70 * - nommu kernels have a single flat list 71 */ 72 static int nommu_region_list_show(struct seq_file *m, void *_p) 73 { 74 struct rb_node *p = _p; 75 76 return nommu_region_show(m, rb_entry(p, struct vm_region, vm_rb)); 77 } 78 79 static void *nommu_region_list_start(struct seq_file *m, loff_t *_pos) 80 { 81 struct rb_node *p; 82 loff_t pos = *_pos; 83 84 down_read(&nommu_region_sem); 85 86 for (p = rb_first(&nommu_region_tree); p; p = rb_next(p)) 87 if (pos-- == 0) 88 return p; 89 return NULL; 90 } 91 92 static void nommu_region_list_stop(struct seq_file *m, void *v) 93 { 94 up_read(&nommu_region_sem); 95 } 96 97 static void *nommu_region_list_next(struct seq_file *m, void *v, loff_t *pos) 98 { 99 (*pos)++; 100 return rb_next((struct rb_node *) v); 101 } 102 103 static const struct seq_operations proc_nommu_region_list_seqop = { 104 .start = nommu_region_list_start, 105 .next = nommu_region_list_next, 106 .stop = nommu_region_list_stop, 107 .show = nommu_region_list_show 108 }; 109 110 static int __init proc_nommu_init(void) 111 { 112 proc_create_seq("maps", S_IRUGO, NULL, &proc_nommu_region_list_seqop); 113 return 0; 114 } 115 116 fs_initcall(proc_nommu_init); 117