Implement the first page access for object type determination more

VM clean.  Also, use vm_map_insert instead of vm_mmap.
Reviewed by:	dg@freebsd.org
This commit is contained in:
John Dyson 1998-01-11 21:35:38 +00:00
parent bb303fe246
commit 1616db3cf8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=32446
3 changed files with 132 additions and 96 deletions

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: imgact_aout.c,v 1.36 1997/09/02 20:05:33 bde Exp $
* $Id: imgact_aout.c,v 1.37 1998/01/06 05:15:25 dyson Exp $
*/
#include <sys/param.h>
@ -36,6 +36,7 @@
#include <sys/proc.h>
#include <sys/sysent.h>
#include <sys/vnode.h>
#include <sys/systm.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@ -43,6 +44,7 @@
#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_object.h>
#include <vm/vm_extern.h>
static int exec_aout_imgact __P((struct image_params *imgp));
@ -53,7 +55,9 @@ exec_aout_imgact(imgp)
{
const struct exec *a_out = (const struct exec *) imgp->image_header;
struct vmspace *vmspace;
vm_offset_t vmaddr;
struct vnode *vp;
vm_object_t object;
vm_offset_t text_end, data_end;
unsigned long virtual_offset;
unsigned long file_offset;
unsigned long bss_size;
@ -145,44 +149,43 @@ exec_aout_imgact(imgp)
*/
vmspace = imgp->proc->p_vmspace;
/*
* Map text/data read/execute
*/
vmaddr = virtual_offset;
error =
vm_mmap(&vmspace->vm_map, /* map */
&vmaddr, /* address */
a_out->a_text + a_out->a_data, /* size */
VM_PROT_READ | VM_PROT_EXECUTE, /* protection */
VM_PROT_ALL, /* max protection */
MAP_PRIVATE | MAP_FIXED, /* flags */
(caddr_t)imgp->vp, /* vnode */
file_offset); /* offset */
vp = imgp->vp;
object = vp->v_object;
vm_object_reference(object);
text_end = virtual_offset + a_out->a_text;
error = vm_map_insert(&vmspace->vm_map, object,
file_offset,
virtual_offset, text_end,
VM_PROT_READ | VM_PROT_EXECUTE, VM_PROT_ALL,
MAP_COPY_NEEDED | MAP_COPY_ON_WRITE);
if (error)
return (error);
/*
* allow writing of data
*/
vm_map_protect(&vmspace->vm_map,
vmaddr + a_out->a_text,
vmaddr + a_out->a_text + a_out->a_data,
VM_PROT_ALL,
FALSE);
if (bss_size != 0) {
/*
* Allocate demand-zeroed area for uninitialized data
* "bss" = 'block started by symbol' - named after the IBM 7090
* instruction of the same name.
*/
vmaddr = virtual_offset + a_out->a_text + a_out->a_data;
error = vm_map_find(&vmspace->vm_map, NULL, 0,
&vmaddr, bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0);
data_end = text_end + a_out->a_data;
if (a_out->a_data) {
vm_object_reference(object);
error = vm_map_insert(&vmspace->vm_map, object,
file_offset + a_out->a_text,
text_end, data_end,
VM_PROT_ALL, VM_PROT_ALL,
MAP_COPY_NEEDED | MAP_COPY_ON_WRITE);
if (error)
return (error);
}
pmap_object_init_pt(&vmspace->vm_pmap, virtual_offset,
object, (vm_pindex_t) OFF_TO_IDX(file_offset),
a_out->a_text + a_out->a_data, 0);
if (bss_size) {
error = vm_map_insert(&vmspace->vm_map, NULL, 0,
data_end, data_end + bss_size,
VM_PROT_ALL, VM_PROT_ALL, 0);
if (error)
return (error);
}
/* Fill in process VM information */
vmspace->vm_tsize = a_out->a_text >> PAGE_SHIFT;
vmspace->vm_dsize = (a_out->a_data + bss_size) >> PAGE_SHIFT;

View File

@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: kern_exec.c,v 1.72 1997/12/27 02:56:21 bde Exp $
* $Id: kern_exec.c,v 1.73 1998/01/06 05:15:34 dyson Exp $
*/
#include <sys/param.h>
@ -54,17 +54,22 @@
#include <vm/vm_prot.h>
#include <sys/lock.h>
#include <vm/pmap.h>
#include <vm/vm_page.h>
#include <vm/vm_map.h>
#include <vm/vm_kern.h>
#include <vm/vm_extern.h>
#include <vm/vm_object.h>
#include <vm/vm_zone.h>
#include <vm/vm_pager.h>
#include <vm/vm_pageout.h>
#include <machine/reg.h>
static int *exec_copyout_strings __P((struct image_params *));
static int exec_check_permissions(struct image_params *);
static int exec_check_permissions __P((struct image_params *));
static int exec_map_first_page __P((struct image_params *));
static void exec_unmap_first_page __P((struct image_params *));
/*
* XXX trouble here if sizeof(caddr_t) != sizeof(int), other parts
@ -114,7 +119,6 @@ execve(p, uap)
imgp->proc = p;
imgp->uap = uap;
imgp->attr = &attr;
imgp->image_header = NULL;
imgp->argc = imgp->envc = 0;
imgp->argv0 = NULL;
imgp->entry_addr = 0;
@ -122,18 +126,21 @@ execve(p, uap)
imgp->interpreted = 0;
imgp->interpreter_name[0] = '\0';
imgp->auxargs = NULL;
imgp->vp = NULL;
imgp->firstpage = NULL;
/*
* Allocate temporary demand zeroed space for argument and
* environment strings
*/
imgp->stringbase = (char *)kmem_alloc_wait(exec_map, ARG_MAX);
imgp->stringbase = (char *)kmem_alloc_wait(exec_map, ARG_MAX + PAGE_SIZE);
if (imgp->stringbase == NULL) {
error = ENOMEM;
goto exec_fail;
}
imgp->stringp = imgp->stringbase;
imgp->stringspace = ARG_MAX;
imgp->image_header = imgp->stringbase + ARG_MAX;
/*
* Translate the file name. namei() returns a vnode pointer
@ -147,7 +154,8 @@ execve(p, uap)
error = namei(ndp);
if (error) {
kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX);
kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase,
ARG_MAX + PAGE_SIZE);
goto exec_fail;
}
@ -162,38 +170,7 @@ execve(p, uap)
goto exec_fail_dealloc;
}
/*
* Get the image header, which we define here as meaning the first
* page of the executable.
*/
if (imgp->vp->v_object && imgp->vp->v_mount &&
imgp->vp->v_mount->mnt_stat.f_iosize >= PAGE_SIZE &&
imgp->vp->v_object->un_pager.vnp.vnp_size >=
imgp->vp->v_mount->mnt_stat.f_iosize) {
/*
* Get a buffer with (at least) the first page.
*/
error = bread(imgp->vp, 0, imgp->vp->v_mount->mnt_stat.f_iosize,
p->p_ucred, &bp);
imgp->image_header = bp->b_data;
} else {
int resid;
/*
* The filesystem block size is too small, so do this the hard
* way. Malloc some space and read PAGE_SIZE worth of the image
* header into it.
*/
imgp->image_header = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
error = vn_rdwr(UIO_READ, imgp->vp,
(void *)imgp->image_header, PAGE_SIZE, 0,
UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
/*
* Clear out any remaining junk.
*/
if (!error && resid)
bzero((char *)imgp->image_header + PAGE_SIZE - resid, resid);
}
error = exec_map_first_page(imgp);
VOP_UNLOCK(imgp->vp, 0, p);
if (error)
goto exec_fail_dealloc;
@ -216,13 +193,7 @@ execve(p, uap)
if (error)
goto exec_fail_dealloc;
if (imgp->interpreted) {
/* free old bp/image_header */
if (bp != NULL) {
brelse(bp);
bp = NULL;
} else
free((void *)imgp->image_header, M_TEMP);
imgp->image_header = NULL;
exec_unmap_first_page(imgp);
/* free old vnode and name buffer */
vrele(ndp->ni_vp);
zfree(namei_zone, ndp->ni_cnd.cn_pnbuf);
@ -351,31 +322,26 @@ execve(p, uap)
/* Set entry address */
setregs(p, imgp->entry_addr, (u_long)stack_base);
exec_fail_dealloc:
/*
* free various allocated resources
*/
kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX);
if (bp != NULL)
brelse(bp);
else if (imgp->image_header != NULL)
free((void *)imgp->image_header, M_TEMP);
vrele(ndp->ni_vp);
zfree(namei_zone, ndp->ni_cnd.cn_pnbuf);
if (imgp->firstpage)
exec_unmap_first_page(imgp);
return (0);
exec_fail_dealloc:
if (imgp->stringbase != NULL)
kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase, ARG_MAX);
if (bp != NULL)
brelse(bp);
else if (imgp->image_header != NULL)
free((void *)imgp->image_header, M_TEMP);
kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase,
ARG_MAX + PAGE_SIZE);
if (ndp->ni_vp) {
vrele(ndp->ni_vp);
zfree(namei_zone, ndp->ni_cnd.cn_pnbuf);
}
if (error == 0)
return (0);
exec_fail:
if (imgp->vmspace_destroyed) {
/* sorry, no more process anymore. exit gracefully */
@ -387,6 +353,71 @@ execve(p, uap)
}
}
int
exec_map_first_page(imgp)
struct image_params *imgp;
{
int s;
vm_page_t m;
vm_object_t object;
if (imgp->firstpage) {
exec_unmap_first_page(imgp);
}
object = imgp->vp->v_object;
s = splvm();
retry:
m = vm_page_lookup(object, 0);
if (m == NULL) {
m = vm_page_alloc(object, 0, VM_ALLOC_NORMAL);
if (m == NULL) {
VM_WAIT;
goto retry;
}
} else if ((m->flags & PG_BUSY) || m->busy) {
m->flags |= PG_WANTED;
tsleep(m, PVM, "execpw", 0);
goto retry;
}
m->flags |= PG_BUSY;
if ((m->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL) {
int rv;
rv = vm_pager_get_pages(object, &m, 1, 0);
if (rv != VM_PAGER_OK) {
vm_page_protect(m, VM_PROT_NONE);
vm_page_deactivate(m);
PAGE_WAKEUP(m);
splx(s);
return EIO;
}
}
vm_page_wire(m);
PAGE_WAKEUP(m);
splx(s);
pmap_kenter((vm_offset_t) imgp->image_header, VM_PAGE_TO_PHYS(m));
imgp->firstpage = m;
return 0;
}
void
exec_unmap_first_page(imgp)
struct image_params *imgp;
{
if (imgp->firstpage) {
pmap_kremove((vm_offset_t) imgp->image_header);
vm_page_unwire(imgp->firstpage);
imgp->firstpage = NULL;
}
}
/*
* Destroy old address space, and allocate a new stack
* The new stack is only SGROWSIZ large because it is grown
@ -420,10 +451,11 @@ exec_new_vmspace(imgp)
}
/* Allocate a new stack */
error = vm_map_find(map, NULL, 0, (vm_offset_t *)&stack_addr,
SGROWSIZ, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0);
error = vm_map_insert(&vmspace->vm_map, NULL, 0,
(vm_offset_t) stack_addr, (vm_offset_t) USRSTACK,
VM_PROT_ALL, VM_PROT_ALL, 0);
if (error)
return(error);
return (error);
vmspace->vm_ssize = SGROWSIZ >> PAGE_SHIFT;

View File

@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: imgact.h,v 1.14 1997/02/22 09:45:17 peter Exp $
* $Id: imgact.h,v 1.15 1997/04/23 22:02:37 ache Exp $
*/
#ifndef _SYS_IMGACT_H_
@ -52,6 +52,7 @@ struct image_params {
char interpreted; /* flag - this executable is interpreted */
char interpreter_name[64]; /* name of the interpreter */
void *auxargs; /* ELF Auxinfo structure pointer */
struct vm_page *firstpage; /* first page that we mapped */
};
#ifdef KERNEL