162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* nommu.c: mmu-less memory info files 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 562306a36Sopenharmony_ci * Written by David Howells (dhowells@redhat.com) 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/init.h> 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <linux/errno.h> 1162306a36Sopenharmony_ci#include <linux/time.h> 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/string.h> 1462306a36Sopenharmony_ci#include <linux/mman.h> 1562306a36Sopenharmony_ci#include <linux/proc_fs.h> 1662306a36Sopenharmony_ci#include <linux/mm.h> 1762306a36Sopenharmony_ci#include <linux/mmzone.h> 1862306a36Sopenharmony_ci#include <linux/pagemap.h> 1962306a36Sopenharmony_ci#include <linux/swap.h> 2062306a36Sopenharmony_ci#include <linux/smp.h> 2162306a36Sopenharmony_ci#include <linux/seq_file.h> 2262306a36Sopenharmony_ci#include <linux/hugetlb.h> 2362306a36Sopenharmony_ci#include <linux/vmalloc.h> 2462306a36Sopenharmony_ci#include <asm/tlb.h> 2562306a36Sopenharmony_ci#include <asm/div64.h> 2662306a36Sopenharmony_ci#include "internal.h" 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/* 2962306a36Sopenharmony_ci * display a single region to a sequenced file 3062306a36Sopenharmony_ci */ 3162306a36Sopenharmony_cistatic int nommu_region_show(struct seq_file *m, struct vm_region *region) 3262306a36Sopenharmony_ci{ 3362306a36Sopenharmony_ci unsigned long ino = 0; 3462306a36Sopenharmony_ci struct file *file; 3562306a36Sopenharmony_ci dev_t dev = 0; 3662306a36Sopenharmony_ci int flags; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci flags = region->vm_flags; 3962306a36Sopenharmony_ci file = region->vm_file; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci if (file) { 4262306a36Sopenharmony_ci struct inode *inode = file_inode(region->vm_file); 4362306a36Sopenharmony_ci dev = inode->i_sb->s_dev; 4462306a36Sopenharmony_ci ino = inode->i_ino; 4562306a36Sopenharmony_ci } 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci seq_setwidth(m, 25 + sizeof(void *) * 6 - 1); 4862306a36Sopenharmony_ci seq_printf(m, 4962306a36Sopenharmony_ci "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ", 5062306a36Sopenharmony_ci region->vm_start, 5162306a36Sopenharmony_ci region->vm_end, 5262306a36Sopenharmony_ci flags & VM_READ ? 'r' : '-', 5362306a36Sopenharmony_ci flags & VM_WRITE ? 'w' : '-', 5462306a36Sopenharmony_ci flags & VM_EXEC ? 'x' : '-', 5562306a36Sopenharmony_ci flags & VM_MAYSHARE ? flags & VM_SHARED ? 'S' : 's' : 'p', 5662306a36Sopenharmony_ci ((loff_t)region->vm_pgoff) << PAGE_SHIFT, 5762306a36Sopenharmony_ci MAJOR(dev), MINOR(dev), ino); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci if (file) { 6062306a36Sopenharmony_ci seq_pad(m, ' '); 6162306a36Sopenharmony_ci seq_file_path(m, file, ""); 6262306a36Sopenharmony_ci } 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci seq_putc(m, '\n'); 6562306a36Sopenharmony_ci return 0; 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* 6962306a36Sopenharmony_ci * display a list of all the REGIONs the kernel knows about 7062306a36Sopenharmony_ci * - nommu kernels have a single flat list 7162306a36Sopenharmony_ci */ 7262306a36Sopenharmony_cistatic int nommu_region_list_show(struct seq_file *m, void *_p) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci struct rb_node *p = _p; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci return nommu_region_show(m, rb_entry(p, struct vm_region, vm_rb)); 7762306a36Sopenharmony_ci} 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic void *nommu_region_list_start(struct seq_file *m, loff_t *_pos) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci struct rb_node *p; 8262306a36Sopenharmony_ci loff_t pos = *_pos; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci down_read(&nommu_region_sem); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci for (p = rb_first(&nommu_region_tree); p; p = rb_next(p)) 8762306a36Sopenharmony_ci if (pos-- == 0) 8862306a36Sopenharmony_ci return p; 8962306a36Sopenharmony_ci return NULL; 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic void nommu_region_list_stop(struct seq_file *m, void *v) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci up_read(&nommu_region_sem); 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic void *nommu_region_list_next(struct seq_file *m, void *v, loff_t *pos) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci (*pos)++; 10062306a36Sopenharmony_ci return rb_next((struct rb_node *) v); 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic const struct seq_operations proc_nommu_region_list_seqop = { 10462306a36Sopenharmony_ci .start = nommu_region_list_start, 10562306a36Sopenharmony_ci .next = nommu_region_list_next, 10662306a36Sopenharmony_ci .stop = nommu_region_list_stop, 10762306a36Sopenharmony_ci .show = nommu_region_list_show 10862306a36Sopenharmony_ci}; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic int __init proc_nommu_init(void) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci proc_create_seq("maps", S_IRUGO, NULL, &proc_nommu_region_list_seqop); 11362306a36Sopenharmony_ci return 0; 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cifs_initcall(proc_nommu_init); 117