diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c index 48cf2e33d3e3..a9e143f30998 100644 --- a/sys/kern/imgact_aout.c +++ b/sys/kern/imgact_aout.c @@ -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 @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -43,6 +44,7 @@ #include #include #include +#include #include 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; diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index eb40b9194d45..76cbb934bf8d 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -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 @@ -54,17 +54,22 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include 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; diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h index 9aaea432d439..1fe98b15e270 100644 --- a/sys/sys/imgact.h +++ b/sys/sys/imgact.h @@ -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