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 */ 31static 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_path(m, file_user_path(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 */ 72static 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 79static 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 92static void nommu_region_list_stop(struct seq_file *m, void *v) 93{ 94 up_read(&nommu_region_sem); 95} 96 97static 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 103static 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 110static 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 116fs_initcall(proc_nommu_init); 117