blob: 13452b32e2bd57e04f47792b1e26fbc5989c5d4e [file] [log] [blame]
Thomas Gleixner2874c5f2019-05-27 08:55:01 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/* 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)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 */
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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <linux/smp.h>
21#include <linux/seq_file.h>
22#include <linux/hugetlb.h>
23#include <linux/vmalloc.h>
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080024#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <asm/tlb.h>
26#include <asm/div64.h>
27#include "internal.h"
28
29/*
David Howells8feae132009-01-08 12:04:47 +000030 * display a single region to a sequenced file
Linus Torvalds1da177e2005-04-16 15:20:36 -070031 */
David Howells8feae132009-01-08 12:04:47 +000032static int nommu_region_show(struct seq_file *m, struct vm_region *region)
Linus Torvalds1da177e2005-04-16 15:20:36 -070033{
Linus Torvalds1da177e2005-04-16 15:20:36 -070034 unsigned long ino = 0;
35 struct file *file;
36 dev_t dev = 0;
Tetsuo Handa652586d2013-11-14 14:31:57 -080037 int flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
David Howells8feae132009-01-08 12:04:47 +000039 flags = region->vm_flags;
40 file = region->vm_file;
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42 if (file) {
Al Viro496ad9a2013-01-23 17:07:38 -050043 struct inode *inode = file_inode(region->vm_file);
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 dev = inode->i_sb->s_dev;
45 ino = inode->i_ino;
46 }
47
Tetsuo Handa652586d2013-11-14 14:31:57 -080048 seq_setwidth(m, 25 + sizeof(void *) * 6 - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070049 seq_printf(m,
Tetsuo Handa652586d2013-11-14 14:31:57 -080050 "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ",
David Howells8feae132009-01-08 12:04:47 +000051 region->vm_start,
52 region->vm_end,
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 flags & VM_READ ? 'r' : '-',
54 flags & VM_WRITE ? 'w' : '-',
55 flags & VM_EXEC ? 'x' : '-',
56 flags & VM_MAYSHARE ? flags & VM_SHARED ? 'S' : 's' : 'p',
David Howells8feae132009-01-08 12:04:47 +000057 ((loff_t)region->vm_pgoff) << PAGE_SHIFT,
Tetsuo Handa652586d2013-11-14 14:31:57 -080058 MAJOR(dev), MINOR(dev), ino);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60 if (file) {
Tetsuo Handa652586d2013-11-14 14:31:57 -080061 seq_pad(m, ' ');
Miklos Szeredi2726d562015-06-19 10:30:28 +020062 seq_file_path(m, file, "");
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 }
64
65 seq_putc(m, '\n');
66 return 0;
67}
68
David Howellsdbf86852006-09-27 01:50:19 -070069/*
David Howells8feae132009-01-08 12:04:47 +000070 * display a list of all the REGIONs the kernel knows about
Uwe Kleine-Koenig973c32b2009-01-12 23:35:47 +010071 * - nommu kernels have a single flat list
David Howellsdbf86852006-09-27 01:50:19 -070072 */
David Howells8feae132009-01-08 12:04:47 +000073static int nommu_region_list_show(struct seq_file *m, void *_p)
David Howellsdbf86852006-09-27 01:50:19 -070074{
David Howells8feae132009-01-08 12:04:47 +000075 struct rb_node *p = _p;
David Howellsdbf86852006-09-27 01:50:19 -070076
David Howells8feae132009-01-08 12:04:47 +000077 return nommu_region_show(m, rb_entry(p, struct vm_region, vm_rb));
David Howellsdbf86852006-09-27 01:50:19 -070078}
79
David Howells8feae132009-01-08 12:04:47 +000080static void *nommu_region_list_start(struct seq_file *m, loff_t *_pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -070081{
David Howells8feae132009-01-08 12:04:47 +000082 struct rb_node *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -070083 loff_t pos = *_pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -070084
David Howells8feae132009-01-08 12:04:47 +000085 down_read(&nommu_region_sem);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
David Howells8feae132009-01-08 12:04:47 +000087 for (p = rb_first(&nommu_region_tree); p; p = rb_next(p))
88 if (pos-- == 0)
89 return p;
90 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070091}
92
David Howells8feae132009-01-08 12:04:47 +000093static void nommu_region_list_stop(struct seq_file *m, void *v)
Linus Torvalds1da177e2005-04-16 15:20:36 -070094{
David Howells8feae132009-01-08 12:04:47 +000095 up_read(&nommu_region_sem);
Linus Torvalds1da177e2005-04-16 15:20:36 -070096}
97
David Howells8feae132009-01-08 12:04:47 +000098static void *nommu_region_list_next(struct seq_file *m, void *v, loff_t *pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -070099{
100 (*pos)++;
101 return rb_next((struct rb_node *) v);
102}
103
James Morris88e9d342009-09-22 16:43:43 -0700104static const struct seq_operations proc_nommu_region_list_seqop = {
David Howells8feae132009-01-08 12:04:47 +0000105 .start = nommu_region_list_start,
106 .next = nommu_region_list_next,
107 .stop = nommu_region_list_stop,
108 .show = nommu_region_list_show
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109};
110
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111static int __init proc_nommu_init(void)
112{
Christoph Hellwigfddda2b2018-04-13 19:44:18 +0200113 proc_create_seq("maps", S_IRUGO, NULL, &proc_nommu_region_list_seqop);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 return 0;
115}
116
Paul Gortmakerabaf3782014-01-23 15:55:45 -0800117fs_initcall(proc_nommu_init);