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