ia32_sysvec.c revision 183322
140123Sdes/*- 266830Sobrien * Copyright (c) 2002 Doug Rabson 366830Sobrien * Copyright (c) 2003 Peter Wemm 466830Sobrien * All rights reserved. 566830Sobrien * 666830Sobrien * Redistribution and use in source and binary forms, with or without 766830Sobrien * modification, are permitted provided that the following conditions 866830Sobrien * are met: 966830Sobrien * 1. Redistributions of source code must retain the above copyright 1066830Sobrien * notice, this list of conditions and the following disclaimer. 1166830Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1266830Sobrien * notice, this list of conditions and the following disclaimer in the 1366830Sobrien * documentation and/or other materials provided with the distribution. 1466830Sobrien * 1566830Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1666830Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1766830Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1866830Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1966830Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2066830Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2166830Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2266830Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2366830Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2466830Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2566830Sobrien * SUCH DAMAGE. 2666830Sobrien */ 2750472Speter 28709Swollman#include <sys/cdefs.h> 2966830Sobrien__FBSDID("$FreeBSD: head/sys/compat/ia32/ia32_sysvec.c 183322 2008-09-24 10:14:37Z kib $"); 3037Srgrimes 3137Srgrimes#include "opt_compat.h" 3237Srgrimes 3337Srgrimes#define __ELF_WORD_SIZE 32 3437Srgrimes 3537Srgrimes#include <sys/param.h> 3651231Ssheldonh#include <sys/exec.h> 3751231Ssheldonh#include <sys/fcntl.h> 3851231Ssheldonh#include <sys/imgact.h> 3951231Ssheldonh#include <sys/kernel.h> 408460Sjkh#include <sys/lock.h> 4137Srgrimes#include <sys/malloc.h> 4237Srgrimes#include <sys/mutex.h> 4337Srgrimes#include <sys/mman.h> 4437Srgrimes#include <sys/namei.h> 4551231Ssheldonh#include <sys/pioctl.h> 4637Srgrimes#include <sys/proc.h> 4737Srgrimes#include <sys/procfs.h> 4837Srgrimes#include <sys/resourcevar.h> 4968985Sdougb#include <sys/systm.h> 5068985Sdougb#include <sys/signalvar.h> 5151231Ssheldonh#include <sys/stat.h> 5220684Sjoerg#include <sys/sx.h> 5351231Ssheldonh#include <sys/syscall.h> 5437Srgrimes#include <sys/sysctl.h> 5543179Sdillon#include <sys/sysent.h> 5643803Sdillon#include <sys/vnode.h> 5743179Sdillon#include <sys/imgact_elf.h> 5851231Ssheldonh 5943375Sdillon#include <vm/vm.h> 6043375Sdillon#include <vm/vm_kern.h> 6143803Sdillon#include <vm/vm_param.h> 6243179Sdillon#include <vm/pmap.h> 6343179Sdillon#include <vm/vm_map.h> 6443179Sdillon#include <vm/vm_object.h> 6543219Speter#include <vm/vm_extern.h> 6643219Speter 6751231Ssheldonh#include <compat/freebsd32/freebsd32_signal.h> 6843849Sjkh#include <compat/freebsd32/freebsd32_util.h> 6959674Ssheldonh#include <compat/freebsd32/freebsd32_proto.h> 7051231Ssheldonh#include <compat/freebsd32/freebsd32_syscall.h> 7143219Speter#include <compat/ia32/ia32_signal.h> 7243219Speter#ifdef __amd64__ 7343219Speter#include <machine/psl.h> 7469876Sobrien#include <machine/segments.h> 7569876Sobrien#include <machine/specialreg.h> 7669876Sobrien#else 7769876Sobrien#include <i386/include/psl.h> 7869876Sobrien#include <i386/include/segments.h> 7969876Sobrien#include <i386/include/specialreg.h> 8069876Sobrien#endif 8169876Sobrien#include <machine/frame.h> 8269876Sobrien#include <machine/md_var.h> 8369876Sobrien#include <machine/pcb.h> 8469876Sobrien#include <machine/cpufunc.h> 8569876Sobrien 8669876SobrienCTASSERT(sizeof(struct ia32_mcontext) == 640); 8769876SobrienCTASSERT(sizeof(struct ia32_ucontext) == 704); 8867179SjwdCTASSERT(sizeof(struct ia32_sigframe) == 800); 8969876SobrienCTASSERT(sizeof(struct siginfo32) == 64); 9067179Sjwd#ifdef COMPAT_FREEBSD4 9167113SmarkmCTASSERT(sizeof(struct ia32_mcontext4) == 260); 9267113SmarkmCTASSERT(sizeof(struct ia32_ucontext4) == 324); 9367113SmarkmCTASSERT(sizeof(struct ia32_sigframe4) == 408); 9467113Smarkm#endif 9567113Smarkm 9667113Smarkmstatic register_t *ia32_copyout_strings(struct image_params *imgp); 9767179Sjwdstatic void ia32_fixlimit(struct rlimit *rl, int which); 9867179Sjwd 9967179Sjwdextern struct sysent freebsd32_sysent[]; 10067113Smarkm 10167179SjwdSYSCTL_NODE(_compat, OID_AUTO, ia32, CTLFLAG_RW, 0, "ia32 mode"); 10267113Smarkm 10367113Smarkmstatic u_long ia32_maxdsiz = IA32_MAXDSIZ; 10467113SmarkmSYSCTL_ULONG(_compat_ia32, OID_AUTO, maxdsiz, CTLFLAG_RW, &ia32_maxdsiz, 0, ""); 10567113SmarkmTUNABLE_ULONG("compat.ia32.maxdsiz", &ia32_maxdsiz); 10667113Smarkmstatic u_long ia32_maxssiz = IA32_MAXSSIZ; 10715568SasamiSYSCTL_ULONG(_compat_ia32, OID_AUTO, maxssiz, CTLFLAG_RW, &ia32_maxssiz, 0, ""); 10851231SsheldonhTUNABLE_ULONG("compat.ia32.maxssiz", &ia32_maxssiz); 10951231Ssheldonhstatic u_long ia32_maxvmem = IA32_MAXVMEM; 11015568SasamiSYSCTL_ULONG(_compat_ia32, OID_AUTO, maxvmem, CTLFLAG_RW, &ia32_maxvmem, 0, ""); 11115568SasamiTUNABLE_ULONG("compat.ia32.maxvmem", &ia32_maxvmem); 11215568Sasami 11351231Ssheldonhstruct sysentvec ia32_freebsd_sysvec = { 11451231Ssheldonh .sv_size = FREEBSD32_SYS_MAXSYSCALL, 11545239Sgrog .sv_table = freebsd32_sysent, 11651231Ssheldonh .sv_mask = 0, 11751231Ssheldonh .sv_sigsize = 0, 11842741Sgrog .sv_sigtbl = NULL, 11943803Sdillon .sv_errsize = 0, 1203843Sdg .sv_errtbl = NULL, 12168985Sdougb .sv_transtrap = NULL, 12251231Ssheldonh .sv_fixup = elf32_freebsd_fixup, 12360350Sdavidn .sv_sendsig = ia32_sendsig, 12437Srgrimes .sv_sigcode = ia32_sigcode, 12537Srgrimes .sv_szsigcode = &sz_ia32_sigcode, 12637Srgrimes .sv_prepsyscall = NULL, 12737Srgrimes .sv_name = "FreeBSD ELF32", 12837Srgrimes .sv_coredump = elf32_coredump, 12937Srgrimes .sv_imgact_try = NULL, 13037Srgrimes .sv_minsigstksz = MINSIGSTKSZ, 13137Srgrimes .sv_pagesize = IA32_PAGE_SIZE, 13237Srgrimes .sv_minuser = 0, 13337Srgrimes .sv_maxuser = FREEBSD32_USRSTACK, 13437Srgrimes .sv_usrstack = FREEBSD32_USRSTACK, 13537Srgrimes .sv_psstrings = FREEBSD32_PS_STRINGS, 13637Srgrimes .sv_stackprot = VM_PROT_ALL, 13737Srgrimes .sv_copyout_strings = ia32_copyout_strings, 13837Srgrimes .sv_setregs = ia32_setregs, 13937Srgrimes .sv_fixlimit = ia32_fixlimit, 14037Srgrimes .sv_maxssiz = &ia32_maxssiz 14137Srgrimes}; 14237Srgrimes 14337Srgrimes 14437Srgrimesstatic Elf32_Brandinfo ia32_brand_info = { 14537Srgrimes .brand = ELFOSABI_FREEBSD, 14637Srgrimes .machine = EM_386, 14737Srgrimes .compat_3_brand = "FreeBSD", 14837Srgrimes .emul_path = NULL, 14937Srgrimes .interp_path = "/libexec/ld-elf.so.1", 15037Srgrimes .sysvec = &ia32_freebsd_sysvec, 15137Srgrimes .interp_newpath = "/libexec/ld-elf32.so.1", 15237Srgrimes .flags = BI_CAN_EXEC_DYN 15351231Ssheldonh}; 15451231Ssheldonh 1552164SdgSYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY, 15651231Ssheldonh (sysinit_cfunc_t) elf32_insert_brand_entry, 15751231Ssheldonh &ia32_brand_info); 15837Srgrimes 15945222Scracauerstatic Elf32_Brandinfo ia32_brand_oinfo = { 16037Srgrimes .brand = ELFOSABI_FREEBSD, 16137Srgrimes .machine = EM_386, 16243197Sdillon .compat_3_brand = "FreeBSD", 16343197Sdillon .emul_path = NULL, 16443197Sdillon .interp_path = "/usr/libexec/ld-elf.so.1", 16551231Ssheldonh .sysvec = &ia32_freebsd_sysvec, 16651231Ssheldonh .interp_newpath = "/libexec/ld-elf32.so.1", 16751231Ssheldonh .flags = BI_CAN_EXEC_DYN, 16851231Ssheldonh}; 16951231Ssheldonh 17051231SsheldonhSYSINIT(oia32, SI_SUB_EXEC, SI_ORDER_ANY, 17151231Ssheldonh (sysinit_cfunc_t) elf32_insert_brand_entry, 17251231Ssheldonh &ia32_brand_oinfo); 17351231Ssheldonh 17451231Ssheldonh 1751692Sphkvoid 17643803Sdillonelf32_dump_thread(struct thread *td __unused, void *dst __unused, 17743197Sdillon size_t *off __unused) 17856038Sgreen{ 17956038Sgreen} 18051231Ssheldonh 18151231Ssheldonh 18251231Ssheldonh/* XXX may be freebsd32 MI */ 18351231Ssheldonhstatic register_t * 18451231Ssheldonhia32_copyout_strings(struct image_params *imgp) 18551231Ssheldonh{ 18643803Sdillon int argc, envc; 18751231Ssheldonh u_int32_t *vectp; 18851231Ssheldonh char *stringp, *destp; 18937Srgrimes u_int32_t *stack_base; 19043197Sdillon struct freebsd32_ps_strings *arginfo; 19143197Sdillon int szsigcode; 19251231Ssheldonh 19350357Ssheldonh /* 19443197Sdillon * Calculate string base and vector table pointers. 19543197Sdillon * Also deal with signal trampoline code for this exec type. 19667179Sjwd */ 19767179Sjwd arginfo = (struct freebsd32_ps_strings *)FREEBSD32_PS_STRINGS; 19867179Sjwd szsigcode = *(imgp->proc->p_sysent->sv_szsigcode); 19967179Sjwd destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - 20067179Sjwd roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *)); 20167179Sjwd 20267179Sjwd /* 20367179Sjwd * install sigcode 20467179Sjwd */ 20567179Sjwd if (szsigcode) 20667179Sjwd copyout(imgp->proc->p_sysent->sv_sigcode, 20767179Sjwd ((caddr_t)arginfo - szsigcode), szsigcode); 20867179Sjwd 20967179Sjwd /* 21067179Sjwd * If we have a valid auxargs ptr, prepare some room 21167179Sjwd * on the stack. 21267179Sjwd */ 21367179Sjwd if (imgp->auxargs) { 21467179Sjwd /* 21567179Sjwd * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for 21667179Sjwd * lower compatibility. 21767181Sjwd */ 21867179Sjwd imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size 21967179Sjwd : (AT_COUNT * 2); 22067181Sjwd /* 22167181Sjwd * The '+ 2' is for the null pointers at the end of each of 22267181Sjwd * the arg and env vector sets,and imgp->auxarg_size is room 22367383Sjkh * for argument of Runtime loader. 22467179Sjwd */ 22567179Sjwd vectp = (u_int32_t *) (destp - (imgp->args->argc + imgp->args->envc + 2 + 22667383Sjkh imgp->auxarg_size) * sizeof(u_int32_t)); 22767179Sjwd 22867179Sjwd } else 22967179Sjwd /* 23067179Sjwd * The '+ 2' is for the null pointers at the end of each of 23167179Sjwd * the arg and env vector sets 23267179Sjwd */ 23367179Sjwd vectp = (u_int32_t *) 23467179Sjwd (destp - (imgp->args->argc + imgp->args->envc + 2) * sizeof(u_int32_t)); 23567179Sjwd 23667179Sjwd /* 2374091Sache * vectp also becomes our initial stack base 238872Sache */ 23964400Sbrian stack_base = vectp; 24064400Sbrian 24164400Sbrian stringp = imgp->args->begin_argv; 24264400Sbrian argc = imgp->args->argc; 24364400Sbrian envc = imgp->args->envc; 24464400Sbrian /* 24564400Sbrian * Copy out strings - arguments and environment. 24664400Sbrian */ 24764400Sbrian copyout(stringp, destp, ARG_MAX - imgp->args->stringspace); 24864449Sbrian 24964400Sbrian /* 25064449Sbrian * Fill in "ps_strings" struct for ps, w, etc. 25164449Sbrian */ 25264449Sbrian suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp); 25364449Sbrian suword32(&arginfo->ps_nargvstr, argc); 25464400Sbrian 25564400Sbrian /* 25664400Sbrian * Fill in argument portion of vector table. 25764400Sbrian */ 25864400Sbrian for (; argc > 0; --argc) { 25964400Sbrian suword32(vectp++, (u_int32_t)(intptr_t)destp); 26038237Sbrian while (*stringp++ != 0) 26139384Sbrian destp++; 26239384Sbrian destp++; 26364400Sbrian } 26439384Sbrian 26539384Sbrian /* a null vector table pointer separates the argp's from the envp's */ 26639384Sbrian suword32(vectp++, 0); 26739384Sbrian 26851231Ssheldonh suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp); 26939384Sbrian suword32(&arginfo->ps_nenvstr, envc); 27039384Sbrian 27138237Sbrian /* 27226450Sache * Fill in environment portion of vector table. 27338237Sbrian */ 27439384Sbrian for (; envc > 0; --envc) { 27539384Sbrian suword32(vectp++, (u_int32_t)(intptr_t)destp); 27639384Sbrian while (*stringp++ != 0) 27739384Sbrian destp++; 27838237Sbrian destp++; 27921197Sphk } 28017767Sjkh 28151231Ssheldonh /* end of vector table is a null pointer */ 28251231Ssheldonh suword32(vectp, 0); 28351231Ssheldonh 28451231Ssheldonh return ((register_t *)stack_base); 28551231Ssheldonh} 28656969Snsayer 28751231Ssheldonhstatic void 28851231Ssheldonhia32_fixlimit(struct rlimit *rl, int which) 28951231Ssheldonh{ 29051231Ssheldonh 29151231Ssheldonh switch (which) { 29217767Sjkh case RLIMIT_DATA: 29351231Ssheldonh if (ia32_maxdsiz != 0) { 29451231Ssheldonh if (rl->rlim_cur > ia32_maxdsiz) 29551231Ssheldonh rl->rlim_cur = ia32_maxdsiz; 29645096Simp if (rl->rlim_max > ia32_maxdsiz) 29745096Simp rl->rlim_max = ia32_maxdsiz; 29845096Simp } 29951231Ssheldonh break; 30051231Ssheldonh case RLIMIT_STACK: 30151231Ssheldonh if (ia32_maxssiz != 0) { 3027293Sjkh if (rl->rlim_cur > ia32_maxssiz) 3031675Sache rl->rlim_cur = ia32_maxssiz; 3041675Sache if (rl->rlim_max > ia32_maxssiz) 30551231Ssheldonh rl->rlim_max = ia32_maxssiz; 30651231Ssheldonh } 30751231Ssheldonh break; 30814624Snate case RLIMIT_VMEM: 30914596Snate if (ia32_maxvmem != 0) { 31014596Snate if (rl->rlim_cur > ia32_maxvmem) 31151231Ssheldonh rl->rlim_cur = ia32_maxvmem; 31251231Ssheldonh if (rl->rlim_max > ia32_maxvmem) 31351231Ssheldonh rl->rlim_max = ia32_maxvmem; 31425184Sjkh } 31525184Sjkh break; 3167460Sjkh } 3177460Sjkh} 31857398Sshin