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:
parent
bb303fe246
commit
1616db3cf8
@ -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;
|
||||
|
@ -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 @@ interpret:
|
||||
|
||||
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 @@ interpret:
|
||||
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 @@ interpret:
|
||||
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 @@ interpret:
|
||||
/* 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 @@ exec_fail:
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user