1232449Sjmallett/*-
2232449Sjmallett * Copyright (c) 2012 Juli Mallett <jmallett@FreeBSD.org>
3232449Sjmallett * All rights reserved.
4232449Sjmallett *
5232449Sjmallett * Redistribution and use in source and binary forms, with or without
6232449Sjmallett * modification, are permitted provided that the following conditions
7232449Sjmallett * are met:
8232449Sjmallett * 1. Redistributions of source code must retain the above copyright
9232449Sjmallett *    notice, this list of conditions and the following disclaimer.
10232449Sjmallett * 2. Redistributions in binary form must reproduce the above copyright
11232449Sjmallett *    notice, this list of conditions and the following disclaimer in the
12232449Sjmallett *    documentation and/or other materials provided with the distribution.
13232449Sjmallett *
14232449Sjmallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15232449Sjmallett * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16232449Sjmallett * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17232449Sjmallett * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18232449Sjmallett * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19232449Sjmallett * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20232449Sjmallett * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21232449Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22232449Sjmallett * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23232449Sjmallett * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24232449Sjmallett * SUCH DAMAGE.
25232449Sjmallett *
26232449Sjmallett * $FreeBSD$
27232449Sjmallett */
28232449Sjmallett
29232449Sjmallett/*
30232449Sjmallett * Based on nwhitehorn's COMPAT_FREEBSD32 support code for PowerPC64.
31232449Sjmallett */
32232449Sjmallett
33232449Sjmallett#include "opt_compat.h"
34232449Sjmallett
35232449Sjmallett#define __ELF_WORD_SIZE 32
36232449Sjmallett
37232449Sjmallett#include <sys/types.h>
38232449Sjmallett#include <sys/param.h>
39232449Sjmallett#include <sys/kernel.h>
40232449Sjmallett#include <sys/systm.h>
41232449Sjmallett#include <sys/sysent.h>
42232449Sjmallett#include <sys/exec.h>
43232449Sjmallett#include <sys/imgact.h>
44232449Sjmallett#include <sys/malloc.h>
45232449Sjmallett#include <sys/proc.h>
46232449Sjmallett#include <sys/namei.h>
47232449Sjmallett#include <sys/fcntl.h>
48232449Sjmallett#include <sys/sysent.h>
49232449Sjmallett#include <sys/imgact_elf.h>
50232449Sjmallett#include <sys/syscall.h>
51232449Sjmallett#include <sys/syscallsubr.h>
52232449Sjmallett#include <sys/sysproto.h>
53232449Sjmallett#include <sys/signalvar.h>
54232449Sjmallett#include <sys/vnode.h>
55232449Sjmallett#include <sys/linker.h>
56232449Sjmallett
57232449Sjmallett#include <vm/vm.h>
58232449Sjmallett#include <vm/vm_param.h>
59232449Sjmallett
60232449Sjmallett#include <machine/md_var.h>
61232449Sjmallett#include <machine/reg.h>
62232449Sjmallett#include <machine/sigframe.h>
63232449Sjmallett#include <machine/sysarch.h>
64232449Sjmallett
65232449Sjmallett#include <compat/freebsd32/freebsd32_signal.h>
66232449Sjmallett#include <compat/freebsd32/freebsd32_util.h>
67232449Sjmallett#include <compat/freebsd32/freebsd32_proto.h>
68232449Sjmallett
69232449Sjmallettstatic void freebsd32_exec_setregs(struct thread *, struct image_params *, u_long);
70232449Sjmallettstatic int get_mcontext32(struct thread *, mcontext32_t *, int);
71278347Skibstatic int set_mcontext32(struct thread *, mcontext32_t *);
72232449Sjmallettstatic void freebsd32_sendsig(sig_t, ksiginfo_t *, sigset_t *);
73232449Sjmallett
74232449Sjmallettextern const char *freebsd32_syscallnames[];
75232449Sjmallett
76232449Sjmallettstruct sysentvec elf32_freebsd_sysvec = {
77232449Sjmallett	.sv_size	= SYS_MAXSYSCALL,
78232449Sjmallett	.sv_table	= freebsd32_sysent,
79232449Sjmallett	.sv_mask	= 0,
80232449Sjmallett	.sv_sigsize	= 0,
81232449Sjmallett	.sv_sigtbl	= NULL,
82232449Sjmallett	.sv_errsize	= 0,
83232449Sjmallett	.sv_errtbl	= NULL,
84232449Sjmallett	.sv_transtrap	= NULL,
85232449Sjmallett	.sv_fixup	= __elfN(freebsd_fixup),
86232449Sjmallett	.sv_sendsig	= freebsd32_sendsig,
87232449Sjmallett	.sv_sigcode	= sigcode32,
88232449Sjmallett	.sv_szsigcode	= &szsigcode32,
89232449Sjmallett	.sv_prepsyscall	= NULL,
90232449Sjmallett	.sv_name	= "FreeBSD ELF32",
91232449Sjmallett	.sv_coredump	= __elfN(coredump),
92232449Sjmallett	.sv_imgact_try	= NULL,
93232449Sjmallett	.sv_minsigstksz	= MINSIGSTKSZ,
94232449Sjmallett	.sv_pagesize	= PAGE_SIZE,
95232449Sjmallett	.sv_minuser	= VM_MIN_ADDRESS,
96232449Sjmallett	.sv_maxuser	= ((vm_offset_t)0x80000000),
97232449Sjmallett	.sv_usrstack	= FREEBSD32_USRSTACK,
98232449Sjmallett	.sv_psstrings	= FREEBSD32_PS_STRINGS,
99232449Sjmallett	.sv_stackprot	= VM_PROT_ALL,
100232449Sjmallett	.sv_copyout_strings = freebsd32_copyout_strings,
101232449Sjmallett	.sv_setregs	= freebsd32_exec_setregs,
102232449Sjmallett	.sv_fixlimit	= NULL,
103232449Sjmallett	.sv_maxssiz	= NULL,
104232449Sjmallett	.sv_flags	= SV_ABI_FREEBSD | SV_ILP32,
105232449Sjmallett	.sv_set_syscall_retval = cpu_set_syscall_retval,
106232449Sjmallett	.sv_fetch_syscall_args = cpu_fetch_syscall_args,
107232449Sjmallett	.sv_syscallnames = freebsd32_syscallnames,
108232449Sjmallett	.sv_schedtail	= NULL,
109293490Sdchagin	.sv_thread_detach = NULL,
110294136Sdchagin	.sv_trap	= NULL,
111232449Sjmallett};
112232449SjmallettINIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
113232449Sjmallett
114232449Sjmallettstatic Elf32_Brandinfo freebsd_brand_info = {
115232449Sjmallett	.brand		= ELFOSABI_FREEBSD,
116232449Sjmallett	.machine	= EM_MIPS,
117232449Sjmallett	.compat_3_brand	= "FreeBSD",
118232449Sjmallett	.emul_path	= NULL,
119232449Sjmallett	.interp_path	= "/libexec/ld-elf.so.1",
120232449Sjmallett	.sysvec		= &elf32_freebsd_sysvec,
121232449Sjmallett	.interp_newpath	= "/libexec/ld-elf32.so.1",
122232449Sjmallett	.flags		= 0
123232449Sjmallett};
124232449Sjmallett
125232449SjmallettSYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST,
126232449Sjmallett    (sysinit_cfunc_t) elf32_insert_brand_entry,
127232449Sjmallett    &freebsd_brand_info);
128232449Sjmallett
129232449Sjmallettstatic void
130232449Sjmallettfreebsd32_exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
131232449Sjmallett{
132232449Sjmallett	exec_setregs(td, imgp, stack);
133232449Sjmallett
134232449Sjmallett	/*
135232449Sjmallett	 * See comment in exec_setregs about running 32-bit binaries with 64-bit
136232449Sjmallett	 * registers.
137232449Sjmallett	 */
138232449Sjmallett	td->td_frame->sp -= 65536;
139232449Sjmallett
140232449Sjmallett	/*
141232449Sjmallett	 * Clear extended address space bit for userland.
142232449Sjmallett	 */
143232449Sjmallett	td->td_frame->sr &= ~MIPS_SR_UX;
144232449Sjmallett}
145232449Sjmallett
146232449Sjmallettint
147232449Sjmallettset_regs32(struct thread *td, struct reg32 *regs)
148232449Sjmallett{
149232449Sjmallett	struct reg r;
150232449Sjmallett	unsigned i;
151232449Sjmallett
152232449Sjmallett	for (i = 0; i < NUMSAVEREGS; i++)
153232449Sjmallett		r.r_regs[i] = regs->r_regs[i];
154232449Sjmallett
155232449Sjmallett	return (set_regs(td, &r));
156232449Sjmallett}
157232449Sjmallett
158232449Sjmallettint
159232449Sjmallettfill_regs32(struct thread *td, struct reg32 *regs)
160232449Sjmallett{
161232449Sjmallett	struct reg r;
162232449Sjmallett	unsigned i;
163232449Sjmallett	int error;
164232449Sjmallett
165232449Sjmallett	error = fill_regs(td, &r);
166232449Sjmallett	if (error != 0)
167232449Sjmallett		return (error);
168232449Sjmallett
169232449Sjmallett	for (i = 0; i < NUMSAVEREGS; i++)
170232449Sjmallett		regs->r_regs[i] = r.r_regs[i];
171232449Sjmallett
172232449Sjmallett	return (0);
173232449Sjmallett}
174232449Sjmallett
175232449Sjmallettint
176232449Sjmallettset_fpregs32(struct thread *td, struct fpreg32 *fpregs)
177232449Sjmallett{
178232449Sjmallett	struct fpreg fp;
179232449Sjmallett	unsigned i;
180232449Sjmallett
181232449Sjmallett	for (i = 0; i < NUMFPREGS; i++)
182232449Sjmallett		fp.r_regs[i] = fpregs->r_regs[i];
183232449Sjmallett
184232449Sjmallett	return (set_fpregs(td, &fp));
185232449Sjmallett}
186232449Sjmallett
187232449Sjmallettint
188232449Sjmallettfill_fpregs32(struct thread *td, struct fpreg32 *fpregs)
189232449Sjmallett{
190232449Sjmallett	struct fpreg fp;
191232449Sjmallett	unsigned i;
192232449Sjmallett	int error;
193232449Sjmallett
194232449Sjmallett	error = fill_fpregs(td, &fp);
195232449Sjmallett	if (error != 0)
196232449Sjmallett		return (error);
197232449Sjmallett
198232449Sjmallett	for (i = 0; i < NUMFPREGS; i++)
199232449Sjmallett		fpregs->r_regs[i] = fp.r_regs[i];
200232449Sjmallett
201232449Sjmallett	return (0);
202232449Sjmallett}
203232449Sjmallett
204232449Sjmallettstatic int
205232449Sjmallettget_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
206232449Sjmallett{
207232449Sjmallett	mcontext_t mcp64;
208232449Sjmallett	unsigned i;
209232449Sjmallett	int error;
210232449Sjmallett
211232449Sjmallett	error = get_mcontext(td, &mcp64, flags);
212232449Sjmallett	if (error != 0)
213232449Sjmallett		return (error);
214232449Sjmallett
215232449Sjmallett	mcp->mc_onstack = mcp64.mc_onstack;
216232449Sjmallett	mcp->mc_pc = mcp64.mc_pc;
217232449Sjmallett	for (i = 0; i < 32; i++)
218232449Sjmallett		mcp->mc_regs[i] = mcp64.mc_regs[i];
219232449Sjmallett	mcp->sr = mcp64.sr;
220232449Sjmallett	mcp->mullo = mcp64.mullo;
221232449Sjmallett	mcp->mulhi = mcp64.mulhi;
222232449Sjmallett	mcp->mc_fpused = mcp64.mc_fpused;
223232449Sjmallett	for (i = 0; i < 33; i++)
224232449Sjmallett		mcp->mc_fpregs[i] = mcp64.mc_fpregs[i];
225232449Sjmallett	mcp->mc_fpc_eir = mcp64.mc_fpc_eir;
226232584Sjmallett	mcp->mc_tls = (int32_t)(intptr_t)mcp64.mc_tls;
227232449Sjmallett
228232449Sjmallett	return (0);
229232449Sjmallett}
230232449Sjmallett
231232449Sjmallettstatic int
232278347Skibset_mcontext32(struct thread *td, mcontext32_t *mcp)
233232449Sjmallett{
234232449Sjmallett	mcontext_t mcp64;
235232449Sjmallett	unsigned i;
236232449Sjmallett
237232449Sjmallett	mcp64.mc_onstack = mcp->mc_onstack;
238232449Sjmallett	mcp64.mc_pc = mcp->mc_pc;
239232449Sjmallett	for (i = 0; i < 32; i++)
240232449Sjmallett		mcp64.mc_regs[i] = mcp->mc_regs[i];
241232449Sjmallett	mcp64.sr = mcp->sr;
242232449Sjmallett	mcp64.mullo = mcp->mullo;
243232449Sjmallett	mcp64.mulhi = mcp->mulhi;
244232449Sjmallett	mcp64.mc_fpused = mcp->mc_fpused;
245232449Sjmallett	for (i = 0; i < 33; i++)
246232449Sjmallett		mcp64.mc_fpregs[i] = mcp->mc_fpregs[i];
247232449Sjmallett	mcp64.mc_fpc_eir = mcp->mc_fpc_eir;
248232584Sjmallett	mcp64.mc_tls = (void *)(intptr_t)mcp->mc_tls;
249232449Sjmallett
250232449Sjmallett	return (set_mcontext(td, &mcp64));
251232449Sjmallett}
252232449Sjmallett
253232449Sjmallettint
254232449Sjmallettfreebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap)
255232449Sjmallett{
256232449Sjmallett	ucontext32_t uc;
257232449Sjmallett	int error;
258232449Sjmallett
259232449Sjmallett	CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
260232449Sjmallett
261232449Sjmallett	if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
262232449Sjmallett		CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
263232449Sjmallett		return (EFAULT);
264232449Sjmallett	}
265232449Sjmallett
266232449Sjmallett	error = set_mcontext32(td, &uc.uc_mcontext);
267232449Sjmallett	if (error != 0)
268232449Sjmallett		return (error);
269232449Sjmallett
270232449Sjmallett	kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
271232449Sjmallett
272232449Sjmallett#if 0
273232449Sjmallett	CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
274232449Sjmallett	     td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
275232449Sjmallett#endif
276232449Sjmallett
277232449Sjmallett	return (EJUSTRETURN);
278232449Sjmallett}
279232449Sjmallett
280232449Sjmallett/*
281232449Sjmallett * The first two fields of a ucontext_t are the signal mask and the machine
282232449Sjmallett * context.  The next field is uc_link; we want to avoid destroying the link
283232449Sjmallett * when copying out contexts.
284232449Sjmallett */
285232449Sjmallett#define	UC32_COPY_SIZE	offsetof(ucontext32_t, uc_link)
286232449Sjmallett
287232449Sjmallettint
288232449Sjmallettfreebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
289232449Sjmallett{
290232449Sjmallett	ucontext32_t uc;
291232449Sjmallett	int ret;
292232449Sjmallett
293232449Sjmallett	if (uap->ucp == NULL)
294232449Sjmallett		ret = EINVAL;
295232449Sjmallett	else {
296232449Sjmallett		get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
297232449Sjmallett		PROC_LOCK(td->td_proc);
298232449Sjmallett		uc.uc_sigmask = td->td_sigmask;
299232449Sjmallett		PROC_UNLOCK(td->td_proc);
300232449Sjmallett		ret = copyout(&uc, uap->ucp, UC32_COPY_SIZE);
301232449Sjmallett	}
302232449Sjmallett	return (ret);
303232449Sjmallett}
304232449Sjmallett
305232449Sjmallettint
306232449Sjmallettfreebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
307232449Sjmallett{
308232449Sjmallett	ucontext32_t uc;
309232449Sjmallett	int ret;
310232449Sjmallett
311232449Sjmallett	if (uap->ucp == NULL)
312232449Sjmallett		ret = EINVAL;
313232449Sjmallett	else {
314232449Sjmallett		ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE);
315232449Sjmallett		if (ret == 0) {
316232449Sjmallett			ret = set_mcontext32(td, &uc.uc_mcontext);
317232449Sjmallett			if (ret == 0) {
318232449Sjmallett				kern_sigprocmask(td, SIG_SETMASK,
319232449Sjmallett				    &uc.uc_sigmask, NULL, 0);
320232449Sjmallett			}
321232449Sjmallett		}
322232449Sjmallett	}
323232449Sjmallett	return (ret == 0 ? EJUSTRETURN : ret);
324232449Sjmallett}
325232449Sjmallett
326232449Sjmallettint
327232449Sjmallettfreebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
328232449Sjmallett{
329232449Sjmallett	ucontext32_t uc;
330232449Sjmallett	int ret;
331232449Sjmallett
332232449Sjmallett	if (uap->oucp == NULL || uap->ucp == NULL)
333232449Sjmallett		ret = EINVAL;
334232449Sjmallett	else {
335232449Sjmallett		get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
336232449Sjmallett		PROC_LOCK(td->td_proc);
337232449Sjmallett		uc.uc_sigmask = td->td_sigmask;
338232449Sjmallett		PROC_UNLOCK(td->td_proc);
339232449Sjmallett		ret = copyout(&uc, uap->oucp, UC32_COPY_SIZE);
340232449Sjmallett		if (ret == 0) {
341232449Sjmallett			ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE);
342232449Sjmallett			if (ret == 0) {
343232449Sjmallett				ret = set_mcontext32(td, &uc.uc_mcontext);
344232449Sjmallett				if (ret == 0) {
345232449Sjmallett					kern_sigprocmask(td, SIG_SETMASK,
346232449Sjmallett					    &uc.uc_sigmask, NULL, 0);
347232449Sjmallett				}
348232449Sjmallett			}
349232449Sjmallett		}
350232449Sjmallett	}
351232449Sjmallett	return (ret == 0 ? EJUSTRETURN : ret);
352232449Sjmallett}
353232449Sjmallett
354232449Sjmallett#define	UCONTEXT_MAGIC	0xACEDBADE
355232449Sjmallett
356232449Sjmallett/*
357232449Sjmallett * Send an interrupt to process.
358232449Sjmallett *
359232449Sjmallett * Stack is set up to allow sigcode stored
360232449Sjmallett * at top to call routine, followed by kcall
361232449Sjmallett * to sigreturn routine below.	After sigreturn
362232449Sjmallett * resets the signal mask, the stack, and the
363232449Sjmallett * frame pointer, it returns to the user
364232449Sjmallett * specified pc, psl.
365232449Sjmallett */
366232449Sjmallettstatic void
367232449Sjmallettfreebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
368232449Sjmallett{
369232449Sjmallett	struct proc *p;
370232449Sjmallett	struct thread *td;
371232449Sjmallett	struct fpreg32 fpregs;
372232449Sjmallett	struct reg32 regs;
373232449Sjmallett	struct sigacts *psp;
374232449Sjmallett	struct sigframe32 sf, *sfp;
375232449Sjmallett	int sig;
376232449Sjmallett	int oonstack;
377232449Sjmallett	unsigned i;
378232449Sjmallett
379232449Sjmallett	td = curthread;
380232449Sjmallett	p = td->td_proc;
381232449Sjmallett	PROC_LOCK_ASSERT(p, MA_OWNED);
382232449Sjmallett	sig = ksi->ksi_signo;
383232449Sjmallett	psp = p->p_sigacts;
384232449Sjmallett	mtx_assert(&psp->ps_mtx, MA_OWNED);
385232449Sjmallett
386232449Sjmallett	fill_regs32(td, &regs);
387232449Sjmallett	oonstack = sigonstack(td->td_frame->sp);
388232449Sjmallett
389232449Sjmallett	/* save user context */
390232449Sjmallett	bzero(&sf, sizeof sf);
391232449Sjmallett	sf.sf_uc.uc_sigmask = *mask;
392232449Sjmallett	sf.sf_uc.uc_stack.ss_sp = (int32_t)(intptr_t)td->td_sigstk.ss_sp;
393232449Sjmallett	sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size;
394232449Sjmallett	sf.sf_uc.uc_stack.ss_flags = td->td_sigstk.ss_flags;
395232449Sjmallett	sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
396232449Sjmallett	sf.sf_uc.uc_mcontext.mc_pc = regs.r_regs[PC];
397232449Sjmallett	sf.sf_uc.uc_mcontext.mullo = regs.r_regs[MULLO];
398232449Sjmallett	sf.sf_uc.uc_mcontext.mulhi = regs.r_regs[MULHI];
399232584Sjmallett	sf.sf_uc.uc_mcontext.mc_tls = (int32_t)(intptr_t)td->td_md.md_tls;
400232449Sjmallett	sf.sf_uc.uc_mcontext.mc_regs[0] = UCONTEXT_MAGIC;  /* magic number */
401232449Sjmallett	for (i = 1; i < 32; i++)
402232449Sjmallett		sf.sf_uc.uc_mcontext.mc_regs[i] = regs.r_regs[i];
403232449Sjmallett	sf.sf_uc.uc_mcontext.mc_fpused = td->td_md.md_flags & MDTD_FPUSED;
404232449Sjmallett	if (sf.sf_uc.uc_mcontext.mc_fpused) {
405232449Sjmallett		/* if FPU has current state, save it first */
406232449Sjmallett		if (td == PCPU_GET(fpcurthread))
407232449Sjmallett			MipsSaveCurFPState(td);
408232449Sjmallett		fill_fpregs32(td, &fpregs);
409232449Sjmallett		for (i = 0; i < 33; i++)
410232449Sjmallett			sf.sf_uc.uc_mcontext.mc_fpregs[i] = fpregs.r_regs[i];
411232449Sjmallett	}
412232449Sjmallett
413232449Sjmallett	/* Allocate and validate space for the signal handler context. */
414232449Sjmallett	if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
415232449Sjmallett	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
416232449Sjmallett		sfp = (struct sigframe32 *)((vm_offset_t)(td->td_sigstk.ss_sp +
417232449Sjmallett		    td->td_sigstk.ss_size - sizeof(struct sigframe32))
418232449Sjmallett		    & ~(sizeof(__int64_t) - 1));
419232449Sjmallett	} else
420232449Sjmallett		sfp = (struct sigframe32 *)((vm_offset_t)(td->td_frame->sp -
421232449Sjmallett		    sizeof(struct sigframe32)) & ~(sizeof(__int64_t) - 1));
422232449Sjmallett
423232449Sjmallett	/* Build the argument list for the signal handler. */
424232449Sjmallett	td->td_frame->a0 = sig;
425232449Sjmallett	td->td_frame->a2 = (register_t)(intptr_t)&sfp->sf_uc;
426232449Sjmallett	if (SIGISMEMBER(psp->ps_siginfo, sig)) {
427232449Sjmallett		/* Signal handler installed with SA_SIGINFO. */
428232449Sjmallett		td->td_frame->a1 = (register_t)(intptr_t)&sfp->sf_si;
429232449Sjmallett		/* sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; */
430232449Sjmallett
431232449Sjmallett		/* fill siginfo structure */
432232449Sjmallett		sf.sf_si.si_signo = sig;
433232449Sjmallett		sf.sf_si.si_code = ksi->ksi_code;
434232449Sjmallett		sf.sf_si.si_addr = td->td_frame->badvaddr;
435232449Sjmallett	} else {
436232449Sjmallett		/* Old FreeBSD-style arguments. */
437232449Sjmallett		td->td_frame->a1 = ksi->ksi_code;
438232449Sjmallett		td->td_frame->a3 = td->td_frame->badvaddr;
439232449Sjmallett		/* sf.sf_ahu.sf_handler = catcher; */
440232449Sjmallett	}
441232449Sjmallett
442232449Sjmallett	mtx_unlock(&psp->ps_mtx);
443232449Sjmallett	PROC_UNLOCK(p);
444232449Sjmallett
445232449Sjmallett	/*
446232449Sjmallett	 * Copy the sigframe out to the user's stack.
447232449Sjmallett	 */
448232449Sjmallett	if (copyout(&sf, sfp, sizeof(struct sigframe32)) != 0) {
449232449Sjmallett		/*
450232449Sjmallett		 * Something is wrong with the stack pointer.
451232449Sjmallett		 * ...Kill the process.
452232449Sjmallett		 */
453232449Sjmallett		PROC_LOCK(p);
454232449Sjmallett		sigexit(td, SIGILL);
455232449Sjmallett	}
456232449Sjmallett
457232449Sjmallett	td->td_frame->pc = (register_t)(intptr_t)catcher;
458232449Sjmallett	td->td_frame->t9 = (register_t)(intptr_t)catcher;
459232449Sjmallett	td->td_frame->sp = (register_t)(intptr_t)sfp;
460232449Sjmallett	/*
461232449Sjmallett	 * Signal trampoline code is at base of user stack.
462232449Sjmallett	 */
463232449Sjmallett	td->td_frame->ra = (register_t)(intptr_t)FREEBSD32_PS_STRINGS - *(p->p_sysent->sv_szsigcode);
464232449Sjmallett	PROC_LOCK(p);
465232449Sjmallett	mtx_lock(&psp->ps_mtx);
466232449Sjmallett}
467232449Sjmallett
468232449Sjmallettint
469232449Sjmallettfreebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap)
470232449Sjmallett{
471232449Sjmallett	int error;
472232449Sjmallett	int32_t tlsbase;
473232449Sjmallett
474232449Sjmallett	switch (uap->op) {
475232449Sjmallett	case MIPS_SET_TLS:
476232449Sjmallett		td->td_md.md_tls = (void *)(intptr_t)uap->parms;
477232449Sjmallett		return (0);
478232449Sjmallett	case MIPS_GET_TLS:
479232449Sjmallett		tlsbase = (int32_t)(intptr_t)td->td_md.md_tls;
480232449Sjmallett		error = copyout(&tlsbase, uap->parms, sizeof(tlsbase));
481232449Sjmallett		return (error);
482232449Sjmallett	default:
483232449Sjmallett		break;
484232449Sjmallett	}
485232449Sjmallett	return (EINVAL);
486232449Sjmallett}
487232449Sjmallett
488232449Sjmallettvoid
489232449Sjmallettelf32_dump_thread(struct thread *td __unused, void *dst __unused,
490232449Sjmallett    size_t *off __unused)
491232449Sjmallett{
492232449Sjmallett}
493