* Copyright (c) 1993 Jan-Simon Pendry
* Copyright (c) 1993 Sean Eric Fagan
* The Regents of the University of California. All rights reserved.
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry and Sean Eric Fagan.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)procfs_mem.c 8.5 (Berkeley) 6/15/94
* $Id: procfs_mem.c,v 3.2 1993/12/15 09:40:17 jsp Exp $
* This is a lightly hacked and merged version
* of sef's pread/pwrite functions
#include <miscfs/procfs/procfs.h>
writing
= uio
->uio_rw
== UIO_WRITE
;
* Only map in one page at a time. We don't have to, but it
* makes things easier. This way is trivial - right?
int page_offset
; /* offset into page */
vm_offset_t pageno
; /* page number */
vm_map_entry_t out_entry
;
boolean_t wired
, single_use
;
uva
= (vm_offset_t
) uio
->uio_offset
;
if (uva
> VM_MAXUSER_ADDRESS
) {
* Get the page number of this segment.
pageno
= trunc_page(uva
);
page_offset
= uva
- pageno
;
len
= min(PAGE_SIZE
- page_offset
, uio
->uio_resid
);
map
= &p
->p_vmspace
->vm_map
;
* Check the permissions for the area we're interested
fix_prot
= !vm_map_check_protection(map
, pageno
,
pageno
+ PAGE_SIZE
, VM_PROT_WRITE
);
* If the page is not writable, we make it so.
* XXX It is possible that a page may *not* be
* read/executable, if a process changes that!
* We will assume, for now, that a page is either
* VM_PROT_ALL, or VM_PROT_READ|VM_PROT_EXECUTE.
error
= vm_map_protect(map
, pageno
,
pageno
+ PAGE_SIZE
, VM_PROT_ALL
, 0);
* Now we need to get the page. out_entry, out_prot, wired,
* and single_use aren't used. One would think the vm code
* would be a *bit* nicer... We use tmap because
* vm_map_lookup() can change the map argument.
error
= vm_map_lookup(&tmap
, pageno
,
writing
? VM_PROT_WRITE
: VM_PROT_READ
,
&out_entry
, &object
, &off
, &out_prot
,
* We're done with tmap now.
vm_map_lookup_done(tmap
, out_entry
);
if (!error
&& writing
&& object
->shadow
) {
m
= vm_page_lookup(object
, off
);
if (m
== 0 || (m
->flags
& PG_COPYONWRITE
))
error
= vm_fault(map
, pageno
,
/* Find space in kernel_map for the page we're interested in */
error
= vm_map_find(kernel_map
, object
, off
, &kva
,
* Neither vm_map_lookup() nor vm_map_find() appear
* to add a reference count to the object, so we do
vm_object_reference(object
);
* Mark the page we just found as pageable.
error
= vm_map_pageable(kernel_map
, kva
,
error
= uiomove(kva
+ page_offset
, len
, uio
);
vm_map_remove(kernel_map
, kva
, kva
+ PAGE_SIZE
);
vm_map_protect(map
, pageno
, pageno
+ PAGE_SIZE
,
VM_PROT_READ
|VM_PROT_EXECUTE
, 0);
} while (error
== 0 && uio
->uio_resid
> 0);
* Copy data in and out of the target process.
* We do this by mapping the process's page into
* the kernel and then doing a uiomove direct
* from the kernel address space.
procfs_domem(curp
, p
, pfs
, uio
)
return (procfs_rwmem(p
, uio
));
* Given process (p), find the vnode from which
* it's text segment is being executed.
* It would be nice to grab this information from
* the VM system, however, there is no sure-fire
* way of doing that. Instead, fork(), exec() and
* wait() all maintain the p_textvp field in the
* process proc structure which contains a held
* reference to the exec'ed vnode.
* Given process (p), find the vnode from which
* it's text segment is being mapped.
* (This is here, rather than in procfs_subr in order
* to keep all the VM related code in one place.)
vm_offset_t pageno
; /* page number */
/* find a vnode pager for the user address space */
for (pageno
= VM_MIN_ADDRESS
;
pageno
< VM_MAXUSER_ADDRESS
;
vm_map_entry_t out_entry
;
boolean_t wired
, single_use
;
map
= &p
->p_vmspace
->vm_map
;
error
= vm_map_lookup(&map
, pageno
,
&out_entry
, &object
, &off
, &out_prot
,
printf("procfs: found vm object\n");
vm_map_lookup_done(map
, out_entry
);
printf("procfs: vm object = %x\n", object
);
* At this point, assuming no errors, object
* is the VM object mapping UVA (pageno).
* Ensure it has a vnode pager, then grab
* the vnode from that pager's handle.
printf("procfs: pager = %x\n", pager
);
printf("procfs: found pager, type = %d\n", pager
->pg_type
);
if (pager
&& pager
->pg_type
== PG_VNODE
) {
vp
= (struct vnode
*) pager
->pg_handle
;
printf("procfs: vp = 0x%x\n", vp
);
printf("procfs: text object not found\n");
#endif /* probably_never */