ia32_signal.c revision 216634
1203954Srdivacky/*-
2203954Srdivacky * Copyright (c) 2003 Peter Wemm
3203954Srdivacky * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
4203954Srdivacky * All rights reserved.
5203954Srdivacky *
6203954Srdivacky * This code is derived from software contributed to Berkeley by
7203954Srdivacky * William Jolitz.
8203954Srdivacky *
9203954Srdivacky * Redistribution and use in source and binary forms, with or without
10203954Srdivacky * modification, are permitted provided that the following conditions
11203954Srdivacky * are met:
12203954Srdivacky * 1. Redistributions of source code must retain the above copyright
13203954Srdivacky *    notice, this list of conditions and the following disclaimer.
14203954Srdivacky * 2. Redistributions in binary form must reproduce the above copyright
15203954Srdivacky *    notice, this list of conditions and the following disclaimer in the
16203954Srdivacky *    documentation and/or other materials provided with the distribution.
17203954Srdivacky * 4. Neither the name of the University nor the names of its contributors
18203954Srdivacky *    may be used to endorse or promote products derived from this software
19203954Srdivacky *    without specific prior written permission.
20203954Srdivacky *
21203954Srdivacky * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22203954Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23203954Srdivacky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24203954Srdivacky * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25203954Srdivacky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26203954Srdivacky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27203954Srdivacky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28203954Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29203954Srdivacky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30203954Srdivacky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31203954Srdivacky * SUCH DAMAGE.
32203954Srdivacky */
33203954Srdivacky
34203954Srdivacky#include <sys/cdefs.h>
35203954Srdivacky__FBSDID("$FreeBSD: head/sys/amd64/ia32/ia32_signal.c 216634 2010-12-22 00:18:42Z jkim $");
36212904Sdim
37203954Srdivacky#include "opt_compat.h"
38203954Srdivacky
39203954Srdivacky#include <sys/param.h>
40203954Srdivacky#include <sys/exec.h>
41203954Srdivacky#include <sys/fcntl.h>
42203954Srdivacky#include <sys/imgact.h>
43203954Srdivacky#include <sys/kernel.h>
44203954Srdivacky#include <sys/lock.h>
45203954Srdivacky#include <sys/malloc.h>
46203954Srdivacky#include <sys/mutex.h>
47203954Srdivacky#include <sys/mman.h>
48203954Srdivacky#include <sys/namei.h>
49203954Srdivacky#include <sys/pioctl.h>
50203954Srdivacky#include <sys/proc.h>
51203954Srdivacky#include <sys/procfs.h>
52203954Srdivacky#include <sys/resourcevar.h>
53203954Srdivacky#include <sys/systm.h>
54203954Srdivacky#include <sys/signalvar.h>
55203954Srdivacky#include <sys/stat.h>
56203954Srdivacky#include <sys/sx.h>
57212904Sdim#include <sys/syscall.h>
58212904Sdim#include <sys/syscallsubr.h>
59203954Srdivacky#include <sys/sysctl.h>
60203954Srdivacky#include <sys/sysent.h>
61203954Srdivacky#include <sys/vnode.h>
62203954Srdivacky
63203954Srdivacky#include <vm/vm.h>
64203954Srdivacky#include <vm/vm_kern.h>
65203954Srdivacky#include <vm/vm_param.h>
66203954Srdivacky#include <vm/pmap.h>
67203954Srdivacky#include <vm/vm_map.h>
68203954Srdivacky#include <vm/vm_object.h>
69203954Srdivacky#include <vm/vm_extern.h>
70203954Srdivacky
71203954Srdivacky#include <compat/freebsd32/freebsd32_signal.h>
72203954Srdivacky#include <compat/freebsd32/freebsd32_util.h>
73203954Srdivacky#include <compat/freebsd32/freebsd32_proto.h>
74203954Srdivacky#include <compat/ia32/ia32_signal.h>
75203954Srdivacky#include <machine/psl.h>
76203954Srdivacky#include <machine/segments.h>
77203954Srdivacky#include <machine/specialreg.h>
78203954Srdivacky#include <machine/frame.h>
79203954Srdivacky#include <machine/md_var.h>
80203954Srdivacky#include <machine/pcb.h>
81203954Srdivacky#include <machine/cpufunc.h>
82203954Srdivacky
83203954Srdivacky#ifdef COMPAT_FREEBSD4
84203954Srdivackystatic void freebsd4_ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *);
85203954Srdivacky#endif
86203954Srdivackystatic void ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp);
87203954Srdivackystatic int ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp);
88203954Srdivacky
89203954Srdivacky#define	CS_SECURE(cs)		(ISPL(cs) == SEL_UPL)
90203954Srdivacky#define	EFL_SECURE(ef, oef)	((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
91203954Srdivacky
92203954Srdivackystatic void
93203954Srdivackyia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp)
94203954Srdivacky{
95203954Srdivacky
96203954Srdivacky	/*
97203954Srdivacky	 * XXX Format of 64bit and 32bit FXSAVE areas differs. FXSAVE
98203954Srdivacky	 * in 32bit mode saves %cs and %ds, while on 64bit it saves
99203954Srdivacky	 * 64bit instruction and data pointers. Ignore the difference
100203954Srdivacky	 * for now, it should be irrelevant for most applications.
101203954Srdivacky	 */
102203954Srdivacky	mcp->mc_ownedfp = fpugetregs(td);
103203954Srdivacky	bcopy(&td->td_pcb->pcb_user_save, &mcp->mc_fpstate,
104212904Sdim	    sizeof(mcp->mc_fpstate));
105212904Sdim	mcp->mc_fpformat = fpuformat();
106212904Sdim}
107212904Sdim
108210299Sedstatic int
109203954Srdivackyia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp)
110203954Srdivacky{
111203954Srdivacky
112203954Srdivacky	if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
113203954Srdivacky		return (0);
114203954Srdivacky	else if (mcp->mc_fpformat != _MC_FPFMT_XMM)
115203954Srdivacky		return (EINVAL);
116203954Srdivacky	else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE)
117203954Srdivacky		/* We don't care what state is left in the FPU or PCB. */
118203954Srdivacky		fpstate_drop(td);
119203954Srdivacky	else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
120203954Srdivacky	    mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
121203954Srdivacky		fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate);
122203954Srdivacky	} else
123203954Srdivacky		return (EINVAL);
124203954Srdivacky	return (0);
125203954Srdivacky}
126203954Srdivacky
127203954Srdivacky/*
128203954Srdivacky * Get machine context.
129203954Srdivacky */
130203954Srdivackystatic int
131203954Srdivackyia32_get_mcontext(struct thread *td, struct ia32_mcontext *mcp, int flags)
132203954Srdivacky{
133203954Srdivacky	struct pcb *pcb;
134203954Srdivacky	struct trapframe *tp;
135203954Srdivacky
136203954Srdivacky	pcb = td->td_pcb;
137203954Srdivacky	tp = td->td_frame;
138203954Srdivacky
139203954Srdivacky	PROC_LOCK(curthread->td_proc);
140203954Srdivacky	mcp->mc_onstack = sigonstack(tp->tf_rsp);
141203954Srdivacky	PROC_UNLOCK(curthread->td_proc);
142203954Srdivacky	/* Entry into kernel always sets TF_HASSEGS */
143203954Srdivacky	mcp->mc_gs = tp->tf_gs;
144203954Srdivacky	mcp->mc_fs = tp->tf_fs;
145203954Srdivacky	mcp->mc_es = tp->tf_es;
146203954Srdivacky	mcp->mc_ds = tp->tf_ds;
147203954Srdivacky	mcp->mc_edi = tp->tf_rdi;
148203954Srdivacky	mcp->mc_esi = tp->tf_rsi;
149203954Srdivacky	mcp->mc_ebp = tp->tf_rbp;
150203954Srdivacky	mcp->mc_isp = tp->tf_rsp;
151203954Srdivacky	mcp->mc_eflags = tp->tf_rflags;
152203954Srdivacky	if (flags & GET_MC_CLEAR_RET) {
153203954Srdivacky		mcp->mc_eax = 0;
154203954Srdivacky		mcp->mc_edx = 0;
155203954Srdivacky		mcp->mc_eflags &= ~PSL_C;
156203954Srdivacky	} else {
157203954Srdivacky		mcp->mc_eax = tp->tf_rax;
158203954Srdivacky		mcp->mc_edx = tp->tf_rdx;
159203954Srdivacky	}
160203954Srdivacky	mcp->mc_ebx = tp->tf_rbx;
161203954Srdivacky	mcp->mc_ecx = tp->tf_rcx;
162203954Srdivacky	mcp->mc_eip = tp->tf_rip;
163203954Srdivacky	mcp->mc_cs = tp->tf_cs;
164203954Srdivacky	mcp->mc_esp = tp->tf_rsp;
165203954Srdivacky	mcp->mc_ss = tp->tf_ss;
166203954Srdivacky	mcp->mc_len = sizeof(*mcp);
167203954Srdivacky	ia32_get_fpcontext(td, mcp);
168203954Srdivacky	mcp->mc_fsbase = pcb->pcb_fsbase;
169203954Srdivacky	mcp->mc_gsbase = pcb->pcb_gsbase;
170203954Srdivacky	set_pcb_flags(pcb, PCB_FULL_IRET);
171203954Srdivacky	return (0);
172203954Srdivacky}
173203954Srdivacky
174203954Srdivacky/*
175203954Srdivacky * Set machine context.
176203954Srdivacky *
177203954Srdivacky * However, we don't set any but the user modifiable flags, and we won't
178203954Srdivacky * touch the cs selector.
179203954Srdivacky */
180203954Srdivackystatic int
181203954Srdivackyia32_set_mcontext(struct thread *td, const struct ia32_mcontext *mcp)
182203954Srdivacky{
183203954Srdivacky	struct trapframe *tp;
184203954Srdivacky	long rflags;
185203954Srdivacky	int ret;
186203954Srdivacky
187203954Srdivacky	tp = td->td_frame;
188203954Srdivacky	if (mcp->mc_len != sizeof(*mcp))
189		return (EINVAL);
190	rflags = (mcp->mc_eflags & PSL_USERCHANGE) |
191	    (tp->tf_rflags & ~PSL_USERCHANGE);
192	ret = ia32_set_fpcontext(td, mcp);
193	if (ret != 0)
194		return (ret);
195	tp->tf_gs = mcp->mc_gs;
196	tp->tf_fs = mcp->mc_fs;
197	tp->tf_es = mcp->mc_es;
198	tp->tf_ds = mcp->mc_ds;
199	tp->tf_flags = TF_HASSEGS;
200	tp->tf_rdi = mcp->mc_edi;
201	tp->tf_rsi = mcp->mc_esi;
202	tp->tf_rbp = mcp->mc_ebp;
203	tp->tf_rbx = mcp->mc_ebx;
204	tp->tf_rdx = mcp->mc_edx;
205	tp->tf_rcx = mcp->mc_ecx;
206	tp->tf_rax = mcp->mc_eax;
207	/* trapno, err */
208	tp->tf_rip = mcp->mc_eip;
209	tp->tf_rflags = rflags;
210	tp->tf_rsp = mcp->mc_esp;
211	tp->tf_ss = mcp->mc_ss;
212	set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
213	return (0);
214}
215
216/*
217 * The first two fields of a ucontext_t are the signal mask and
218 * the machine context.  The next field is uc_link; we want to
219 * avoid destroying the link when copying out contexts.
220 */
221#define	UC_COPY_SIZE	offsetof(struct ia32_ucontext, uc_link)
222
223int
224freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
225{
226	struct ia32_ucontext uc;
227	int ret;
228
229	if (uap->ucp == NULL)
230		ret = EINVAL;
231	else {
232		ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
233		PROC_LOCK(td->td_proc);
234		uc.uc_sigmask = td->td_sigmask;
235		PROC_UNLOCK(td->td_proc);
236		ret = copyout(&uc, uap->ucp, UC_COPY_SIZE);
237	}
238	return (ret);
239}
240
241int
242freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
243{
244	struct ia32_ucontext uc;
245	int ret;
246
247	if (uap->ucp == NULL)
248		ret = EINVAL;
249	else {
250		ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
251		if (ret == 0) {
252			ret = ia32_set_mcontext(td, &uc.uc_mcontext);
253			if (ret == 0) {
254				kern_sigprocmask(td, SIG_SETMASK,
255				    &uc.uc_sigmask, NULL, 0);
256			}
257		}
258	}
259	return (ret == 0 ? EJUSTRETURN : ret);
260}
261
262int
263freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
264{
265	struct ia32_ucontext uc;
266	int ret;
267
268	if (uap->oucp == NULL || uap->ucp == NULL)
269		ret = EINVAL;
270	else {
271		ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
272		PROC_LOCK(td->td_proc);
273		uc.uc_sigmask = td->td_sigmask;
274		PROC_UNLOCK(td->td_proc);
275		ret = copyout(&uc, uap->oucp, UC_COPY_SIZE);
276		if (ret == 0) {
277			ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
278			if (ret == 0) {
279				ret = ia32_set_mcontext(td, &uc.uc_mcontext);
280				if (ret == 0) {
281					kern_sigprocmask(td, SIG_SETMASK,
282					    &uc.uc_sigmask, NULL, 0);
283				}
284			}
285		}
286	}
287	return (ret == 0 ? EJUSTRETURN : ret);
288}
289
290/*
291 * Send an interrupt to process.
292 *
293 * Stack is set up to allow sigcode stored
294 * at top to call routine, followed by kcall
295 * to sigreturn routine below.  After sigreturn
296 * resets the signal mask, the stack, and the
297 * frame pointer, it returns to the user
298 * specified pc, psl.
299 */
300#ifdef COMPAT_FREEBSD4
301static void
302freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
303{
304	struct ia32_sigframe4 sf, *sfp;
305	struct siginfo32 siginfo;
306	struct proc *p;
307	struct thread *td;
308	struct sigacts *psp;
309	struct trapframe *regs;
310	int oonstack;
311	int sig;
312
313	td = curthread;
314	p = td->td_proc;
315	siginfo_to_siginfo32(&ksi->ksi_info, &siginfo);
316
317	PROC_LOCK_ASSERT(p, MA_OWNED);
318	sig = siginfo.si_signo;
319	psp = p->p_sigacts;
320	mtx_assert(&psp->ps_mtx, MA_OWNED);
321	regs = td->td_frame;
322	oonstack = sigonstack(regs->tf_rsp);
323
324	/* Save user context. */
325	bzero(&sf, sizeof(sf));
326	sf.sf_uc.uc_sigmask = *mask;
327	sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
328	sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size;
329	sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
330	    ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
331	sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
332	sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
333	sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
334	sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
335	sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */
336	sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx;
337	sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx;
338	sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx;
339	sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax;
340	sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno;
341	sf.sf_uc.uc_mcontext.mc_err = regs->tf_err;
342	sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip;
343	sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs;
344	sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
345	sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
346	sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
347	sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds;
348	sf.sf_uc.uc_mcontext.mc_es = regs->tf_es;
349	sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs;
350	sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs;
351
352	/* Allocate space for the signal handler context. */
353	if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
354	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
355		sfp = (struct ia32_sigframe4 *)(td->td_sigstk.ss_sp +
356		    td->td_sigstk.ss_size - sizeof(sf));
357	} else
358		sfp = (struct ia32_sigframe4 *)regs->tf_rsp - 1;
359	PROC_UNLOCK(p);
360
361	/* Translate the signal if appropriate. */
362	if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
363		sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
364
365	/* Build the argument list for the signal handler. */
366	sf.sf_signum = sig;
367	sf.sf_ucontext = (register_t)&sfp->sf_uc;
368	if (SIGISMEMBER(psp->ps_siginfo, sig)) {
369		/* Signal handler installed with SA_SIGINFO. */
370		sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si;
371		sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
372
373		/* Fill in POSIX parts */
374		sf.sf_si = siginfo;
375		sf.sf_si.si_signo = sig;
376	} else {
377		/* Old FreeBSD-style arguments. */
378		sf.sf_siginfo = siginfo.si_code;
379		sf.sf_addr = (u_int32_t)siginfo.si_addr;
380		sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
381	}
382	mtx_unlock(&psp->ps_mtx);
383
384	/*
385	 * Copy the sigframe out to the user's stack.
386	 */
387	if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
388#ifdef DEBUG
389		printf("process %ld has trashed its stack\n", (long)p->p_pid);
390#endif
391		PROC_LOCK(p);
392		sigexit(td, SIGILL);
393	}
394
395	regs->tf_rsp = (uintptr_t)sfp;
396	regs->tf_rip = p->p_sysent->sv_psstrings - sz_freebsd4_ia32_sigcode;
397	regs->tf_rflags &= ~(PSL_T | PSL_D);
398	regs->tf_cs = _ucode32sel;
399	regs->tf_ss = _udatasel;
400	regs->tf_ds = _udatasel;
401	regs->tf_es = _udatasel;
402	set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
403	/* leave user %fs and %gs untouched */
404	PROC_LOCK(p);
405	mtx_lock(&psp->ps_mtx);
406}
407#endif	/* COMPAT_FREEBSD4 */
408
409void
410ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
411{
412	struct ia32_sigframe sf, *sfp;
413	struct siginfo32 siginfo;
414	struct proc *p;
415	struct thread *td;
416	struct sigacts *psp;
417	char *sp;
418	struct trapframe *regs;
419	int oonstack;
420	int sig;
421
422	siginfo_to_siginfo32(&ksi->ksi_info, &siginfo);
423	td = curthread;
424	p = td->td_proc;
425	PROC_LOCK_ASSERT(p, MA_OWNED);
426	sig = siginfo.si_signo;
427	psp = p->p_sigacts;
428#ifdef COMPAT_FREEBSD4
429	if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
430		freebsd4_ia32_sendsig(catcher, ksi, mask);
431		return;
432	}
433#endif
434	mtx_assert(&psp->ps_mtx, MA_OWNED);
435	regs = td->td_frame;
436	oonstack = sigonstack(regs->tf_rsp);
437
438	/* Save user context. */
439	bzero(&sf, sizeof(sf));
440	sf.sf_uc.uc_sigmask = *mask;
441	sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
442	sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size;
443	sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
444	    ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
445	sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
446	sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
447	sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
448	sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
449	sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */
450	sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx;
451	sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx;
452	sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx;
453	sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax;
454	sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno;
455	sf.sf_uc.uc_mcontext.mc_err = regs->tf_err;
456	sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip;
457	sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs;
458	sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
459	sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
460	sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
461	sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds;
462	sf.sf_uc.uc_mcontext.mc_es = regs->tf_es;
463	sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs;
464	sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs;
465	sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
466	ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext);
467	fpstate_drop(td);
468	sf.sf_uc.uc_mcontext.mc_fsbase = td->td_pcb->pcb_fsbase;
469	sf.sf_uc.uc_mcontext.mc_gsbase = td->td_pcb->pcb_gsbase;
470
471	/* Allocate space for the signal handler context. */
472	if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
473	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
474		sp = td->td_sigstk.ss_sp +
475		    td->td_sigstk.ss_size - sizeof(sf);
476	} else
477		sp = (char *)regs->tf_rsp - sizeof(sf);
478	/* Align to 16 bytes. */
479	sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF);
480	PROC_UNLOCK(p);
481
482	/* Translate the signal if appropriate. */
483	if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
484		sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
485
486	/* Build the argument list for the signal handler. */
487	sf.sf_signum = sig;
488	sf.sf_ucontext = (register_t)&sfp->sf_uc;
489	if (SIGISMEMBER(psp->ps_siginfo, sig)) {
490		/* Signal handler installed with SA_SIGINFO. */
491		sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si;
492		sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
493
494		/* Fill in POSIX parts */
495		sf.sf_si = siginfo;
496		sf.sf_si.si_signo = sig;
497	} else {
498		/* Old FreeBSD-style arguments. */
499		sf.sf_siginfo = siginfo.si_code;
500		sf.sf_addr = (u_int32_t)siginfo.si_addr;
501		sf.sf_ah = (u_int32_t)(uintptr_t)catcher;
502	}
503	mtx_unlock(&psp->ps_mtx);
504
505	/*
506	 * Copy the sigframe out to the user's stack.
507	 */
508	if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
509#ifdef DEBUG
510		printf("process %ld has trashed its stack\n", (long)p->p_pid);
511#endif
512		PROC_LOCK(p);
513		sigexit(td, SIGILL);
514	}
515
516	regs->tf_rsp = (uintptr_t)sfp;
517	regs->tf_rip = p->p_sysent->sv_psstrings - *(p->p_sysent->sv_szsigcode);
518	regs->tf_rflags &= ~(PSL_T | PSL_D);
519	regs->tf_cs = _ucode32sel;
520	regs->tf_ss = _udatasel;
521	regs->tf_ds = _udatasel;
522	regs->tf_es = _udatasel;
523	set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
524	/* XXXKIB leave user %fs and %gs untouched */
525	PROC_LOCK(p);
526	mtx_lock(&psp->ps_mtx);
527}
528
529/*
530 * System call to cleanup state after a signal
531 * has been taken.  Reset signal mask and
532 * stack state from context left by sendsig (above).
533 * Return to previous pc and psl as specified by
534 * context left by sendsig. Check carefully to
535 * make sure that the user has not modified the
536 * state to gain improper privileges.
537 */
538#ifdef COMPAT_FREEBSD4
539/*
540 * MPSAFE
541 */
542int
543freebsd4_freebsd32_sigreturn(td, uap)
544	struct thread *td;
545	struct freebsd4_freebsd32_sigreturn_args /* {
546		const struct freebsd4_freebsd32_ucontext *sigcntxp;
547	} */ *uap;
548{
549	struct ia32_ucontext4 uc;
550	struct trapframe *regs;
551	struct ia32_ucontext4 *ucp;
552	int cs, eflags, error;
553	ksiginfo_t ksi;
554
555	error = copyin(uap->sigcntxp, &uc, sizeof(uc));
556	if (error != 0)
557		return (error);
558	ucp = &uc;
559	regs = td->td_frame;
560	eflags = ucp->uc_mcontext.mc_eflags;
561	/*
562	 * Don't allow users to change privileged or reserved flags.
563	 */
564	/*
565	 * XXX do allow users to change the privileged flag PSL_RF.
566	 * The cpu sets PSL_RF in tf_eflags for faults.  Debuggers
567	 * should sometimes set it there too.  tf_eflags is kept in
568	 * the signal context during signal handling and there is no
569	 * other place to remember it, so the PSL_RF bit may be
570	 * corrupted by the signal handler without us knowing.
571	 * Corruption of the PSL_RF bit at worst causes one more or
572	 * one less debugger trap, so allowing it is fairly harmless.
573	 */
574	if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
575		uprintf("pid %d (%s): freebsd4_freebsd32_sigreturn eflags = 0x%x\n",
576		    td->td_proc->p_pid, td->td_name, eflags);
577		return (EINVAL);
578	}
579
580	/*
581	 * Don't allow users to load a valid privileged %cs.  Let the
582	 * hardware check for invalid selectors, excess privilege in
583	 * other selectors, invalid %eip's and invalid %esp's.
584	 */
585	cs = ucp->uc_mcontext.mc_cs;
586	if (!CS_SECURE(cs)) {
587		uprintf("pid %d (%s): freebsd4_sigreturn cs = 0x%x\n",
588		    td->td_proc->p_pid, td->td_name, cs);
589		ksiginfo_init_trap(&ksi);
590		ksi.ksi_signo = SIGBUS;
591		ksi.ksi_code = BUS_OBJERR;
592		ksi.ksi_trapno = T_PROTFLT;
593		ksi.ksi_addr = (void *)regs->tf_rip;
594		trapsignal(td, &ksi);
595		return (EINVAL);
596	}
597
598	regs->tf_rdi = ucp->uc_mcontext.mc_edi;
599	regs->tf_rsi = ucp->uc_mcontext.mc_esi;
600	regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
601	regs->tf_rbx = ucp->uc_mcontext.mc_ebx;
602	regs->tf_rdx = ucp->uc_mcontext.mc_edx;
603	regs->tf_rcx = ucp->uc_mcontext.mc_ecx;
604	regs->tf_rax = ucp->uc_mcontext.mc_eax;
605	regs->tf_trapno = ucp->uc_mcontext.mc_trapno;
606	regs->tf_err = ucp->uc_mcontext.mc_err;
607	regs->tf_rip = ucp->uc_mcontext.mc_eip;
608	regs->tf_cs = cs;
609	regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
610	regs->tf_rsp = ucp->uc_mcontext.mc_esp;
611	regs->tf_ss = ucp->uc_mcontext.mc_ss;
612	regs->tf_ds = ucp->uc_mcontext.mc_ds;
613	regs->tf_es = ucp->uc_mcontext.mc_es;
614	regs->tf_fs = ucp->uc_mcontext.mc_fs;
615	regs->tf_gs = ucp->uc_mcontext.mc_gs;
616
617	kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0);
618	set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
619	return (EJUSTRETURN);
620}
621#endif	/* COMPAT_FREEBSD4 */
622
623/*
624 * MPSAFE
625 */
626int
627freebsd32_sigreturn(td, uap)
628	struct thread *td;
629	struct freebsd32_sigreturn_args /* {
630		const struct freebsd32_ucontext *sigcntxp;
631	} */ *uap;
632{
633	struct ia32_ucontext uc;
634	struct trapframe *regs;
635	struct ia32_ucontext *ucp;
636	int cs, eflags, error, ret;
637	ksiginfo_t ksi;
638
639	error = copyin(uap->sigcntxp, &uc, sizeof(uc));
640	if (error != 0)
641		return (error);
642	ucp = &uc;
643	regs = td->td_frame;
644	eflags = ucp->uc_mcontext.mc_eflags;
645	/*
646	 * Don't allow users to change privileged or reserved flags.
647	 */
648	/*
649	 * XXX do allow users to change the privileged flag PSL_RF.
650	 * The cpu sets PSL_RF in tf_eflags for faults.  Debuggers
651	 * should sometimes set it there too.  tf_eflags is kept in
652	 * the signal context during signal handling and there is no
653	 * other place to remember it, so the PSL_RF bit may be
654	 * corrupted by the signal handler without us knowing.
655	 * Corruption of the PSL_RF bit at worst causes one more or
656	 * one less debugger trap, so allowing it is fairly harmless.
657	 */
658	if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
659		uprintf("pid %d (%s): freebsd32_sigreturn eflags = 0x%x\n",
660		    td->td_proc->p_pid, td->td_name, eflags);
661		return (EINVAL);
662	}
663
664	/*
665	 * Don't allow users to load a valid privileged %cs.  Let the
666	 * hardware check for invalid selectors, excess privilege in
667	 * other selectors, invalid %eip's and invalid %esp's.
668	 */
669	cs = ucp->uc_mcontext.mc_cs;
670	if (!CS_SECURE(cs)) {
671		uprintf("pid %d (%s): sigreturn cs = 0x%x\n",
672		    td->td_proc->p_pid, td->td_name, cs);
673		ksiginfo_init_trap(&ksi);
674		ksi.ksi_signo = SIGBUS;
675		ksi.ksi_code = BUS_OBJERR;
676		ksi.ksi_trapno = T_PROTFLT;
677		ksi.ksi_addr = (void *)regs->tf_rip;
678		trapsignal(td, &ksi);
679		return (EINVAL);
680	}
681
682	ret = ia32_set_fpcontext(td, &ucp->uc_mcontext);
683	if (ret != 0)
684		return (ret);
685
686	regs->tf_rdi = ucp->uc_mcontext.mc_edi;
687	regs->tf_rsi = ucp->uc_mcontext.mc_esi;
688	regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
689	regs->tf_rbx = ucp->uc_mcontext.mc_ebx;
690	regs->tf_rdx = ucp->uc_mcontext.mc_edx;
691	regs->tf_rcx = ucp->uc_mcontext.mc_ecx;
692	regs->tf_rax = ucp->uc_mcontext.mc_eax;
693	regs->tf_trapno = ucp->uc_mcontext.mc_trapno;
694	regs->tf_err = ucp->uc_mcontext.mc_err;
695	regs->tf_rip = ucp->uc_mcontext.mc_eip;
696	regs->tf_cs = cs;
697	regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
698	regs->tf_rsp = ucp->uc_mcontext.mc_esp;
699	regs->tf_ss = ucp->uc_mcontext.mc_ss;
700	regs->tf_ds = ucp->uc_mcontext.mc_ds;
701	regs->tf_es = ucp->uc_mcontext.mc_es;
702	regs->tf_fs = ucp->uc_mcontext.mc_fs;
703	regs->tf_gs = ucp->uc_mcontext.mc_gs;
704	regs->tf_flags = TF_HASSEGS;
705
706	kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0);
707	set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
708	return (EJUSTRETURN);
709}
710
711/*
712 * Clear registers on exec
713 */
714void
715ia32_setregs(struct thread *td, struct image_params *imgp, u_long stack)
716{
717	struct trapframe *regs = td->td_frame;
718	struct pcb *pcb = td->td_pcb;
719
720	mtx_lock(&dt_lock);
721	if (td->td_proc->p_md.md_ldt != NULL)
722		user_ldt_free(td);
723	else
724		mtx_unlock(&dt_lock);
725
726	pcb->pcb_fsbase = 0;
727	pcb->pcb_gsbase = 0;
728	pcb->pcb_initial_fpucw = __INITIAL_FPUCW_I386__;
729
730	bzero((char *)regs, sizeof(struct trapframe));
731	regs->tf_rip = imgp->entry_addr;
732	regs->tf_rsp = stack;
733	regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T);
734	regs->tf_ss = _udatasel;
735	regs->tf_cs = _ucode32sel;
736	regs->tf_rbx = imgp->ps_strings;
737	regs->tf_ds = _udatasel;
738	regs->tf_es = _udatasel;
739	regs->tf_fs = _ufssel;
740	regs->tf_gs = _ugssel;
741	regs->tf_flags = TF_HASSEGS;
742
743	load_cr0(rcr0() | CR0_MP | CR0_TS);
744	fpstate_drop(td);
745
746	/* Return via doreti so that we can change to a different %cs */
747	set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET);
748	clear_pcb_flags(pcb, PCB_GS32BIT);
749	td->td_retval[1] = 0;
750}
751