ia32_sysvec.c revision 115006
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 * $FreeBSD: head/sys/compat/ia32/ia32_sysvec.c 115006 2003-05-15 00:23:40Z peter $
28100384Speter */
29100384Speter
30114987Speter#include "opt_compat.h"
31114987Speter
32100384Speter#define __ELF_WORD_SIZE 32
33100384Speter
34100384Speter#include <sys/param.h>
35100384Speter#include <sys/exec.h>
36100384Speter#include <sys/fcntl.h>
37100384Speter#include <sys/imgact.h>
38100384Speter#include <sys/kernel.h>
39100384Speter#include <sys/lock.h>
40100384Speter#include <sys/malloc.h>
41100384Speter#include <sys/mutex.h>
42100384Speter#include <sys/mman.h>
43100384Speter#include <sys/namei.h>
44100384Speter#include <sys/pioctl.h>
45100384Speter#include <sys/proc.h>
46100384Speter#include <sys/procfs.h>
47100384Speter#include <sys/resourcevar.h>
48100384Speter#include <sys/systm.h>
49100384Speter#include <sys/signalvar.h>
50100384Speter#include <sys/stat.h>
51100384Speter#include <sys/sx.h>
52100384Speter#include <sys/syscall.h>
53100384Speter#include <sys/sysctl.h>
54100384Speter#include <sys/sysent.h>
55100384Speter#include <sys/vnode.h>
56100384Speter#include <sys/imgact_elf.h>
57100384Speter
58100384Speter#include <vm/vm.h>
59100384Speter#include <vm/vm_kern.h>
60100384Speter#include <vm/vm_param.h>
61100384Speter#include <vm/pmap.h>
62100384Speter#include <vm/vm_map.h>
63100384Speter#include <vm/vm_object.h>
64100384Speter#include <vm/vm_extern.h>
65100384Speter
66114987Speter#include <amd64/ia32/ia32_util.h>
67114987Speter#include <amd64/ia32/ia32_proto.h>
68114987Speter#include <amd64/ia32/ia32_signal.h>
69114987Speter#include <machine/psl.h>
70114987Speter#include <machine/segments.h>
71114987Speter#include <machine/specialreg.h>
72100384Speter#include <machine/frame.h>
73100384Speter#include <machine/md_var.h>
74114987Speter#include <machine/pcb.h>
75114987Speter#include <machine/cpufunc.h>
76100384Speter
77100384Speterstatic register_t *ia32_copyout_strings(struct image_params *imgp);
78100384Speterstatic void ia32_setregs(struct thread *td, u_long entry, u_long stack,
79100384Speter    u_long ps_strings);
80100384Speter
81100384Speterextern struct sysent ia32_sysent[];
82100384Speter
83100384Speterstruct sysentvec ia32_freebsd_sysvec = {
84100384Speter	SYS_MAXSYSCALL,
85100384Speter	ia32_sysent,
86100384Speter	0,
87100384Speter	0,
88102808Sjake	NULL,
89100384Speter	0,
90102808Sjake	NULL,
91102808Sjake	NULL,
92100384Speter	elf32_freebsd_fixup,
93114987Speter	ia32_sendsig,
94100384Speter	ia32_sigcode,
95114987Speter	&sz_ia32_sigcode,
96102808Sjake	NULL,
97114987Speter	"FreeBSD ELF32",
98100384Speter	elf32_coredump,
99100384Speter	NULL,
100100384Speter	MINSIGSTKSZ,
101114987Speter	PAGE_SIZE,
102102808Sjake	0,
103114987Speter	USRSTACK,
104114987Speter	USRSTACK,
105114987Speter	PS_STRINGS,
106102808Sjake	VM_PROT_ALL,
107100384Speter	ia32_copyout_strings,
108100384Speter	ia32_setregs
109100384Speter};
110100384Speter
111114987Speter
112114987Speter
113100384Speterstatic Elf32_Brandinfo ia32_brand_info = {
114100384Speter						ELFOSABI_FREEBSD,
115100384Speter						EM_386,
116100384Speter						"FreeBSD",
117100384Speter						"/compat/ia32",
118100384Speter						"/usr/libexec/ld-elf.so.1",
119100384Speter						&ia32_freebsd_sysvec
120100384Speter					  };
121100384Speter
122100384SpeterSYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY,
123100384Speter	(sysinit_cfunc_t) elf32_insert_brand_entry,
124100384Speter	&ia32_brand_info);
125100384Speter
126114987Speterextern int _ucode32sel, _udatasel;
127114987Speter
128100384Speterstatic register_t *
129100384Speteria32_copyout_strings(struct image_params *imgp)
130100384Speter{
131100384Speter	int argc, envc;
132100384Speter	u_int32_t *vectp;
133100384Speter	char *stringp, *destp;
134100384Speter	u_int32_t *stack_base;
135100384Speter	struct ia32_ps_strings *arginfo;
136100384Speter	int szsigcode;
137100384Speter
138100384Speter	/*
139100384Speter	 * Calculate string base and vector table pointers.
140100384Speter	 * Also deal with signal trampoline code for this exec type.
141100384Speter	 */
142114987Speter	arginfo = (struct ia32_ps_strings *)PS_STRINGS;
143100384Speter	szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
144100384Speter	destp =	(caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
145100384Speter		roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
146100384Speter
147100384Speter	/*
148100384Speter	 * install sigcode
149100384Speter	 */
150100384Speter	if (szsigcode)
151100384Speter		copyout(imgp->proc->p_sysent->sv_sigcode,
152100384Speter			((caddr_t)arginfo - szsigcode), szsigcode);
153100384Speter
154100384Speter	/*
155100384Speter	 * If we have a valid auxargs ptr, prepare some room
156100384Speter	 * on the stack.
157100384Speter	 */
158100384Speter	if (imgp->auxargs) {
159100384Speter		/*
160100384Speter		 * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
161100384Speter		 * lower compatibility.
162100384Speter		 */
163100384Speter		imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size
164100384Speter			: (AT_COUNT * 2);
165100384Speter		/*
166100384Speter		 * The '+ 2' is for the null pointers at the end of each of
167100384Speter		 * the arg and env vector sets,and imgp->auxarg_size is room
168100384Speter		 * for argument of Runtime loader.
169100384Speter		 */
170100384Speter		vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 +
171100384Speter				       imgp->auxarg_size) * sizeof(u_int32_t));
172100384Speter
173100384Speter	} else
174100384Speter		/*
175100384Speter		 * The '+ 2' is for the null pointers at the end of each of
176100384Speter		 * the arg and env vector sets
177100384Speter		 */
178100384Speter		vectp = (u_int32_t *)
179100384Speter			(destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t));
180100384Speter
181100384Speter	/*
182100384Speter	 * vectp also becomes our initial stack base
183100384Speter	 */
184100384Speter	stack_base = vectp;
185100384Speter
186100384Speter	stringp = imgp->stringbase;
187100384Speter	argc = imgp->argc;
188100384Speter	envc = imgp->envc;
189100384Speter	/*
190100384Speter	 * Copy out strings - arguments and environment.
191100384Speter	 */
192100384Speter	copyout(stringp, destp, ARG_MAX - imgp->stringspace);
193100384Speter
194100384Speter	/*
195100384Speter	 * Fill in "ps_strings" struct for ps, w, etc.
196100384Speter	 */
197100384Speter	suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
198100384Speter	suword32(&arginfo->ps_nargvstr, argc);
199100384Speter
200100384Speter	/*
201100384Speter	 * Fill in argument portion of vector table.
202100384Speter	 */
203100384Speter	for (; argc > 0; --argc) {
204100384Speter		suword32(vectp++, (u_int32_t)(intptr_t)destp);
205100384Speter		while (*stringp++ != 0)
206100384Speter			destp++;
207100384Speter		destp++;
208100384Speter	}
209100384Speter
210100384Speter	/* a null vector table pointer separates the argp's from the envp's */
211100384Speter	suword32(vectp++, 0);
212100384Speter
213100384Speter	suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
214100384Speter	suword32(&arginfo->ps_nenvstr, envc);
215100384Speter
216100384Speter	/*
217100384Speter	 * Fill in environment portion of vector table.
218100384Speter	 */
219100384Speter	for (; envc > 0; --envc) {
220100384Speter		suword32(vectp++, (u_int32_t)(intptr_t)destp);
221100384Speter		while (*stringp++ != 0)
222100384Speter			destp++;
223100384Speter		destp++;
224100384Speter	}
225100384Speter
226100384Speter	/* end of vector table is a null pointer */
227100384Speter	suword32(vectp, 0);
228100384Speter
229100384Speter	return ((register_t *)stack_base);
230100384Speter}
231100384Speter
232114987Speter/*
233114987Speter * Clear registers on exec
234114987Speter */
235114987Spetervoid
236114987Speteria32_setregs(td, entry, stack, ps_strings)
237114987Speter	struct thread *td;
238114987Speter	u_long entry;
239114987Speter	u_long stack;
240114987Speter	u_long ps_strings;
241100384Speter{
242114987Speter	struct trapframe *regs = td->td_frame;
243114987Speter	struct pcb *pcb = td->td_pcb;
244114987Speter
245114987Speter	wrmsr(MSR_FSBASE, 0);
246114987Speter	wrmsr(MSR_KGSBASE, 0);	/* User value while we're in the kernel */
247114987Speter	pcb->pcb_fsbase = 0;
248114987Speter	pcb->pcb_gsbase = 0;
249114987Speter	load_ds(_udatasel);
250114987Speter	load_es(_udatasel);
251114987Speter	load_fs(_udatasel);
252115006Speter	load_gs(_udatasel);
253114987Speter	pcb->pcb_ds = _udatasel;
254114987Speter	pcb->pcb_es = _udatasel;
255114987Speter	pcb->pcb_fs = _udatasel;
256114987Speter	pcb->pcb_gs = _udatasel;
257100384Speter
258114987Speter	bzero((char *)regs, sizeof(struct trapframe));
259114987Speter	regs->tf_rip = entry;
260114987Speter	regs->tf_rsp = stack;
261114987Speter	regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T);
262114987Speter	regs->tf_ss = _udatasel;
263114987Speter	regs->tf_cs = _ucode32sel;
264114987Speter	regs->tf_rbx = ps_strings;
265100384Speter
266100384Speter	/*
267114987Speter	 * Arrange to trap the next npx or `fwait' instruction (see npx.c
268114987Speter	 * for why fwait must be trapped at least if there is an npx or an
269114987Speter	 * emulator).  This is mainly to handle the case where npx0 is not
270114987Speter	 * configured, since the npx routines normally set up the trap
271114987Speter	 * otherwise.  It should be done only at boot time, but doing it
272114987Speter	 * here allows modifying `npx_exists' for testing the emulator on
273114987Speter	 * systems with an npx.
274100384Speter	 */
275114987Speter	load_cr0(rcr0() | CR0_MP | CR0_TS);
276100384Speter
277114987Speter	fpstate_drop(td);
278100384Speter
279114987Speter	/* Return via doreti so that we can change to a different %cs */
280114987Speter	pcb->pcb_flags |= PCB_FULLCTX;
281100384Speter	td->td_retval[1] = 0;
282100384Speter}
283