Home | History | Annotate | Line # | Download | only in procfs
procfs_subr.c revision 1.3.2.1
      1      1.1       pk /*
      2      1.2       pk  * Copyright (c) 1993 Paul Kranenburg
      3      1.2       pk  * All rights reserved.
      4      1.2       pk  *
      5      1.2       pk  * Redistribution and use in source and binary forms, with or without
      6      1.2       pk  * modification, are permitted provided that the following conditions
      7      1.2       pk  * are met:
      8      1.2       pk  * 1. Redistributions of source code must retain the above copyright
      9      1.2       pk  *    notice, this list of conditions and the following disclaimer.
     10      1.2       pk  * 2. Redistributions in binary form must reproduce the above copyright
     11      1.2       pk  *    notice, this list of conditions and the following disclaimer in the
     12      1.2       pk  *    documentation and/or other materials provided with the distribution.
     13      1.2       pk  * 3. All advertising materials mentioning features or use of this software
     14      1.2       pk  *    must display the following acknowledgement:
     15      1.3       pk  *      This product includes software developed by Paul Kranenburg.
     16      1.2       pk  * 4. The name of the author may not be used to endorse or promote products
     17      1.2       pk  *    derived from this software withough specific prior written permission
     18      1.2       pk  *
     19      1.2       pk  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20      1.2       pk  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21      1.2       pk  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22      1.2       pk  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23      1.2       pk  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24      1.2       pk  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25      1.2       pk  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26      1.2       pk  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27      1.2       pk  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28      1.2       pk  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29      1.2       pk  *
     30  1.3.2.1  mycroft  *	$Id: procfs_subr.c,v 1.3.2.1 1993/11/14 22:35:01 mycroft Exp $
     31      1.1       pk  */
     32      1.1       pk 
     33  1.3.2.1  mycroft #include <sys/param.h>
     34  1.3.2.1  mycroft #include <sys/systm.h>
     35  1.3.2.1  mycroft #include <sys/time.h>
     36  1.3.2.1  mycroft #include <sys/kernel.h>
     37  1.3.2.1  mycroft #include <sys/ioctl.h>
     38  1.3.2.1  mycroft #include <sys/proc.h>
     39  1.3.2.1  mycroft #include <sys/buf.h>
     40  1.3.2.1  mycroft #include <sys/vnode.h>
     41  1.3.2.1  mycroft #include <sys/file.h>
     42  1.3.2.1  mycroft #include <sys/resourcevar.h>
     43      1.1       pk 
     44  1.3.2.1  mycroft #include <vm/vm.h>
     45  1.3.2.1  mycroft #include <vm/vm_page.h>
     46  1.3.2.1  mycroft #include <vm/vm_kern.h>
     47  1.3.2.1  mycroft 
     48  1.3.2.1  mycroft #include <sys/kinfo.h>
     49  1.3.2.1  mycroft #include <sys/kinfo_proc.h>
     50  1.3.2.1  mycroft 
     51  1.3.2.1  mycroft #include <miscfs/procfs/procfs.h>
     52  1.3.2.1  mycroft #include <miscfs/procfs/pfsnode.h>
     53  1.3.2.1  mycroft 
     54  1.3.2.1  mycroft #include <machine/vmparam.h>
     55      1.1       pk 
     56      1.1       pk /*
     57      1.1       pk  * Get process address map (PIOCGMAP)
     58      1.1       pk  */
     59      1.1       pk int
     60      1.1       pk pfs_vmmap(procp, pfsp, pmapp)
     61      1.1       pk struct proc	*procp;
     62      1.1       pk struct nfsnode	*pfsp;
     63      1.1       pk struct procmap	*pmapp;
     64      1.1       pk {
     65      1.1       pk 	int		error = 0;
     66      1.1       pk 	vm_map_t	map;
     67      1.1       pk 	vm_map_entry_t	entry;
     68      1.1       pk 	struct procmap	prmap;
     69      1.1       pk 
     70      1.1       pk 	map = &procp->p_vmspace->vm_map;
     71      1.1       pk 	vm_map_lock(map);
     72      1.1       pk 	entry = map->header.next;
     73      1.1       pk 
     74      1.1       pk 	while (entry != &map->header) {
     75      1.1       pk 		if (entry->is_a_map) {
     76      1.1       pk 			vm_map_t	submap = entry->object.share_map;
     77      1.1       pk 			vm_map_entry_t	subentry;
     78      1.1       pk 
     79      1.1       pk 			vm_map_lock(submap);
     80      1.1       pk 			subentry = submap->header.next;
     81      1.1       pk 			while (subentry != &submap->header) {
     82      1.1       pk 				prmap.vaddr = subentry->start;
     83      1.1       pk 				prmap.size = subentry->end - subentry->start;
     84      1.1       pk 				prmap.offset = subentry->offset;
     85      1.1       pk 				prmap.prot = subentry->protection;
     86      1.1       pk 				error = copyout(&prmap, pmapp, sizeof(prmap));
     87      1.1       pk 				if (error)
     88      1.1       pk 					break;
     89      1.1       pk 				pmapp++;
     90      1.1       pk 				subentry = subentry->next;
     91      1.1       pk 			}
     92      1.1       pk 			vm_map_unlock(submap);
     93      1.1       pk 			if (error)
     94      1.1       pk 				break;
     95      1.1       pk 		}
     96      1.1       pk 		prmap.vaddr = entry->start;
     97      1.1       pk 		prmap.size = entry->end - entry->start;
     98      1.1       pk 		prmap.offset = entry->offset;
     99      1.1       pk 		prmap.prot = entry->protection;
    100      1.1       pk 		error = copyout(&prmap, pmapp, sizeof(prmap));
    101      1.1       pk 		if (error)
    102      1.1       pk 			break;
    103      1.1       pk 		pmapp++;
    104      1.1       pk 		entry = entry->next;
    105      1.1       pk 	}
    106      1.1       pk 
    107      1.1       pk 	vm_map_unlock(map);
    108      1.1       pk 	return error;
    109      1.1       pk }
    110      1.1       pk 
    111      1.1       pk /*
    112      1.1       pk  * Count number of VM entries of process (PIOCNMAP)
    113      1.1       pk  */
    114      1.1       pk int
    115      1.1       pk pfs_vm_nentries(procp, pfsp)
    116      1.1       pk struct proc	*procp;
    117      1.1       pk struct nfsnode	*pfsp;
    118      1.1       pk {
    119      1.1       pk 	int		count = 0;
    120      1.1       pk 	vm_map_t	map;
    121      1.1       pk 	vm_map_entry_t	entry;
    122      1.1       pk 
    123      1.1       pk 	map = &procp->p_vmspace->vm_map;
    124      1.1       pk 	vm_map_lock(map);
    125      1.1       pk 	entry = map->header.next;
    126      1.1       pk 
    127      1.1       pk 	while (entry != &map->header) {
    128      1.1       pk 		if (entry->is_a_map)
    129      1.1       pk 			count += entry->object.share_map->nentries;
    130      1.1       pk 		else
    131      1.1       pk 			count++;
    132      1.1       pk 		entry = entry->next;
    133      1.1       pk 	}
    134      1.1       pk 
    135      1.1       pk 	vm_map_unlock(map);
    136      1.1       pk 	return count;
    137      1.1       pk }
    138      1.1       pk 
    139      1.1       pk /*
    140      1.1       pk  * Map process mapped file to file descriptor (PIOCGMAPFD)
    141      1.1       pk  */
    142      1.1       pk int
    143      1.1       pk pfs_vmfd(procp, pfsp, vmfdp, p)
    144      1.1       pk struct proc	*procp;
    145      1.1       pk struct pfsnode	*pfsp;
    146      1.1       pk struct vmfd	*vmfdp;
    147      1.1       pk struct proc	*p;
    148      1.1       pk {
    149      1.1       pk 	int		rv;
    150      1.1       pk 	vm_map_t	map;
    151      1.1       pk 	vm_offset_t	addr;
    152      1.1       pk 	vm_size_t	size;
    153      1.1       pk 	vm_prot_t	prot, maxprot;
    154      1.1       pk 	vm_inherit_t	inherit;
    155      1.1       pk 	boolean_t	shared;
    156      1.1       pk 	vm_object_t	object;
    157      1.1       pk 	vm_offset_t	objoff;
    158      1.1       pk 	struct vnode	*vp;
    159      1.1       pk 	struct file	*fp;
    160      1.1       pk 	extern struct fileops	vnops;
    161      1.1       pk 
    162      1.1       pk 	map = &procp->p_vmspace->vm_map;
    163      1.1       pk 
    164      1.1       pk 	addr = vmfdp->vaddr;
    165      1.1       pk 	rv = vm_region(map, &addr, &size, &prot, &maxprot,
    166      1.1       pk 			&inherit, &shared, &object, &objoff);
    167      1.1       pk 
    168      1.1       pk 	if (rv != KERN_SUCCESS)
    169      1.1       pk 		return EINVAL;
    170      1.1       pk 
    171      1.1       pk 	while (object != NULL && object->pager == NULL)
    172      1.1       pk 		object = object->shadow;
    173      1.1       pk 
    174      1.1       pk 	if (object == NULL || object->pager == NULL
    175      1.1       pk 			/* Nobody seems to care || !object->pager_ready */ )
    176      1.1       pk 		return ENOENT;
    177      1.1       pk 
    178      1.1       pk 	if (object->pager->pg_type != PG_VNODE)
    179      1.1       pk 		return ENOENT;
    180      1.1       pk 
    181      1.1       pk 	/* We have a vnode pager, allocate file descriptor */
    182      1.1       pk 	vp = (struct vnode *)object->pager->pg_handle;
    183      1.1       pk 	if (VOP_ACCESS(vp, VREAD, p->p_ucred, p)) {
    184      1.1       pk 		rv = EACCES;
    185      1.1       pk 		goto out;
    186      1.1       pk 	}
    187      1.1       pk 	rv = falloc(p, &fp, &vmfdp->fd);
    188      1.1       pk 	if (rv)
    189      1.1       pk 		goto out;
    190      1.1       pk 
    191      1.1       pk 	VREF(vp);
    192      1.1       pk 	fp->f_type = DTYPE_VNODE;
    193      1.1       pk 	fp->f_ops = &vnops;
    194      1.1       pk 	fp->f_data = (caddr_t)vp;
    195      1.1       pk 	fp->f_flag = FREAD;
    196      1.1       pk 
    197      1.1       pk out:
    198      1.1       pk 	vm_object_unlock(object);
    199      1.1       pk 	return rv;
    200      1.1       pk }
    201      1.1       pk 
    202      1.1       pk /*
    203      1.1       pk  * Vnode op for reading/writing.
    204      1.1       pk  */
    205      1.1       pk /* ARGSUSED */
    206      1.1       pk pfs_doio(vp, uio, ioflag, cred)
    207      1.1       pk 	struct vnode *vp;
    208      1.1       pk 	register struct uio *uio;
    209      1.1       pk 	int ioflag;
    210      1.1       pk 	struct ucred *cred;
    211      1.1       pk {
    212      1.1       pk 	struct pfsnode	*pfsp = VTOPFS(vp);
    213      1.1       pk 	struct proc	*procp;
    214      1.1       pk 	int		error = 0;
    215      1.1       pk 	long		n, on;
    216      1.1       pk 
    217      1.1       pk #ifdef DEBUG
    218      1.1       pk 	if (pfs_debug)
    219      1.1       pk 		printf("pfs_doio(%s): vp 0x%x, proc %x\n",
    220      1.1       pk 			uio->uio_rw==UIO_READ?"R":"W", vp, uio->uio_procp);
    221      1.1       pk #endif
    222      1.1       pk 
    223      1.1       pk #ifdef DIAGNOSTIC
    224      1.1       pk 	if (vp->v_type != VPROC)
    225      1.1       pk 		panic("pfs_doio vtype");
    226      1.1       pk #endif
    227      1.1       pk 	procp = pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0;
    228      1.1       pk 	if (!procp)
    229      1.1       pk 		return ESRCH;
    230      1.1       pk 
    231      1.1       pk 	if (procp->p_flag & SSYS)
    232      1.1       pk 		return EACCES;
    233      1.1       pk 
    234      1.1       pk 	if (uio->uio_resid == 0)
    235      1.1       pk 		return (0);
    236      1.1       pk 	if (uio->uio_offset < 0)
    237      1.1       pk 		return (EINVAL);
    238      1.1       pk 
    239      1.1       pk 	do { /* One page at a time */
    240      1.1       pk 		int		rv;
    241      1.1       pk 		vm_map_t	map;
    242      1.1       pk 		vm_offset_t	offset;
    243      1.1       pk 		vm_size_t	size;
    244      1.1       pk 		vm_prot_t	oldprot = 0, prot, maxprot;
    245      1.1       pk 		vm_inherit_t	inherit;
    246      1.1       pk 		boolean_t	shared;
    247      1.1       pk 		vm_object_t	object;
    248      1.1       pk 		vm_offset_t	objoff;
    249      1.1       pk 		vm_page_t	m;
    250      1.1       pk 		vm_offset_t	kva;
    251      1.1       pk 
    252      1.1       pk 		on = uio->uio_offset - trunc_page(uio->uio_offset);
    253      1.1       pk 		n = MIN(PAGE_SIZE-on, uio->uio_resid);
    254      1.1       pk 
    255      1.1       pk 		/* Map page into kernel space */
    256      1.1       pk 
    257      1.1       pk 		map = &procp->p_vmspace->vm_map;
    258      1.1       pk #if 0
    259      1.1       pk 	vm_map_print(map, 1);
    260      1.1       pk #endif
    261      1.1       pk 
    262      1.1       pk 		offset = trunc_page(uio->uio_offset);
    263      1.1       pk 
    264      1.1       pk 		rv = vm_region(map, &offset, &size, &prot, &maxprot,
    265      1.1       pk 				&inherit, &shared, &object, &objoff);
    266      1.1       pk 		if (rv != KERN_SUCCESS)
    267      1.1       pk 			return EINVAL;
    268      1.1       pk 
    269      1.1       pk 		vm_object_unlock(object);
    270      1.1       pk 
    271      1.1       pk 		if (uio->uio_rw == UIO_WRITE && (prot & VM_PROT_WRITE) == 0) {
    272      1.1       pk 			oldprot = prot;
    273      1.1       pk 			prot |= VM_PROT_WRITE;
    274      1.1       pk 			rv = vm_protect(map, offset, PAGE_SIZE, FALSE, prot);
    275      1.1       pk 			if (rv != KERN_SUCCESS)
    276      1.1       pk 				return EPERM;
    277      1.1       pk 		}
    278      1.1       pk 		/* Just fault the page */
    279      1.1       pk 		rv = vm_fault(map, offset, prot, FALSE);
    280      1.1       pk 		if (rv != KERN_SUCCESS)
    281      1.1       pk 			return EFAULT;
    282      1.1       pk 
    283      1.1       pk 		/* Look up again as vm_fault() may have inserted a shadow object */
    284      1.1       pk 		rv = vm_region(map, &offset, &size, &prot, &maxprot,
    285      1.1       pk 				&inherit, &shared, &object, &objoff);
    286      1.1       pk 		if (rv != KERN_SUCCESS)
    287      1.1       pk 			return EINVAL;
    288      1.1       pk 
    289      1.1       pk 		/* Now find the page */
    290      1.1       pk 		/* XXX hope it's still there, should we have wired it? */
    291      1.1       pk 		m = vm_page_lookup(object, objoff);
    292      1.1       pk 		if (m == NULL)
    293      1.1       pk 			return ESRCH;
    294      1.1       pk 
    295      1.1       pk 		kva = kmem_alloc_wait(kernel_map, PAGE_SIZE);
    296      1.1       pk 
    297      1.1       pk 		pmap_enter(vm_map_pmap(kernel_map), kva, VM_PAGE_TO_PHYS(m),
    298      1.1       pk 			VM_PROT_DEFAULT, TRUE);
    299      1.1       pk 
    300      1.1       pk 		error = uiomove(kva + on, (int)n, uio);
    301      1.1       pk 
    302      1.1       pk 		pmap_remove(vm_map_pmap(kernel_map), kva, kva + PAGE_SIZE);
    303      1.1       pk 		kmem_free_wakeup(kernel_map, kva, PAGE_SIZE);
    304      1.1       pk 		if (oldprot) {
    305      1.1       pk 			rv = vm_protect(map, offset, PAGE_SIZE, FALSE, oldprot);
    306      1.1       pk 			if (rv != KERN_SUCCESS)
    307      1.1       pk 				return EPERM;
    308      1.1       pk 		}
    309      1.1       pk 
    310      1.1       pk 	} while (error == 0 && uio->uio_resid > 0);
    311      1.1       pk 
    312      1.1       pk 	return (error);
    313      1.1       pk }
    314      1.1       pk 
    315      1.1       pk #if 00
    316      1.1       pk int
    317      1.1       pk pfs_map(procp, kva, rw, offset)
    318      1.1       pk struct proc	*procp;
    319      1.1       pk int		rw;
    320      1.1       pk vm_offset_t	*kva, offset;
    321      1.1       pk {
    322      1.1       pk 	int		rv;
    323      1.1       pk 	vm_map_t	map;
    324      1.1       pk 	vm_size_t	size;
    325      1.1       pk 	vm_prot_t	prot, maxprot;
    326      1.1       pk 	vm_inherit_t	inherit;
    327      1.1       pk 	boolean_t	shared;
    328      1.1       pk 	vm_object_t	object;
    329      1.1       pk 	vm_offset_t	objoff;
    330      1.1       pk 	vm_page_t	m;
    331      1.1       pk 
    332      1.1       pk 	map = &procp->p_vmspace->vm_map;
    333      1.1       pk #if 0
    334      1.1       pk 	vm_map_print(map, 1);
    335      1.1       pk #endif
    336      1.1       pk 
    337      1.1       pk 	offset = trunc_page(offset);
    338      1.1       pk 
    339      1.1       pk 	rv = vm_region(map, &offset, &size, &prot, &maxprot,
    340      1.1       pk 			&inherit, &shared, &object, &objoff);
    341      1.1       pk 	if (rv != KERN_SUCCESS)
    342      1.1       pk 		return EINVAL;
    343      1.1       pk 
    344      1.1       pk 	vm_object_unlock(object);
    345      1.1       pk 
    346      1.1       pk 	if (rw == UIO_WRITE && (prot & VM_PROT_WRITE) == 0) {
    347      1.1       pk 		prot |= VM_PROT_WRITE;
    348      1.1       pk 		rv = vm_protect(map, offset, PAGE_SIZE, FALSE, prot);
    349      1.1       pk 		if (rv != KERN_SUCCESS)
    350      1.1       pk 			return EPERM;
    351      1.1       pk 	}
    352      1.1       pk 	/* Just fault page */
    353      1.1       pk 	rv = vm_fault(map, offset, prot, FALSE);
    354      1.1       pk 	if (rv != KERN_SUCCESS)
    355      1.1       pk 		return EFAULT;
    356      1.1       pk 
    357      1.1       pk 	/* Look up again as vm_fault() may have inserted a shadow object */
    358      1.1       pk 	rv = vm_region(map, &offset, &size, &prot, &maxprot,
    359      1.1       pk 			&inherit, &shared, &object, &objoff);
    360      1.1       pk 	if (rv != KERN_SUCCESS)
    361      1.1       pk 		return EINVAL;
    362      1.1       pk 
    363      1.1       pk 	m = vm_page_lookup(object, objoff);
    364      1.1       pk 	if (m == NULL)
    365      1.1       pk 		return ESRCH;
    366      1.1       pk 
    367      1.1       pk 	*kva = kmem_alloc_wait(kernel_map, PAGE_SIZE);
    368      1.1       pk 
    369      1.1       pk 	pmap_enter(vm_map_pmap(kernel_map), *kva, VM_PAGE_TO_PHYS(m),
    370      1.1       pk 			VM_PROT_DEFAULT, TRUE);
    371      1.1       pk 
    372      1.1       pk 	return 0;
    373      1.1       pk }
    374      1.1       pk 
    375      1.1       pk int
    376      1.1       pk pfs_unmap(procp, kva)
    377      1.1       pk struct proc	*procp;
    378      1.1       pk vm_offset_t	kva;
    379      1.1       pk {
    380      1.1       pk 	pmap_remove(vm_map_pmap(kernel_map), kva, kva + PAGE_SIZE);
    381      1.1       pk 	kmem_free_wakeup(kernel_map, kva, PAGE_SIZE);
    382      1.1       pk }
    383      1.1       pk #endif
    384