ia32_sysvec.c revision 120422
1100384Speter/*-
2100384Speter * Copyright (c) 2002 Doug Rabson
3114987Speter * Copyright (c) 2003 Peter Wemm
4100384Speter * All rights reserved.
5100384Speter *
6100384Speter * Redistribution and use in source and binary forms, with or without
7100384Speter * modification, are permitted provided that the following conditions
8100384Speter * are met:
9100384Speter * 1. Redistributions of source code must retain the above copyright
10100384Speter *    notice, this list of conditions and the following disclaimer.
11100384Speter * 2. Redistributions in binary form must reproduce the above copyright
12100384Speter *    notice, this list of conditions and the following disclaimer in the
13100384Speter *    documentation and/or other materials provided with the distribution.
14100384Speter *
15100384Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16100384Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17100384Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18100384Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19100384Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20100384Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21100384Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22100384Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23100384Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24100384Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25100384Speter * SUCH DAMAGE.
26100384Speter */
27100384Speter
28118031Sobrien#include <sys/cdefs.h>
29118031Sobrien__FBSDID("$FreeBSD: head/sys/compat/ia32/ia32_sysvec.c 120422 2003-09-25 01:10:26Z peter $");
30118031Sobrien
31114987Speter#include "opt_compat.h"
32114987Speter
33100384Speter#define __ELF_WORD_SIZE 32
34100384Speter
35100384Speter#include <sys/param.h>
36100384Speter#include <sys/exec.h>
37100384Speter#include <sys/fcntl.h>
38100384Speter#include <sys/imgact.h>
39100384Speter#include <sys/kernel.h>
40100384Speter#include <sys/lock.h>
41100384Speter#include <sys/malloc.h>
42100384Speter#include <sys/mutex.h>
43100384Speter#include <sys/mman.h>
44100384Speter#include <sys/namei.h>
45100384Speter#include <sys/pioctl.h>
46100384Speter#include <sys/proc.h>
47100384Speter#include <sys/procfs.h>
48100384Speter#include <sys/resourcevar.h>
49100384Speter#include <sys/systm.h>
50100384Speter#include <sys/signalvar.h>
51100384Speter#include <sys/stat.h>
52100384Speter#include <sys/sx.h>
53100384Speter#include <sys/syscall.h>
54100384Speter#include <sys/sysctl.h>
55100384Speter#include <sys/sysent.h>
56100384Speter#include <sys/vnode.h>
57100384Speter#include <sys/imgact_elf.h>
58100384Speter
59100384Speter#include <vm/vm.h>
60100384Speter#include <vm/vm_kern.h>
61100384Speter#include <vm/vm_param.h>
62100384Speter#include <vm/pmap.h>
63100384Speter#include <vm/vm_map.h>
64100384Speter#include <vm/vm_object.h>
65100384Speter#include <vm/vm_extern.h>
66100384Speter
67119336Speter#include <compat/freebsd32/freebsd32_util.h>
68119336Speter#include <compat/freebsd32/freebsd32_proto.h>
69119336Speter#include <compat/ia32/ia32_signal.h>
70114987Speter#include <machine/psl.h>
71114987Speter#include <machine/segments.h>
72114987Speter#include <machine/specialreg.h>
73100384Speter#include <machine/frame.h>
74100384Speter#include <machine/md_var.h>
75114987Speter#include <machine/pcb.h>
76114987Speter#include <machine/cpufunc.h>
77100384Speter
78100384Speterstatic register_t *ia32_copyout_strings(struct image_params *imgp);
79100384Speterstatic void ia32_setregs(struct thread *td, u_long entry, u_long stack,
80100384Speter    u_long ps_strings);
81120422Speterstatic void ia32_fixlimits(struct image_params *imgp);
82100384Speter
83119334Speterextern struct sysent freebsd32_sysent[];
84100384Speter
85120422SpeterSYSCTL_NODE(_compat, OID_AUTO, ia32, CTLFLAG_RW, 0, "ia32 mode");
86120422Speter
87100384Speterstruct sysentvec ia32_freebsd_sysvec = {
88100384Speter	SYS_MAXSYSCALL,
89119334Speter	freebsd32_sysent,
90100384Speter	0,
91100384Speter	0,
92102808Sjake	NULL,
93100384Speter	0,
94102808Sjake	NULL,
95102808Sjake	NULL,
96100384Speter	elf32_freebsd_fixup,
97114987Speter	ia32_sendsig,
98100384Speter	ia32_sigcode,
99114987Speter	&sz_ia32_sigcode,
100102808Sjake	NULL,
101114987Speter	"FreeBSD ELF32",
102100384Speter	elf32_coredump,
103100384Speter	NULL,
104100384Speter	MINSIGSTKSZ,
105114987Speter	PAGE_SIZE,
106102808Sjake	0,
107119336Speter	FREEBSD32_USRSTACK,
108119336Speter	FREEBSD32_USRSTACK,
109119336Speter	FREEBSD32_PS_STRINGS,
110102808Sjake	VM_PROT_ALL,
111100384Speter	ia32_copyout_strings,
112120422Speter	ia32_setregs,
113120422Speter	ia32_fixlimits
114100384Speter};
115100384Speter
116114987Speter
117119336Speterconst char freebsd32_emul_path[] = "/compat/ia32";
118114987Speter
119100384Speterstatic Elf32_Brandinfo ia32_brand_info = {
120100384Speter						ELFOSABI_FREEBSD,
121100384Speter						EM_386,
122100384Speter						"FreeBSD",
123100384Speter						"/compat/ia32",
124100384Speter						"/usr/libexec/ld-elf.so.1",
125100384Speter						&ia32_freebsd_sysvec
126100384Speter					  };
127100384Speter
128100384SpeterSYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY,
129100384Speter	(sysinit_cfunc_t) elf32_insert_brand_entry,
130100384Speter	&ia32_brand_info);
131100384Speter
132119334Speter/* XXX may be freebsd32 MI */
133100384Speterstatic register_t *
134100384Speteria32_copyout_strings(struct image_params *imgp)
135100384Speter{
136100384Speter	int argc, envc;
137100384Speter	u_int32_t *vectp;
138100384Speter	char *stringp, *destp;
139100384Speter	u_int32_t *stack_base;
140119336Speter	struct freebsd32_ps_strings *arginfo;
141100384Speter	int szsigcode;
142100384Speter
143100384Speter	/*
144100384Speter	 * Calculate string base and vector table pointers.
145100384Speter	 * Also deal with signal trampoline code for this exec type.
146100384Speter	 */
147119336Speter	arginfo = (struct freebsd32_ps_strings *)FREEBSD32_PS_STRINGS;
148100384Speter	szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
149100384Speter	destp =	(caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
150100384Speter		roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
151100384Speter
152100384Speter	/*
153100384Speter	 * install sigcode
154100384Speter	 */
155100384Speter	if (szsigcode)
156100384Speter		copyout(imgp->proc->p_sysent->sv_sigcode,
157100384Speter			((caddr_t)arginfo - szsigcode), szsigcode);
158100384Speter
159100384Speter	/*
160100384Speter	 * If we have a valid auxargs ptr, prepare some room
161100384Speter	 * on the stack.
162100384Speter	 */
163100384Speter	if (imgp->auxargs) {
164100384Speter		/*
165100384Speter		 * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
166100384Speter		 * lower compatibility.
167100384Speter		 */
168100384Speter		imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size
169100384Speter			: (AT_COUNT * 2);
170100384Speter		/*
171100384Speter		 * The '+ 2' is for the null pointers at the end of each of
172100384Speter		 * the arg and env vector sets,and imgp->auxarg_size is room
173100384Speter		 * for argument of Runtime loader.
174100384Speter		 */
175100384Speter		vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 +
176100384Speter				       imgp->auxarg_size) * sizeof(u_int32_t));
177100384Speter
178100384Speter	} else
179100384Speter		/*
180100384Speter		 * The '+ 2' is for the null pointers at the end of each of
181100384Speter		 * the arg and env vector sets
182100384Speter		 */
183100384Speter		vectp = (u_int32_t *)
184100384Speter			(destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t));
185100384Speter
186100384Speter	/*
187100384Speter	 * vectp also becomes our initial stack base
188100384Speter	 */
189100384Speter	stack_base = vectp;
190100384Speter
191100384Speter	stringp = imgp->stringbase;
192100384Speter	argc = imgp->argc;
193100384Speter	envc = imgp->envc;
194100384Speter	/*
195100384Speter	 * Copy out strings - arguments and environment.
196100384Speter	 */
197100384Speter	copyout(stringp, destp, ARG_MAX - imgp->stringspace);
198100384Speter
199100384Speter	/*
200100384Speter	 * Fill in "ps_strings" struct for ps, w, etc.
201100384Speter	 */
202100384Speter	suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
203100384Speter	suword32(&arginfo->ps_nargvstr, argc);
204100384Speter
205100384Speter	/*
206100384Speter	 * Fill in argument portion of vector table.
207100384Speter	 */
208100384Speter	for (; argc > 0; --argc) {
209100384Speter		suword32(vectp++, (u_int32_t)(intptr_t)destp);
210100384Speter		while (*stringp++ != 0)
211100384Speter			destp++;
212100384Speter		destp++;
213100384Speter	}
214100384Speter
215100384Speter	/* a null vector table pointer separates the argp's from the envp's */
216100384Speter	suword32(vectp++, 0);
217100384Speter
218100384Speter	suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
219100384Speter	suword32(&arginfo->ps_nenvstr, envc);
220100384Speter
221100384Speter	/*
222100384Speter	 * Fill in environment portion of vector table.
223100384Speter	 */
224100384Speter	for (; envc > 0; --envc) {
225100384Speter		suword32(vectp++, (u_int32_t)(intptr_t)destp);
226100384Speter		while (*stringp++ != 0)
227100384Speter			destp++;
228100384Speter		destp++;
229100384Speter	}
230100384Speter
231100384Speter	/* end of vector table is a null pointer */
232100384Speter	suword32(vectp, 0);
233100384Speter
234100384Speter	return ((register_t *)stack_base);
235100384Speter}
236100384Speter
237114987Speter/*
238114987Speter * Clear registers on exec
239119334Speter * XXX backend MD
240114987Speter */
241119334Speterextern int _ucode32sel, _udatasel;
242114987Spetervoid
243114987Speteria32_setregs(td, entry, stack, ps_strings)
244114987Speter	struct thread *td;
245114987Speter	u_long entry;
246114987Speter	u_long stack;
247114987Speter	u_long ps_strings;
248100384Speter{
249114987Speter	struct trapframe *regs = td->td_frame;
250114987Speter	struct pcb *pcb = td->td_pcb;
251114987Speter
252114987Speter	wrmsr(MSR_FSBASE, 0);
253114987Speter	wrmsr(MSR_KGSBASE, 0);	/* User value while we're in the kernel */
254114987Speter	pcb->pcb_fsbase = 0;
255114987Speter	pcb->pcb_gsbase = 0;
256114987Speter	load_ds(_udatasel);
257114987Speter	load_es(_udatasel);
258114987Speter	load_fs(_udatasel);
259115006Speter	load_gs(_udatasel);
260114987Speter	pcb->pcb_ds = _udatasel;
261114987Speter	pcb->pcb_es = _udatasel;
262114987Speter	pcb->pcb_fs = _udatasel;
263114987Speter	pcb->pcb_gs = _udatasel;
264100384Speter
265114987Speter	bzero((char *)regs, sizeof(struct trapframe));
266114987Speter	regs->tf_rip = entry;
267114987Speter	regs->tf_rsp = stack;
268114987Speter	regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T);
269114987Speter	regs->tf_ss = _udatasel;
270114987Speter	regs->tf_cs = _ucode32sel;
271114987Speter	regs->tf_rbx = ps_strings;
272100384Speter
273100384Speter	/*
274114987Speter	 * Arrange to trap the next npx or `fwait' instruction (see npx.c
275114987Speter	 * for why fwait must be trapped at least if there is an npx or an
276114987Speter	 * emulator).  This is mainly to handle the case where npx0 is not
277114987Speter	 * configured, since the npx routines normally set up the trap
278114987Speter	 * otherwise.  It should be done only at boot time, but doing it
279114987Speter	 * here allows modifying `npx_exists' for testing the emulator on
280114987Speter	 * systems with an npx.
281100384Speter	 */
282114987Speter	load_cr0(rcr0() | CR0_MP | CR0_TS);
283100384Speter
284114987Speter	fpstate_drop(td);
285100384Speter
286114987Speter	/* Return via doreti so that we can change to a different %cs */
287114987Speter	pcb->pcb_flags |= PCB_FULLCTX;
288100384Speter	td->td_retval[1] = 0;
289100384Speter}
290120422Speter
291120422Speterstatic u_long	ia32_maxdsiz = IA32_MAXDSIZ;
292120422SpeterSYSCTL_ULONG(_compat_ia32, OID_AUTO, maxdsiz, CTLFLAG_RW, &ia32_maxdsiz, 0, "");
293120422Speterstatic u_long	ia32_maxssiz = IA32_MAXSSIZ;
294120422SpeterSYSCTL_ULONG(_compat_ia32, OID_AUTO, maxssiz, CTLFLAG_RW, &ia32_maxssiz, 0, "");
295120422Speterstatic u_long	ia32_maxvmem = IA32_MAXVMEM;
296120422SpeterSYSCTL_ULONG(_compat_ia32, OID_AUTO, maxvmem, CTLFLAG_RW, &ia32_maxvmem, 0, "");
297120422Speter
298120422Speterstatic void
299120422Speteria32_fixlimits(struct image_params *imgp)
300120422Speter{
301120422Speter	struct proc *p = imgp->proc;
302120422Speter
303120422Speter	if (ia32_maxdsiz != 0) {
304120422Speter		if (p->p_rlimit[RLIMIT_DATA].rlim_cur > ia32_maxdsiz ||
305120422Speter		    p->p_rlimit[RLIMIT_DATA].rlim_max > ia32_maxdsiz) {
306120422Speter			if (p->p_limit->p_refcnt > 1) {
307120422Speter				p->p_limit->p_refcnt--;
308120422Speter				p->p_limit = limcopy(p->p_limit);
309120422Speter			}
310120422Speter			if (p->p_rlimit[RLIMIT_DATA].rlim_cur > ia32_maxdsiz)
311120422Speter				p->p_rlimit[RLIMIT_DATA].rlim_cur =
312120422Speter				    ia32_maxdsiz;
313120422Speter			if (p->p_rlimit[RLIMIT_DATA].rlim_max > ia32_maxdsiz)
314120422Speter				p->p_rlimit[RLIMIT_DATA].rlim_max =
315120422Speter				    ia32_maxdsiz;
316120422Speter		}
317120422Speter	}
318120422Speter	if (ia32_maxssiz != 0) {
319120422Speter		if (p->p_rlimit[RLIMIT_STACK].rlim_cur > ia32_maxssiz ||
320120422Speter		    p->p_rlimit[RLIMIT_STACK].rlim_max > ia32_maxssiz) {
321120422Speter			if (p->p_limit->p_refcnt > 1) {
322120422Speter				p->p_limit->p_refcnt--;
323120422Speter				p->p_limit = limcopy(p->p_limit);
324120422Speter			}
325120422Speter			if (p->p_rlimit[RLIMIT_STACK].rlim_cur > ia32_maxssiz)
326120422Speter				p->p_rlimit[RLIMIT_STACK].rlim_cur =
327120422Speter				    ia32_maxssiz;
328120422Speter			if (p->p_rlimit[RLIMIT_STACK].rlim_max > ia32_maxssiz)
329120422Speter				p->p_rlimit[RLIMIT_STACK].rlim_max =
330120422Speter				    ia32_maxssiz;
331120422Speter		}
332120422Speter	}
333120422Speter	if (ia32_maxvmem != 0) {
334120422Speter		if (p->p_rlimit[RLIMIT_VMEM].rlim_cur > ia32_maxvmem ||
335120422Speter		    p->p_rlimit[RLIMIT_VMEM].rlim_max > ia32_maxvmem) {
336120422Speter			if (p->p_limit->p_refcnt > 1) {
337120422Speter				p->p_limit->p_refcnt--;
338120422Speter				p->p_limit = limcopy(p->p_limit);
339120422Speter			}
340120422Speter			if (p->p_rlimit[RLIMIT_VMEM].rlim_cur > ia32_maxvmem)
341120422Speter				p->p_rlimit[RLIMIT_VMEM].rlim_cur =
342120422Speter				    ia32_maxvmem;
343120422Speter			if (p->p_rlimit[RLIMIT_VMEM].rlim_max > ia32_maxvmem)
344120422Speter				p->p_rlimit[RLIMIT_VMEM].rlim_max =
345120422Speter				    ia32_maxvmem;
346120422Speter		}
347120422Speter	}
348120422Speter}
349