xref: /freebsd/sys/i386/linux/linux_sysvec.c (revision aad9af2ba3fb10cf1f80ac6117e37f97d38ccee0)
1d66a5066SPeter Wemm /*-
2e1743d02SSøren Schmidt  * Copyright (c) 1994-1996 S�ren Schmidt
3d66a5066SPeter Wemm  * All rights reserved.
4d66a5066SPeter Wemm  *
5d66a5066SPeter Wemm  * Redistribution and use in source and binary forms, with or without
6d66a5066SPeter Wemm  * modification, are permitted provided that the following conditions
7d66a5066SPeter Wemm  * are met:
8d66a5066SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
9d66a5066SPeter Wemm  *    notice, this list of conditions and the following disclaimer
10d66a5066SPeter Wemm  *    in this position and unchanged.
11d66a5066SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
12d66a5066SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
13d66a5066SPeter Wemm  *    documentation and/or other materials provided with the distribution.
14d66a5066SPeter Wemm  * 3. The name of the author may not be used to endorse or promote products
15d66a5066SPeter Wemm  *    derived from this software withough specific prior written permission
16d66a5066SPeter Wemm  *
17d66a5066SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18d66a5066SPeter Wemm  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19d66a5066SPeter Wemm  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20d66a5066SPeter Wemm  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21d66a5066SPeter Wemm  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22d66a5066SPeter Wemm  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23d66a5066SPeter Wemm  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24d66a5066SPeter Wemm  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25d66a5066SPeter Wemm  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26d66a5066SPeter Wemm  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27d66a5066SPeter Wemm  *
28aad9af2bSBruce Evans  *  $Id: linux_sysvec.c,v 1.7 1996/06/18 05:15:53 dyson Exp $
29d66a5066SPeter Wemm  */
30d66a5066SPeter Wemm 
31d66a5066SPeter Wemm /* XXX we use functions that might not exist. */
32d66a5066SPeter Wemm #define	COMPAT_43	1
33d66a5066SPeter Wemm 
34d66a5066SPeter Wemm #include <sys/param.h>
355e26fb6fSJordan K. Hubbard #include <sys/buf.h>
36aad9af2bSBruce Evans #include <sys/proc.h>
37d66a5066SPeter Wemm #include <sys/systm.h>
38d66a5066SPeter Wemm #include <sys/sysproto.h>
39d66a5066SPeter Wemm #include <sys/sysent.h>
40d66a5066SPeter Wemm #include <sys/imgact.h>
41e1743d02SSøren Schmidt #include <sys/imgact_elf.h>
42d66a5066SPeter Wemm #include <sys/signalvar.h>
43e1743d02SSøren Schmidt #include <sys/malloc.h>
44d66a5066SPeter Wemm #include <vm/vm.h>
45d66a5066SPeter Wemm #include <vm/vm_param.h>
46d66a5066SPeter Wemm #include <vm/vm_prot.h>
47d66a5066SPeter Wemm #include <vm/lock.h>
48d66a5066SPeter Wemm #include <vm/vm_kern.h>
49d66a5066SPeter Wemm #include <vm/vm_object.h>
50d66a5066SPeter Wemm #include <vm/vm_page.h>
51d66a5066SPeter Wemm #include <vm/vm_map.h>
52d66a5066SPeter Wemm #include <vm/vm_pager.h>
53d66a5066SPeter Wemm #include <vm/vm_extern.h>
54d66a5066SPeter Wemm #include <sys/user.h>
55d66a5066SPeter Wemm #include <sys/exec.h>
565cf588ebSPeter Wemm #include <sys/kernel.h>
57d66a5066SPeter Wemm #include <machine/cpu.h>
58d66a5066SPeter Wemm #include <machine/frame.h>
59d66a5066SPeter Wemm #include <machine/reg.h>
60d66a5066SPeter Wemm #include <machine/specialreg.h>
61d66a5066SPeter Wemm #include <machine/psl.h>
62d66a5066SPeter Wemm #include <machine/sysarch.h>
63d66a5066SPeter Wemm #include <machine/md_var.h>
64d66a5066SPeter Wemm 
65d66a5066SPeter Wemm #include <i386/linux/linux.h>
66d66a5066SPeter Wemm #include <i386/linux/linux_proto.h>
67e1743d02SSøren Schmidt 
68e1743d02SSøren Schmidt int	linux_fixup __P((int **stack_base, struct image_params *iparams));
69e1743d02SSøren Schmidt int	elf_linux_fixup __P((int **stack_base, struct image_params *iparams));
70e1743d02SSøren Schmidt void	linux_prepsyscall __P((struct trapframe *tf, int *args, u_int *code, caddr_t *params));
71b36546f6SPeter Wemm void    linux_sendsig __P((sig_t catcher, int sig, int mask, u_long code));
72d66a5066SPeter Wemm 
73d66a5066SPeter Wemm /*
74d66a5066SPeter Wemm  * Linux syscalls return negative errno's, we do positive and map them
75d66a5066SPeter Wemm  */
76d66a5066SPeter Wemm int bsd_to_linux_errno[ELAST] = {
77d66a5066SPeter Wemm   	-0,  -1,  -2,  -3,  -4,  -5,  -6,  -7,  -8,  -9,
78d66a5066SPeter Wemm  	-10, -35, -12, -13, -14, -15, -16, -17, -18, -19,
79d66a5066SPeter Wemm  	-20, -21, -22, -23, -24, -25, -26, -27, -28, -29,
80d66a5066SPeter Wemm  	-30, -31, -32, -33, -34, -11,-115,-114, -88, -89,
81d66a5066SPeter Wemm  	-90, -91, -92, -93, -94, -95, -96, -97, -98, -99,
82d66a5066SPeter Wemm 	-100,-101,-102,-103,-104,-105,-106,-107,-108,-109,
83d66a5066SPeter Wemm 	-110,-111, -40, -36,-112,-113, -39, -11, -87,-122,
84d66a5066SPeter Wemm 	-116, -66,  -6,  -6,  -6,  -6,  -6, -37, -38,  -9,
85d66a5066SPeter Wemm   	-6,
86d66a5066SPeter Wemm };
87d66a5066SPeter Wemm 
88d66a5066SPeter Wemm int bsd_to_linux_signal[NSIG] = {
89d66a5066SPeter Wemm 	0, LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT,
90d66a5066SPeter Wemm 	LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGABRT, 0,
91d66a5066SPeter Wemm 	LINUX_SIGFPE, LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV,
92d66a5066SPeter Wemm 	0, LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM,
93d66a5066SPeter Wemm 	LINUX_SIGURG, LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT,
94d66a5066SPeter Wemm 	LINUX_SIGCHLD, LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO,
95d66a5066SPeter Wemm 	LINUX_SIGXCPU, LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF,
96d66a5066SPeter Wemm 	LINUX_SIGWINCH, 0, LINUX_SIGUSR1, LINUX_SIGUSR2
97d66a5066SPeter Wemm };
98d66a5066SPeter Wemm 
99d66a5066SPeter Wemm int linux_to_bsd_signal[LINUX_NSIG] = {
100d66a5066SPeter Wemm 	0, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGEMT,
101d66a5066SPeter Wemm 	SIGFPE, SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM,
102d66a5066SPeter Wemm 	SIGBUS, SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGIO,
103d66a5066SPeter Wemm 	SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH, SIGURG, SIGURG, 0
104d66a5066SPeter Wemm };
105d66a5066SPeter Wemm 
106d66a5066SPeter Wemm int linux_fixup(int **stack_base, struct image_params *imgp)
107d66a5066SPeter Wemm {
108d66a5066SPeter Wemm 	int *argv, *envp;
109d66a5066SPeter Wemm 
110d66a5066SPeter Wemm 	argv = *stack_base;
111d66a5066SPeter Wemm 	envp = *stack_base + (imgp->argc + 1);
112d66a5066SPeter Wemm 	(*stack_base)--;
113d66a5066SPeter Wemm 	**stack_base = (int)envp;
114d66a5066SPeter Wemm 	(*stack_base)--;
115d66a5066SPeter Wemm 	**stack_base = (int)argv;
116d66a5066SPeter Wemm 	(*stack_base)--;
117d66a5066SPeter Wemm 	**stack_base = (int)imgp->argc;
118e1743d02SSøren Schmidt 	return 0;
119d66a5066SPeter Wemm }
120d66a5066SPeter Wemm 
121e1743d02SSøren Schmidt int elf_linux_fixup(int **stack_base, struct image_params *imgp)
122e1743d02SSøren Schmidt {
123e1743d02SSøren Schmidt 	Elf32_Auxargs *args = (Elf32_Auxargs *)imgp->auxargs;
124e1743d02SSøren Schmidt 	int *pos;
125d66a5066SPeter Wemm 
126e1743d02SSøren Schmidt 	pos = *stack_base + (imgp->argc + imgp->envc + 2);
127e1743d02SSøren Schmidt 
128e1743d02SSøren Schmidt 	if (args->trace) {
129e1743d02SSøren Schmidt 		AUXARGS_ENTRY(pos, AT_DEBUG, 1);
130e1743d02SSøren Schmidt 	}
131e1743d02SSøren Schmidt 	if (args->execfd != -1) {
132e1743d02SSøren Schmidt 		AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
133e1743d02SSøren Schmidt 	}
134e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
135e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
136e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
137e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_PAGESZ, args->pagesz);
138e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
139e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
140e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_BASE, args->base);
141e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_cred->p_ruid);
142e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_cred->p_svuid);
143e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_cred->p_rgid);
144e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_cred->p_svgid);
145e1743d02SSøren Schmidt 	AUXARGS_ENTRY(pos, AT_NULL, 0);
146e1743d02SSøren Schmidt 
147e1743d02SSøren Schmidt 	free(imgp->auxargs, M_TEMP);
148e1743d02SSøren Schmidt 	imgp->auxargs = NULL;
149e1743d02SSøren Schmidt 
150e1743d02SSøren Schmidt 	(*stack_base)--;
151e1743d02SSøren Schmidt 	**stack_base = (int)imgp->argc;
152e1743d02SSøren Schmidt 	return 0;
153e1743d02SSøren Schmidt }
154d66a5066SPeter Wemm 
155d66a5066SPeter Wemm extern int _ucodesel, _udatasel;
156d66a5066SPeter Wemm 
157d66a5066SPeter Wemm /*
158d66a5066SPeter Wemm  * Send an interrupt to process.
159d66a5066SPeter Wemm  *
160d66a5066SPeter Wemm  * Stack is set up to allow sigcode stored
161d66a5066SPeter Wemm  * in u. to call routine, followed by kcall
162d66a5066SPeter Wemm  * to sigreturn routine below.  After sigreturn
163d66a5066SPeter Wemm  * resets the signal mask, the stack, and the
164d66a5066SPeter Wemm  * frame pointer, it returns to the user
165d66a5066SPeter Wemm  * specified pc, psl.
166d66a5066SPeter Wemm  */
167d66a5066SPeter Wemm 
168e1743d02SSøren Schmidt void
169b36546f6SPeter Wemm linux_sendsig(sig_t catcher, int sig, int mask, u_long code)
170d66a5066SPeter Wemm {
171d66a5066SPeter Wemm 	register struct proc *p = curproc;
172d66a5066SPeter Wemm 	register int *regs;
173d66a5066SPeter Wemm 	struct linux_sigframe *fp, frame;
174d66a5066SPeter Wemm 	struct sigacts *psp = p->p_sigacts;
175d66a5066SPeter Wemm 	int oonstack;
176d66a5066SPeter Wemm 
177d66a5066SPeter Wemm 	regs = p->p_md.md_regs;
178d66a5066SPeter Wemm 	oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
179d66a5066SPeter Wemm 
180d66a5066SPeter Wemm #ifdef DEBUG
181b36546f6SPeter Wemm 	printf("Linux-emul(%d): linux_sendsig(%8x, %d, %d, %ld)\n",
182d66a5066SPeter Wemm 		p->p_pid, catcher, sig, mask, code);
183d66a5066SPeter Wemm #endif
184d66a5066SPeter Wemm 	/*
185d66a5066SPeter Wemm 	 * Allocate space for the signal handler context.
186d66a5066SPeter Wemm 	 */
187d66a5066SPeter Wemm 	if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
188d66a5066SPeter Wemm 	    (psp->ps_sigonstack & sigmask(sig))) {
189d66a5066SPeter Wemm 		fp = (struct linux_sigframe *)(psp->ps_sigstk.ss_sp +
190d66a5066SPeter Wemm 		    psp->ps_sigstk.ss_size - sizeof(struct linux_sigframe));
191d66a5066SPeter Wemm 		psp->ps_sigstk.ss_flags |= SS_ONSTACK;
192d66a5066SPeter Wemm 	} else {
193d66a5066SPeter Wemm 		fp = (struct linux_sigframe *)regs[tESP] - 1;
194d66a5066SPeter Wemm 	}
195d66a5066SPeter Wemm 
196d66a5066SPeter Wemm 	/*
197d66a5066SPeter Wemm 	 * grow() will return FALSE if the fp will not fit inside the stack
198d66a5066SPeter Wemm 	 *	and the stack can not be grown. useracc will return FALSE
199d66a5066SPeter Wemm 	 *	if access is denied.
200d66a5066SPeter Wemm 	 */
201d66a5066SPeter Wemm 	if ((grow(p, (int)fp) == FALSE) ||
202d66a5066SPeter Wemm 	    (useracc((caddr_t)fp, sizeof (struct linux_sigframe), B_WRITE) == FALSE)) {
203d66a5066SPeter Wemm 		/*
204d66a5066SPeter Wemm 		 * Process has trashed its stack; give it an illegal
205d66a5066SPeter Wemm 		 * instruction to halt it in its tracks.
206d66a5066SPeter Wemm 		 */
207d66a5066SPeter Wemm 		SIGACTION(p, SIGILL) = SIG_DFL;
208d66a5066SPeter Wemm 		sig = sigmask(SIGILL);
209d66a5066SPeter Wemm 		p->p_sigignore &= ~sig;
210d66a5066SPeter Wemm 		p->p_sigcatch &= ~sig;
211d66a5066SPeter Wemm 		p->p_sigmask &= ~sig;
212d66a5066SPeter Wemm 		psignal(p, SIGILL);
213d66a5066SPeter Wemm 		return;
214d66a5066SPeter Wemm 	}
215d66a5066SPeter Wemm 
216d66a5066SPeter Wemm 	/*
217d66a5066SPeter Wemm 	 * Build the argument list for the signal handler.
218d66a5066SPeter Wemm 	 */
219d66a5066SPeter Wemm 	if (p->p_sysent->sv_sigtbl) {
220d66a5066SPeter Wemm 		if (sig < p->p_sysent->sv_sigsize)
221d66a5066SPeter Wemm 			sig = p->p_sysent->sv_sigtbl[sig];
222d66a5066SPeter Wemm 		else
223d66a5066SPeter Wemm 			sig = p->p_sysent->sv_sigsize + 1;
224d66a5066SPeter Wemm 	}
225d66a5066SPeter Wemm 
226d66a5066SPeter Wemm 	frame.sf_handler = catcher;
227d66a5066SPeter Wemm 	frame.sf_sig = sig;
228d66a5066SPeter Wemm 
229d66a5066SPeter Wemm 	/*
230d66a5066SPeter Wemm 	 * Build the signal context to be used by sigreturn.
231d66a5066SPeter Wemm 	 */
232d66a5066SPeter Wemm 	frame.sf_sc.sc_mask   = mask;
233d66a5066SPeter Wemm 	__asm("movl %%gs,%w0" : "=r" (frame.sf_sc.sc_gs));
234d66a5066SPeter Wemm 	__asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs));
235d66a5066SPeter Wemm 	frame.sf_sc.sc_es     = regs[tES];
236d66a5066SPeter Wemm 	frame.sf_sc.sc_ds     = regs[tDS];
237d66a5066SPeter Wemm 	frame.sf_sc.sc_edi    = regs[tEDI];
238d66a5066SPeter Wemm 	frame.sf_sc.sc_esi    = regs[tESI];
239d66a5066SPeter Wemm 	frame.sf_sc.sc_ebp    = regs[tEBP];
240d66a5066SPeter Wemm 	frame.sf_sc.sc_ebx    = regs[tEBX];
241d66a5066SPeter Wemm 	frame.sf_sc.sc_edx    = regs[tEDX];
242d66a5066SPeter Wemm 	frame.sf_sc.sc_ecx    = regs[tECX];
243d66a5066SPeter Wemm 	frame.sf_sc.sc_eax    = regs[tEAX];
244d66a5066SPeter Wemm 	frame.sf_sc.sc_eip    = regs[tEIP];
245d66a5066SPeter Wemm 	frame.sf_sc.sc_cs     = regs[tCS];
246d66a5066SPeter Wemm 	frame.sf_sc.sc_eflags = regs[tEFLAGS];
247d66a5066SPeter Wemm 	frame.sf_sc.sc_esp_at_signal = regs[tESP];
248d66a5066SPeter Wemm 	frame.sf_sc.sc_ss     = regs[tSS];
249d66a5066SPeter Wemm 	frame.sf_sc.sc_err    = regs[tERR];
250d66a5066SPeter Wemm 	frame.sf_sc.sc_trapno = code;	/* XXX ???? */
251d66a5066SPeter Wemm 
252d66a5066SPeter Wemm 	if (copyout(&frame, fp, sizeof(frame)) != 0) {
253d66a5066SPeter Wemm 		/*
254d66a5066SPeter Wemm 		 * Process has trashed its stack; give it an illegal
255d66a5066SPeter Wemm 		 * instruction to halt it in its tracks.
256d66a5066SPeter Wemm 		 */
257d66a5066SPeter Wemm 		sigexit(p, SIGILL);
258d66a5066SPeter Wemm 		/* NOTREACHED */
259d66a5066SPeter Wemm 	}
260d66a5066SPeter Wemm 
261d66a5066SPeter Wemm 	/*
262d66a5066SPeter Wemm 	 * Build context to run handler in.
263d66a5066SPeter Wemm 	 */
264d66a5066SPeter Wemm 	regs[tESP] = (int)fp;
265d66a5066SPeter Wemm 	regs[tEIP] = (int)(((char *)PS_STRINGS) - *(p->p_sysent->sv_szsigcode));
266d66a5066SPeter Wemm 	regs[tEFLAGS] &= ~PSL_VM;
267d66a5066SPeter Wemm 	regs[tCS] = _ucodesel;
268d66a5066SPeter Wemm 	regs[tDS] = _udatasel;
269d66a5066SPeter Wemm 	regs[tES] = _udatasel;
270d66a5066SPeter Wemm 	regs[tSS] = _udatasel;
271d66a5066SPeter Wemm }
272d66a5066SPeter Wemm 
273d66a5066SPeter Wemm /*
274d66a5066SPeter Wemm  * System call to cleanup state after a signal
275d66a5066SPeter Wemm  * has been taken.  Reset signal mask and
276d66a5066SPeter Wemm  * stack state from context left by sendsig (above).
277d66a5066SPeter Wemm  * Return to previous pc and psl as specified by
278d66a5066SPeter Wemm  * context left by sendsig. Check carefully to
279d66a5066SPeter Wemm  * make sure that the user has not modified the
280d66a5066SPeter Wemm  * psl to gain improper privileges or to cause
281d66a5066SPeter Wemm  * a machine fault.
282d66a5066SPeter Wemm  */
283d66a5066SPeter Wemm int
284d66a5066SPeter Wemm linux_sigreturn(p, args, retval)
285d66a5066SPeter Wemm 	struct proc *p;
286d66a5066SPeter Wemm 	struct linux_sigreturn_args *args;
287d66a5066SPeter Wemm 	int *retval;
288d66a5066SPeter Wemm {
289d66a5066SPeter Wemm 	struct linux_sigcontext *scp, context;
290d66a5066SPeter Wemm 	register int *regs;
291d66a5066SPeter Wemm 	int eflags;
292d66a5066SPeter Wemm 
293d66a5066SPeter Wemm 	regs = p->p_md.md_regs;
294d66a5066SPeter Wemm 
295d66a5066SPeter Wemm #ifdef DEBUG
296d66a5066SPeter Wemm 	printf("Linux-emul(%d): linux_sigreturn(%8x)\n", p->p_pid, args->scp);
297d66a5066SPeter Wemm #endif
298d66a5066SPeter Wemm 	/*
299d66a5066SPeter Wemm 	 * The trampoline code hands us the context.
300d66a5066SPeter Wemm 	 * It is unsafe to keep track of it ourselves, in the event that a
301d66a5066SPeter Wemm 	 * program jumps out of a signal handler.
302d66a5066SPeter Wemm 	 */
303d66a5066SPeter Wemm 	scp = args->scp;
304d66a5066SPeter Wemm 	if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
305d66a5066SPeter Wemm 		return (EFAULT);
306d66a5066SPeter Wemm 
307d66a5066SPeter Wemm 	/*
308d66a5066SPeter Wemm 	 * Check for security violations.
309d66a5066SPeter Wemm 	 */
310d66a5066SPeter Wemm #define	EFLAGS_SECURE(ef, oef)	((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
311d66a5066SPeter Wemm 	eflags = context.sc_eflags;
312d66a5066SPeter Wemm 	/*
313d66a5066SPeter Wemm 	 * XXX do allow users to change the privileged flag PSL_RF.  The
314d66a5066SPeter Wemm 	 * cpu sets PSL_RF in tf_eflags for faults.  Debuggers should
315d66a5066SPeter Wemm 	 * sometimes set it there too.  tf_eflags is kept in the signal
316d66a5066SPeter Wemm 	 * context during signal handling and there is no other place
317d66a5066SPeter Wemm 	 * to remember it, so the PSL_RF bit may be corrupted by the
318d66a5066SPeter Wemm 	 * signal handler without us knowing.  Corruption of the PSL_RF
319d66a5066SPeter Wemm 	 * bit at worst causes one more or one less debugger trap, so
320d66a5066SPeter Wemm 	 * allowing it is fairly harmless.
321d66a5066SPeter Wemm 	 */
322d66a5066SPeter Wemm 	if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs[tEFLAGS] & ~PSL_RF)) {
323d66a5066SPeter Wemm     		return(EINVAL);
324d66a5066SPeter Wemm 	}
325d66a5066SPeter Wemm 
326d66a5066SPeter Wemm 	/*
327d66a5066SPeter Wemm 	 * Don't allow users to load a valid privileged %cs.  Let the
328d66a5066SPeter Wemm 	 * hardware check for invalid selectors, excess privilege in
329d66a5066SPeter Wemm 	 * other selectors, invalid %eip's and invalid %esp's.
330d66a5066SPeter Wemm 	 */
331d66a5066SPeter Wemm #define	CS_SECURE(cs)	(ISPL(cs) == SEL_UPL)
332d66a5066SPeter Wemm 	if (!CS_SECURE(context.sc_cs)) {
333d66a5066SPeter Wemm 		trapsignal(p, SIGBUS, T_PROTFLT);
334d66a5066SPeter Wemm 		return(EINVAL);
335d66a5066SPeter Wemm 	}
336d66a5066SPeter Wemm 
337d66a5066SPeter Wemm 	p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
338d66a5066SPeter Wemm 	p->p_sigmask = context.sc_mask &~
339d66a5066SPeter Wemm 		(sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP));
340d66a5066SPeter Wemm 	/*
341d66a5066SPeter Wemm 	 * Restore signal context.
342d66a5066SPeter Wemm 	 */
343d66a5066SPeter Wemm 	/* %fs and %gs were restored by the trampoline. */
344d66a5066SPeter Wemm 	regs[tES]     = context.sc_es;
345d66a5066SPeter Wemm 	regs[tDS]     = context.sc_ds;
346d66a5066SPeter Wemm 	regs[tEDI]    = context.sc_edi;
347d66a5066SPeter Wemm 	regs[tESI]    = context.sc_esi;
348d66a5066SPeter Wemm 	regs[tEBP]    = context.sc_ebp;
349d66a5066SPeter Wemm 	regs[tEBX]    = context.sc_ebx;
350d66a5066SPeter Wemm 	regs[tEDX]    = context.sc_edx;
351d66a5066SPeter Wemm 	regs[tECX]    = context.sc_ecx;
352d66a5066SPeter Wemm 	regs[tEAX]    = context.sc_eax;
353d66a5066SPeter Wemm 	regs[tEIP]    = context.sc_eip;
354d66a5066SPeter Wemm 	regs[tCS]     = context.sc_cs;
355d66a5066SPeter Wemm 	regs[tEFLAGS] = eflags;
356d66a5066SPeter Wemm 	regs[tESP]    = context.sc_esp_at_signal;
357d66a5066SPeter Wemm 	regs[tSS]     = context.sc_ss;
358d66a5066SPeter Wemm 
359d66a5066SPeter Wemm 	return (EJUSTRETURN);
360d66a5066SPeter Wemm }
361d66a5066SPeter Wemm 
362e1743d02SSøren Schmidt void
363d66a5066SPeter Wemm linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params)
364d66a5066SPeter Wemm {
365d66a5066SPeter Wemm 	args[0] = tf->tf_ebx;
366d66a5066SPeter Wemm 	args[1] = tf->tf_ecx;
367d66a5066SPeter Wemm 	args[2] = tf->tf_edx;
368d66a5066SPeter Wemm 	args[3] = tf->tf_esi;
369d66a5066SPeter Wemm 	args[4] = tf->tf_edi;
370d66a5066SPeter Wemm 	*params = NULL;		/* no copyin */
371d66a5066SPeter Wemm }
372d66a5066SPeter Wemm 
373d66a5066SPeter Wemm struct sysentvec linux_sysvec = {
374e1743d02SSøren Schmidt 	LINUX_SYS_MAXSYSCALL,
375d66a5066SPeter Wemm 	linux_sysent,
376d66a5066SPeter Wemm 	0xff,
377d66a5066SPeter Wemm 	NSIG,
378d66a5066SPeter Wemm 	bsd_to_linux_signal,
379d66a5066SPeter Wemm 	ELAST,
380d66a5066SPeter Wemm 	bsd_to_linux_errno,
381d66a5066SPeter Wemm 	linux_fixup,
382d66a5066SPeter Wemm 	linux_sendsig,
383d66a5066SPeter Wemm 	linux_sigcode,
384d66a5066SPeter Wemm 	&linux_szsigcode,
385d66a5066SPeter Wemm 	linux_prepsyscall,
3866ead3eddSJohn Dyson 	"Linux a.out"
387d66a5066SPeter Wemm };
388e1743d02SSøren Schmidt 
389e1743d02SSøren Schmidt struct sysentvec elf_linux_sysvec = {
390e1743d02SSøren Schmidt         LINUX_SYS_MAXSYSCALL,
391e1743d02SSøren Schmidt         linux_sysent,
392e1743d02SSøren Schmidt         0xff,
393e1743d02SSøren Schmidt         NSIG,
394e1743d02SSøren Schmidt         bsd_to_linux_signal,
395e1743d02SSøren Schmidt         ELAST,
396e1743d02SSøren Schmidt         bsd_to_linux_errno,
397e1743d02SSøren Schmidt         elf_linux_fixup,
398e1743d02SSøren Schmidt         linux_sendsig,
399e1743d02SSøren Schmidt         linux_sigcode,
400e1743d02SSøren Schmidt         &linux_szsigcode,
401e1743d02SSøren Schmidt         linux_prepsyscall,
4026ead3eddSJohn Dyson 	"Linux ELF"
403e1743d02SSøren Schmidt };
404e1743d02SSøren Schmidt 
4055cf588ebSPeter Wemm /*
4065cf588ebSPeter Wemm  * Installed either via SYSINIT() or via LKM stubs.
4075cf588ebSPeter Wemm  */
4085cf588ebSPeter Wemm Elf32_Interp_info linux_interp = {
4095cf588ebSPeter Wemm 					&elf_linux_sysvec,
4105cf588ebSPeter Wemm 					"/lib/ld-linux.so.1",
4115cf588ebSPeter Wemm 					"/compat/linux"
4125cf588ebSPeter Wemm 				 };
4135cf588ebSPeter Wemm 
4145cf588ebSPeter Wemm #ifndef LKM
4155cf588ebSPeter Wemm /*
4165cf588ebSPeter Wemm  * XXX: this is WRONG, it needs to be SI_SUB_EXEC, but this is just at the
4175cf588ebSPeter Wemm  * "proof of concept" stage and will be fixed shortly
4185cf588ebSPeter Wemm  */
4195cf588ebSPeter Wemm SYSINIT(linuxelf, SI_SUB_VFS, SI_ORDER_ANY, elf_insert_interp, &linux_interp);
4205cf588ebSPeter Wemm #endif
421