procfs_map.c revision 77031
116468Sdyson/* 216468Sdyson * Copyright (c) 1993 Jan-Simon Pendry 316468Sdyson * Copyright (c) 1993 416468Sdyson * The Regents of the University of California. All rights reserved. 516468Sdyson * 616468Sdyson * This code is derived from software contributed to Berkeley by 716468Sdyson * Jan-Simon Pendry. 816468Sdyson * 916468Sdyson * Redistribution and use in source and binary forms, with or without 1016468Sdyson * modification, are permitted provided that the following conditions 1116468Sdyson * are met: 1216468Sdyson * 1. Redistributions of source code must retain the above copyright 1316468Sdyson * notice, this list of conditions and the following disclaimer. 1416468Sdyson * 2. Redistributions in binary form must reproduce the above copyright 1516468Sdyson * notice, this list of conditions and the following disclaimer in the 1616468Sdyson * documentation and/or other materials provided with the distribution. 1716468Sdyson * 3. All advertising materials mentioning features or use of this software 1816468Sdyson * must display the following acknowledgement: 1916468Sdyson * This product includes software developed by the University of 2016468Sdyson * California, Berkeley and its contributors. 2116468Sdyson * 4. Neither the name of the University nor the names of its contributors 2216468Sdyson * may be used to endorse or promote products derived from this software 2316468Sdyson * without specific prior written permission. 2416468Sdyson * 2516468Sdyson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2616468Sdyson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2716468Sdyson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2816468Sdyson * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2916468Sdyson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3016468Sdyson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3116468Sdyson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3216468Sdyson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3316468Sdyson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3416468Sdyson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3516468Sdyson * SUCH DAMAGE. 3616468Sdyson * 3716468Sdyson * @(#)procfs_status.c 8.3 (Berkeley) 2/17/94 3816468Sdyson * 3950477Speter * $FreeBSD: head/sys/fs/procfs/procfs_map.c 77031 2001-05-23 09:42:29Z ru $ 4016468Sdyson */ 4116468Sdyson 4216468Sdyson#include <sys/param.h> 4316468Sdyson#include <sys/systm.h> 4476166Smarkm#include <sys/lock.h> 4576827Salfred#include <sys/mutex.h> 4616468Sdyson#include <sys/proc.h> 4716468Sdyson#include <sys/vnode.h> 4876166Smarkm 4977031Sru#include <fs/procfs/procfs.h> 5016468Sdyson 5116468Sdyson#include <vm/vm.h> 5216468Sdyson#include <vm/pmap.h> 5316468Sdyson#include <vm/vm_map.h> 5416468Sdyson#include <vm/vm_page.h> 5516468Sdyson#include <vm/vm_object.h> 5616468Sdyson 5716468Sdyson 5819260Sdyson#define MEBUFFERSIZE 256 5916468Sdyson 6019260Sdyson/* 6119260Sdyson * The map entries can *almost* be read with programs like cat. However, 6219260Sdyson * large maps need special programs to read. It is not easy to implement 6319260Sdyson * a program that can sense the required size of the buffer, and then 6419260Sdyson * subsequently do a read with the appropriate size. This operation cannot 6519260Sdyson * be atomic. The best that we can do is to allow the program to do a read 6619260Sdyson * with an arbitrarily large buffer, and return as much as we can. We can 6719260Sdyson * return an error code if the buffer is too small (EFBIG), then the program 6819260Sdyson * can try a bigger buffer. 6919260Sdyson */ 7016468Sdysonint 7116468Sdysonprocfs_domap(curp, p, pfs, uio) 7216468Sdyson struct proc *curp; 7316468Sdyson struct proc *p; 7416468Sdyson struct pfsnode *pfs; 7516468Sdyson struct uio *uio; 7616468Sdyson{ 7716468Sdyson int len; 7816468Sdyson int error; 7916468Sdyson vm_map_t map = &p->p_vmspace->vm_map; 8044146Sluoqi pmap_t pmap = vmspace_pmap(p->p_vmspace); 8116468Sdyson vm_map_entry_t entry; 8219260Sdyson char mebuffer[MEBUFFERSIZE]; 8316468Sdyson 8416468Sdyson if (uio->uio_rw != UIO_READ) 8516468Sdyson return (EOPNOTSUPP); 8616468Sdyson 8716468Sdyson if (uio->uio_offset != 0) 8816468Sdyson return (0); 8916468Sdyson 9019260Sdyson error = 0; 9119261Sdyson if (map != &curproc->p_vmspace->vm_map) 9231174Stegge vm_map_lock_read(map); 9319260Sdyson for (entry = map->header.next; 9419260Sdyson ((uio->uio_resid > 0) && (entry != &map->header)); 9516468Sdyson entry = entry->next) { 9616468Sdyson vm_object_t obj, tobj, lobj; 9742957Sdillon int ref_count, shadow_count, flags; 9816468Sdyson vm_offset_t addr; 9916468Sdyson int resident, privateresident; 10016468Sdyson char *type; 10116468Sdyson 10243748Sdillon if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) 10316468Sdyson continue; 10416468Sdyson 10516468Sdyson obj = entry->object.vm_object; 10632286Sdyson if (obj && (obj->shadow_count == 1)) 10716468Sdyson privateresident = obj->resident_page_count; 10816468Sdyson else 10916468Sdyson privateresident = 0; 11016468Sdyson 11116468Sdyson resident = 0; 11216468Sdyson addr = entry->start; 11316468Sdyson while (addr < entry->end) { 11416468Sdyson if (pmap_extract( pmap, addr)) 11516468Sdyson resident++; 11616468Sdyson addr += PAGE_SIZE; 11716468Sdyson } 11816468Sdyson 11916468Sdyson for( lobj = tobj = obj; tobj; tobj = tobj->backing_object) 12016468Sdyson lobj = tobj; 12116468Sdyson 12235497Sdyson if (lobj) { 12335497Sdyson switch(lobj->type) { 12416468Sdyson 12516468Sdysondefault: 12616468Sdysoncase OBJT_DEFAULT: 12735497Sdyson type = "default"; 12835497Sdyson break; 12916468Sdysoncase OBJT_VNODE: 13035497Sdyson type = "vnode"; 13135497Sdyson break; 13216468Sdysoncase OBJT_SWAP: 13335497Sdyson type = "swap"; 13435497Sdyson break; 13516468Sdysoncase OBJT_DEVICE: 13635497Sdyson type = "device"; 13735497Sdyson break; 13835497Sdyson } 13935497Sdyson 14035497Sdyson flags = obj->flags; 14135497Sdyson ref_count = obj->ref_count; 14235497Sdyson shadow_count = obj->shadow_count; 14317303Sdyson } else { 14417303Sdyson type = "none"; 14535497Sdyson flags = 0; 14635497Sdyson ref_count = 0; 14735497Sdyson shadow_count = 0; 14816468Sdyson } 14917303Sdyson 15016468Sdyson 15116468Sdyson /* 15216468Sdyson * format: 15316468Sdyson * start, end, resident, private resident, cow, access, type. 15416468Sdyson */ 15541514Sarchie snprintf(mebuffer, sizeof(mebuffer), 15643634Sjdp "0x%lx 0x%lx %d %d %p %s%s%s %d %d 0x%x %s %s %s\n", 15743634Sjdp (u_long)entry->start, (u_long)entry->end, 15842957Sdillon resident, privateresident, obj, 15917306Sdyson (entry->protection & VM_PROT_READ)?"r":"-", 16017306Sdyson (entry->protection & VM_PROT_WRITE)?"w":"-", 16117306Sdyson (entry->protection & VM_PROT_EXECUTE)?"x":"-", 16235497Sdyson ref_count, shadow_count, flags, 16335497Sdyson (entry->eflags & MAP_ENTRY_COW)?"COW":"NCOW", 16435497Sdyson (entry->eflags & MAP_ENTRY_NEEDS_COPY)?"NC":"NNC", 16516468Sdyson type); 16616468Sdyson 16716468Sdyson len = strlen(mebuffer); 16819260Sdyson if (len > uio->uio_resid) { 16919260Sdyson error = EFBIG; 17019260Sdyson break; 17116468Sdyson } 17219260Sdyson error = uiomove(mebuffer, len, uio); 17319260Sdyson if (error) 17419260Sdyson break; 17516468Sdyson } 17619261Sdyson if (map != &curproc->p_vmspace->vm_map) 17731174Stegge vm_map_unlock_read(map); 17816468Sdyson return error; 17916468Sdyson} 18016474Sdyson 18116474Sdysonint 18216474Sdysonprocfs_validmap(p) 18316474Sdyson struct proc *p; 18416474Sdyson{ 18516474Sdyson return ((p->p_flag & P_SYSTEM) == 0); 18616474Sdyson} 187