xref: /freebsd/sys/arm/arm/exec_machdep.c (revision fdafd315)
1dfaf6502SKonstantin Belousov /*	$NetBSD: arm32_machdep.c,v 1.44 2004/03/24 15:34:47 atatat Exp $	*/
2dfaf6502SKonstantin Belousov 
3dfaf6502SKonstantin Belousov /*-
4dfaf6502SKonstantin Belousov  * SPDX-License-Identifier: BSD-4-Clause
5dfaf6502SKonstantin Belousov  *
6dfaf6502SKonstantin Belousov  * Copyright (c) 2004 Olivier Houchard
7dfaf6502SKonstantin Belousov  * Copyright (c) 1994-1998 Mark Brinicombe.
8dfaf6502SKonstantin Belousov  * Copyright (c) 1994 Brini.
9dfaf6502SKonstantin Belousov  * All rights reserved.
10dfaf6502SKonstantin Belousov  *
11dfaf6502SKonstantin Belousov  * This code is derived from software written for Brini by Mark Brinicombe
12dfaf6502SKonstantin Belousov  *
13dfaf6502SKonstantin Belousov  * Redistribution and use in source and binary forms, with or without
14dfaf6502SKonstantin Belousov  * modification, are permitted provided that the following conditions
15dfaf6502SKonstantin Belousov  * are met:
16dfaf6502SKonstantin Belousov  * 1. Redistributions of source code must retain the above copyright
17dfaf6502SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer.
18dfaf6502SKonstantin Belousov  * 2. Redistributions in binary form must reproduce the above copyright
19dfaf6502SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer in the
20dfaf6502SKonstantin Belousov  *    documentation and/or other materials provided with the distribution.
21dfaf6502SKonstantin Belousov  * 3. All advertising materials mentioning features or use of this software
22dfaf6502SKonstantin Belousov  *    must display the following acknowledgement:
23dfaf6502SKonstantin Belousov  *	This product includes software developed by Mark Brinicombe
24dfaf6502SKonstantin Belousov  *	for the NetBSD Project.
25dfaf6502SKonstantin Belousov  * 4. The name of the company nor the name of the author may be used to
26dfaf6502SKonstantin Belousov  *    endorse or promote products derived from this software without specific
27dfaf6502SKonstantin Belousov  *    prior written permission.
28dfaf6502SKonstantin Belousov  *
29dfaf6502SKonstantin Belousov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
30dfaf6502SKonstantin Belousov  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
31dfaf6502SKonstantin Belousov  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
32dfaf6502SKonstantin Belousov  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33dfaf6502SKonstantin Belousov  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34dfaf6502SKonstantin Belousov  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35dfaf6502SKonstantin Belousov  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36dfaf6502SKonstantin Belousov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37dfaf6502SKonstantin Belousov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38dfaf6502SKonstantin Belousov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39dfaf6502SKonstantin Belousov  * SUCH DAMAGE.
40dfaf6502SKonstantin Belousov  */
41dfaf6502SKonstantin Belousov 
42dfaf6502SKonstantin Belousov #include <sys/param.h>
43706f4a81SMark Johnston #include <sys/exec.h>
44dfaf6502SKonstantin Belousov #include <sys/imgact.h>
45dfaf6502SKonstantin Belousov #include <sys/kdb.h>
46dfaf6502SKonstantin Belousov #include <sys/kernel.h>
47dfaf6502SKonstantin Belousov #include <sys/ktr.h>
48dfaf6502SKonstantin Belousov #include <sys/lock.h>
49dfaf6502SKonstantin Belousov #include <sys/mutex.h>
50dfaf6502SKonstantin Belousov #include <sys/proc.h>
51dfaf6502SKonstantin Belousov #include <sys/rwlock.h>
52dfaf6502SKonstantin Belousov #include <sys/syscallsubr.h>
53dfaf6502SKonstantin Belousov #include <sys/sysent.h>
54dfaf6502SKonstantin Belousov #include <sys/sysproto.h>
55dfaf6502SKonstantin Belousov #include <sys/vmmeter.h>
56dfaf6502SKonstantin Belousov 
57dfaf6502SKonstantin Belousov #include <machine/asm.h>
58dfaf6502SKonstantin Belousov #include <machine/machdep.h>
59dfaf6502SKonstantin Belousov #include <machine/pcb.h>
60dfaf6502SKonstantin Belousov #include <machine/sysarch.h>
61dfaf6502SKonstantin Belousov #include <machine/vfp.h>
62dfaf6502SKonstantin Belousov #include <machine/vmparam.h>
63dfaf6502SKonstantin Belousov 
64706f4a81SMark Johnston #include <vm/vm.h>
65706f4a81SMark Johnston #include <vm/vm_param.h>
66706f4a81SMark Johnston #include <vm/pmap.h>
67706f4a81SMark Johnston #include <vm/vm_map.h>
68706f4a81SMark Johnston 
690c988f92SWarner Losh _Static_assert(sizeof(mcontext_t) == 208, "mcontext_t size incorrect");
700c988f92SWarner Losh _Static_assert(sizeof(ucontext_t) == 260, "ucontext_t size incorrect");
710c988f92SWarner Losh _Static_assert(sizeof(siginfo_t) == 64, "siginfo_t size incorrect");
720c988f92SWarner Losh 
73dfaf6502SKonstantin Belousov /*
74dfaf6502SKonstantin Belousov  * Clear registers on exec
75dfaf6502SKonstantin Belousov  */
76dfaf6502SKonstantin Belousov void
exec_setregs(struct thread * td,struct image_params * imgp,uintptr_t stack)77dfaf6502SKonstantin Belousov exec_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack)
78dfaf6502SKonstantin Belousov {
79dfaf6502SKonstantin Belousov 	struct trapframe *tf = td->td_frame;
80dfaf6502SKonstantin Belousov 
81dfaf6502SKonstantin Belousov 	memset(tf, 0, sizeof(*tf));
82dfaf6502SKonstantin Belousov 	tf->tf_usr_sp = stack;
83dfaf6502SKonstantin Belousov 	tf->tf_usr_lr = imgp->entry_addr;
84dfaf6502SKonstantin Belousov 	tf->tf_svc_lr = 0x77777777;
85dfaf6502SKonstantin Belousov 	tf->tf_pc = imgp->entry_addr;
86dfaf6502SKonstantin Belousov 	tf->tf_spsr = PSR_USR32_MODE;
87dfaf6502SKonstantin Belousov 	if ((register_t)imgp->entry_addr & 1)
88dfaf6502SKonstantin Belousov 		tf->tf_spsr |= PSR_T;
89dfaf6502SKonstantin Belousov }
90dfaf6502SKonstantin Belousov 
91dfaf6502SKonstantin Belousov #ifdef VFP
92dfaf6502SKonstantin Belousov /*
93dfaf6502SKonstantin Belousov  * Get machine VFP context.
94dfaf6502SKonstantin Belousov  */
95dfaf6502SKonstantin Belousov void
get_vfpcontext(struct thread * td,mcontext_vfp_t * vfp)96dfaf6502SKonstantin Belousov get_vfpcontext(struct thread *td, mcontext_vfp_t *vfp)
97dfaf6502SKonstantin Belousov {
98dfaf6502SKonstantin Belousov 	struct pcb *pcb;
99dfaf6502SKonstantin Belousov 
1004d2427f2SKornel Dulęba 	MPASS(td == curthread || TD_IS_SUSPENDED(td) ||
1014d2427f2SKornel Dulęba 	    P_SHOULDSTOP(td->td_proc));
1026926e269SKornel Dulęba 
103dfaf6502SKonstantin Belousov 	pcb = td->td_pcb;
1044d2427f2SKornel Dulęba 	if ((pcb->pcb_fpflags & PCB_FP_STARTED) != 0 && td == curthread) {
105dfaf6502SKonstantin Belousov 		critical_enter();
106dfaf6502SKonstantin Belousov 		vfp_store(&pcb->pcb_vfpstate, false);
107dfaf6502SKonstantin Belousov 		critical_exit();
1086926e269SKornel Dulęba 	}
1096926e269SKornel Dulęba 	KASSERT(pcb->pcb_vfpsaved == &pcb->pcb_vfpstate,
1106926e269SKornel Dulęba 		("Called get_vfpcontext while the kernel is using the VFP"));
1114d2427f2SKornel Dulęba 	memcpy(vfp, &pcb->pcb_vfpstate, sizeof(*vfp));
112dfaf6502SKonstantin Belousov }
113dfaf6502SKonstantin Belousov 
114dfaf6502SKonstantin Belousov /*
115dfaf6502SKonstantin Belousov  * Set machine VFP context.
116dfaf6502SKonstantin Belousov  */
117dfaf6502SKonstantin Belousov void
set_vfpcontext(struct thread * td,mcontext_vfp_t * vfp)118dfaf6502SKonstantin Belousov set_vfpcontext(struct thread *td, mcontext_vfp_t *vfp)
119dfaf6502SKonstantin Belousov {
120dfaf6502SKonstantin Belousov 	struct pcb *pcb;
121dfaf6502SKonstantin Belousov 
122dfaf6502SKonstantin Belousov 	pcb = td->td_pcb;
1234d2427f2SKornel Dulęba 	if (td == curthread) {
124dfaf6502SKonstantin Belousov 		critical_enter();
125dfaf6502SKonstantin Belousov 		vfp_discard(td);
126dfaf6502SKonstantin Belousov 		critical_exit();
1276926e269SKornel Dulęba 	}
1286926e269SKornel Dulęba 	KASSERT(pcb->pcb_vfpsaved == &pcb->pcb_vfpstate,
1296926e269SKornel Dulęba 		("Called set_vfpcontext while the kernel is using the VFP"));
1304d2427f2SKornel Dulęba 	memcpy(&pcb->pcb_vfpstate, vfp, sizeof(*vfp));
131dfaf6502SKonstantin Belousov }
132dfaf6502SKonstantin Belousov #endif
133dfaf6502SKonstantin Belousov 
134dfaf6502SKonstantin Belousov int
arm_get_vfpstate(struct thread * td,void * args)135dfaf6502SKonstantin Belousov arm_get_vfpstate(struct thread *td, void *args)
136dfaf6502SKonstantin Belousov {
137dfaf6502SKonstantin Belousov 	int rv;
138dfaf6502SKonstantin Belousov 	struct arm_get_vfpstate_args ua;
139dfaf6502SKonstantin Belousov 	mcontext_vfp_t	mcontext_vfp;
140dfaf6502SKonstantin Belousov 
141dfaf6502SKonstantin Belousov 	rv = copyin(args, &ua, sizeof(ua));
142dfaf6502SKonstantin Belousov 	if (rv != 0)
143dfaf6502SKonstantin Belousov 		return (rv);
144dfaf6502SKonstantin Belousov 	if (ua.mc_vfp_size != sizeof(mcontext_vfp_t))
145dfaf6502SKonstantin Belousov 		return (EINVAL);
146dfaf6502SKonstantin Belousov #ifdef VFP
147dfaf6502SKonstantin Belousov 	get_vfpcontext(td, &mcontext_vfp);
148dfaf6502SKonstantin Belousov #else
149dfaf6502SKonstantin Belousov 	bzero(&mcontext_vfp, sizeof(mcontext_vfp));
150dfaf6502SKonstantin Belousov #endif
151dfaf6502SKonstantin Belousov 
152dfaf6502SKonstantin Belousov 	rv = copyout(&mcontext_vfp, ua.mc_vfp,  sizeof(mcontext_vfp));
153dfaf6502SKonstantin Belousov 	if (rv != 0)
154dfaf6502SKonstantin Belousov 		return (rv);
155dfaf6502SKonstantin Belousov 	return (0);
156dfaf6502SKonstantin Belousov }
157dfaf6502SKonstantin Belousov 
158dfaf6502SKonstantin Belousov /*
159dfaf6502SKonstantin Belousov  * Get machine context.
160dfaf6502SKonstantin Belousov  */
161dfaf6502SKonstantin Belousov int
get_mcontext(struct thread * td,mcontext_t * mcp,int clear_ret)162dfaf6502SKonstantin Belousov get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
163dfaf6502SKonstantin Belousov {
164dfaf6502SKonstantin Belousov 	struct trapframe *tf = td->td_frame;
165dfaf6502SKonstantin Belousov 	__greg_t *gr = mcp->__gregs;
1666926e269SKornel Dulęba 	mcontext_vfp_t	mcontext_vfp;
1676926e269SKornel Dulęba 	int rv;
168dfaf6502SKonstantin Belousov 
169dfaf6502SKonstantin Belousov 	if (clear_ret & GET_MC_CLEAR_RET) {
170dfaf6502SKonstantin Belousov 		gr[_REG_R0] = 0;
171dfaf6502SKonstantin Belousov 		gr[_REG_CPSR] = tf->tf_spsr & ~PSR_C;
172dfaf6502SKonstantin Belousov 	} else {
173dfaf6502SKonstantin Belousov 		gr[_REG_R0]   = tf->tf_r0;
174dfaf6502SKonstantin Belousov 		gr[_REG_CPSR] = tf->tf_spsr;
175dfaf6502SKonstantin Belousov 	}
176dfaf6502SKonstantin Belousov 	gr[_REG_R1]   = tf->tf_r1;
177dfaf6502SKonstantin Belousov 	gr[_REG_R2]   = tf->tf_r2;
178dfaf6502SKonstantin Belousov 	gr[_REG_R3]   = tf->tf_r3;
179dfaf6502SKonstantin Belousov 	gr[_REG_R4]   = tf->tf_r4;
180dfaf6502SKonstantin Belousov 	gr[_REG_R5]   = tf->tf_r5;
181dfaf6502SKonstantin Belousov 	gr[_REG_R6]   = tf->tf_r6;
182dfaf6502SKonstantin Belousov 	gr[_REG_R7]   = tf->tf_r7;
183dfaf6502SKonstantin Belousov 	gr[_REG_R8]   = tf->tf_r8;
184dfaf6502SKonstantin Belousov 	gr[_REG_R9]   = tf->tf_r9;
185dfaf6502SKonstantin Belousov 	gr[_REG_R10]  = tf->tf_r10;
186dfaf6502SKonstantin Belousov 	gr[_REG_R11]  = tf->tf_r11;
187dfaf6502SKonstantin Belousov 	gr[_REG_R12]  = tf->tf_r12;
188dfaf6502SKonstantin Belousov 	gr[_REG_SP]   = tf->tf_usr_sp;
189dfaf6502SKonstantin Belousov 	gr[_REG_LR]   = tf->tf_usr_lr;
190dfaf6502SKonstantin Belousov 	gr[_REG_PC]   = tf->tf_pc;
191dfaf6502SKonstantin Belousov 
1926926e269SKornel Dulęba #ifdef VFP
1936926e269SKornel Dulęba 	if (mcp->mc_vfp_size != sizeof(mcontext_vfp_t))
1946926e269SKornel Dulęba 		return (EINVAL);
1956926e269SKornel Dulęba 	get_vfpcontext(td, &mcontext_vfp);
1966926e269SKornel Dulęba #else
1976926e269SKornel Dulęba 	bzero(&mcontext_vfp, sizeof(mcontext_vfp));
1986926e269SKornel Dulęba #endif
1996926e269SKornel Dulęba 
2006926e269SKornel Dulęba 	if (mcp->mc_vfp_ptr != NULL) {
2016926e269SKornel Dulęba 		rv = copyout(&mcontext_vfp, mcp->mc_vfp_ptr,  sizeof(mcontext_vfp));
2026926e269SKornel Dulęba 		if (rv != 0)
2036926e269SKornel Dulęba 			return (rv);
2046926e269SKornel Dulęba 	}
205dfaf6502SKonstantin Belousov 
206dfaf6502SKonstantin Belousov 	return (0);
207dfaf6502SKonstantin Belousov }
208dfaf6502SKonstantin Belousov 
209dfaf6502SKonstantin Belousov /*
210dfaf6502SKonstantin Belousov  * Set machine context.
211dfaf6502SKonstantin Belousov  *
212dfaf6502SKonstantin Belousov  * However, we don't set any but the user modifiable flags, and we won't
213dfaf6502SKonstantin Belousov  * touch the cs selector.
214dfaf6502SKonstantin Belousov  */
215dfaf6502SKonstantin Belousov int
set_mcontext(struct thread * td,mcontext_t * mcp)216dfaf6502SKonstantin Belousov set_mcontext(struct thread *td, mcontext_t *mcp)
217dfaf6502SKonstantin Belousov {
218dfaf6502SKonstantin Belousov 	mcontext_vfp_t mc_vfp, *vfp;
219dfaf6502SKonstantin Belousov 	struct trapframe *tf = td->td_frame;
220dfaf6502SKonstantin Belousov 	const __greg_t *gr = mcp->__gregs;
221dfaf6502SKonstantin Belousov 	int spsr;
222dfaf6502SKonstantin Belousov 
223dfaf6502SKonstantin Belousov 	/*
224dfaf6502SKonstantin Belousov 	 * Make sure the processor mode has not been tampered with and
225dfaf6502SKonstantin Belousov 	 * interrupts have not been disabled.
226dfaf6502SKonstantin Belousov 	 */
227dfaf6502SKonstantin Belousov 	spsr = gr[_REG_CPSR];
228dfaf6502SKonstantin Belousov 	if ((spsr & PSR_MODE) != PSR_USR32_MODE ||
229dfaf6502SKonstantin Belousov 	    (spsr & (PSR_I | PSR_F)) != 0)
230dfaf6502SKonstantin Belousov 		return (EINVAL);
231dfaf6502SKonstantin Belousov 
232dfaf6502SKonstantin Belousov #ifdef WITNESS
233dfaf6502SKonstantin Belousov 	if (mcp->mc_vfp_size != 0 && mcp->mc_vfp_size != sizeof(mc_vfp)) {
234dfaf6502SKonstantin Belousov 		printf("%s: %s: Malformed mc_vfp_size: %d (0x%08X)\n",
235dfaf6502SKonstantin Belousov 		    td->td_proc->p_comm, __func__,
236dfaf6502SKonstantin Belousov 		    mcp->mc_vfp_size, mcp->mc_vfp_size);
237dfaf6502SKonstantin Belousov 	} else if (mcp->mc_vfp_size != 0 && mcp->mc_vfp_ptr == NULL) {
238dfaf6502SKonstantin Belousov 		printf("%s: %s: c_vfp_size != 0 but mc_vfp_ptr == NULL\n",
239dfaf6502SKonstantin Belousov 		    td->td_proc->p_comm, __func__);
240dfaf6502SKonstantin Belousov 	}
241dfaf6502SKonstantin Belousov #endif
242dfaf6502SKonstantin Belousov 
243dfaf6502SKonstantin Belousov 	if (mcp->mc_vfp_size == sizeof(mc_vfp) && mcp->mc_vfp_ptr != NULL) {
244dfaf6502SKonstantin Belousov 		if (copyin(mcp->mc_vfp_ptr, &mc_vfp, sizeof(mc_vfp)) != 0)
245dfaf6502SKonstantin Belousov 			return (EFAULT);
246dfaf6502SKonstantin Belousov 		vfp = &mc_vfp;
247dfaf6502SKonstantin Belousov 	} else {
248dfaf6502SKonstantin Belousov 		vfp = NULL;
249dfaf6502SKonstantin Belousov 	}
250dfaf6502SKonstantin Belousov 
251dfaf6502SKonstantin Belousov 	tf->tf_r0 = gr[_REG_R0];
252dfaf6502SKonstantin Belousov 	tf->tf_r1 = gr[_REG_R1];
253dfaf6502SKonstantin Belousov 	tf->tf_r2 = gr[_REG_R2];
254dfaf6502SKonstantin Belousov 	tf->tf_r3 = gr[_REG_R3];
255dfaf6502SKonstantin Belousov 	tf->tf_r4 = gr[_REG_R4];
256dfaf6502SKonstantin Belousov 	tf->tf_r5 = gr[_REG_R5];
257dfaf6502SKonstantin Belousov 	tf->tf_r6 = gr[_REG_R6];
258dfaf6502SKonstantin Belousov 	tf->tf_r7 = gr[_REG_R7];
259dfaf6502SKonstantin Belousov 	tf->tf_r8 = gr[_REG_R8];
260dfaf6502SKonstantin Belousov 	tf->tf_r9 = gr[_REG_R9];
261dfaf6502SKonstantin Belousov 	tf->tf_r10 = gr[_REG_R10];
262dfaf6502SKonstantin Belousov 	tf->tf_r11 = gr[_REG_R11];
263dfaf6502SKonstantin Belousov 	tf->tf_r12 = gr[_REG_R12];
264dfaf6502SKonstantin Belousov 	tf->tf_usr_sp = gr[_REG_SP];
265dfaf6502SKonstantin Belousov 	tf->tf_usr_lr = gr[_REG_LR];
266dfaf6502SKonstantin Belousov 	tf->tf_pc = gr[_REG_PC];
267dfaf6502SKonstantin Belousov 	tf->tf_spsr = gr[_REG_CPSR];
268dfaf6502SKonstantin Belousov #ifdef VFP
269dfaf6502SKonstantin Belousov 	if (vfp != NULL)
270dfaf6502SKonstantin Belousov 		set_vfpcontext(td, vfp);
271dfaf6502SKonstantin Belousov #endif
272dfaf6502SKonstantin Belousov 	return (0);
273dfaf6502SKonstantin Belousov }
274dfaf6502SKonstantin Belousov 
275dfaf6502SKonstantin Belousov void
sendsig(sig_t catcher,ksiginfo_t * ksi,sigset_t * mask)276dfaf6502SKonstantin Belousov sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
277dfaf6502SKonstantin Belousov {
278dfaf6502SKonstantin Belousov 	struct thread *td;
279dfaf6502SKonstantin Belousov 	struct proc *p;
280dfaf6502SKonstantin Belousov 	struct trapframe *tf;
281dfaf6502SKonstantin Belousov 	struct sigframe *fp, frame;
282dfaf6502SKonstantin Belousov 	struct sigacts *psp;
283dfaf6502SKonstantin Belousov 	struct sysentvec *sysent;
284dfaf6502SKonstantin Belousov 	int onstack;
285dfaf6502SKonstantin Belousov 	int sig;
286dfaf6502SKonstantin Belousov 
287dfaf6502SKonstantin Belousov 	td = curthread;
288dfaf6502SKonstantin Belousov 	p = td->td_proc;
289dfaf6502SKonstantin Belousov 	PROC_LOCK_ASSERT(p, MA_OWNED);
290dfaf6502SKonstantin Belousov 	sig = ksi->ksi_signo;
291dfaf6502SKonstantin Belousov 	psp = p->p_sigacts;
292dfaf6502SKonstantin Belousov 	mtx_assert(&psp->ps_mtx, MA_OWNED);
293dfaf6502SKonstantin Belousov 	tf = td->td_frame;
294dfaf6502SKonstantin Belousov 	onstack = sigonstack(tf->tf_usr_sp);
295dfaf6502SKonstantin Belousov 
296dfaf6502SKonstantin Belousov 	CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
297dfaf6502SKonstantin Belousov 	    catcher, sig);
298dfaf6502SKonstantin Belousov 
299dfaf6502SKonstantin Belousov 	/* Allocate and validate space for the signal handler context. */
300dfaf6502SKonstantin Belousov 	if ((td->td_pflags & TDP_ALTSTACK) != 0 && !(onstack) &&
301dfaf6502SKonstantin Belousov 	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
302dfaf6502SKonstantin Belousov 		fp = (struct sigframe *)((uintptr_t)td->td_sigstk.ss_sp +
303dfaf6502SKonstantin Belousov 		    td->td_sigstk.ss_size);
304dfaf6502SKonstantin Belousov #if defined(COMPAT_43)
305dfaf6502SKonstantin Belousov 		td->td_sigstk.ss_flags |= SS_ONSTACK;
306dfaf6502SKonstantin Belousov #endif
307dfaf6502SKonstantin Belousov 	} else
308dfaf6502SKonstantin Belousov 		fp = (struct sigframe *)td->td_frame->tf_usr_sp;
309dfaf6502SKonstantin Belousov 
310dfaf6502SKonstantin Belousov 	/* make room on the stack */
311dfaf6502SKonstantin Belousov 	fp--;
312dfaf6502SKonstantin Belousov 
313dfaf6502SKonstantin Belousov 	/* make the stack aligned */
314dfaf6502SKonstantin Belousov 	fp = (struct sigframe *)STACKALIGN(fp);
315dfaf6502SKonstantin Belousov 	/* Populate the siginfo frame. */
316dfaf6502SKonstantin Belousov 	bzero(&frame, sizeof(frame));
317dfaf6502SKonstantin Belousov 	get_mcontext(td, &frame.sf_uc.uc_mcontext, 0);
318dfaf6502SKonstantin Belousov 	frame.sf_si = ksi->ksi_info;
319dfaf6502SKonstantin Belousov 	frame.sf_uc.uc_sigmask = *mask;
320dfaf6502SKonstantin Belousov 	frame.sf_uc.uc_stack = td->td_sigstk;
321dfaf6502SKonstantin Belousov 	frame.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) != 0 ?
322dfaf6502SKonstantin Belousov 	    (onstack ? SS_ONSTACK : 0) : SS_DISABLE;
323dfaf6502SKonstantin Belousov 	mtx_unlock(&psp->ps_mtx);
324dfaf6502SKonstantin Belousov 	PROC_UNLOCK(td->td_proc);
325dfaf6502SKonstantin Belousov 
326dfaf6502SKonstantin Belousov 	/* Copy the sigframe out to the user's stack. */
327dfaf6502SKonstantin Belousov 	if (copyout(&frame, fp, sizeof(*fp)) != 0) {
328dfaf6502SKonstantin Belousov 		/* Process has trashed its stack. Kill it. */
329dfaf6502SKonstantin Belousov 		CTR2(KTR_SIG, "sendsig: sigexit td=%p fp=%p", td, fp);
330dfaf6502SKonstantin Belousov 		PROC_LOCK(p);
331dfaf6502SKonstantin Belousov 		sigexit(td, SIGILL);
332dfaf6502SKonstantin Belousov 	}
333dfaf6502SKonstantin Belousov 
334dfaf6502SKonstantin Belousov 	/*
335dfaf6502SKonstantin Belousov 	 * Build context to run handler in.  We invoke the handler
336dfaf6502SKonstantin Belousov 	 * directly, only returning via the trampoline.  Note the
337dfaf6502SKonstantin Belousov 	 * trampoline version numbers are coordinated with machine-
338dfaf6502SKonstantin Belousov 	 * dependent code in libc.
339dfaf6502SKonstantin Belousov 	 */
340dfaf6502SKonstantin Belousov 
341dfaf6502SKonstantin Belousov 	tf->tf_r0 = sig;
342dfaf6502SKonstantin Belousov 	tf->tf_r1 = (register_t)&fp->sf_si;
343dfaf6502SKonstantin Belousov 	tf->tf_r2 = (register_t)&fp->sf_uc;
344dfaf6502SKonstantin Belousov 
345dfaf6502SKonstantin Belousov 	/* the trampoline uses r5 as the uc address */
346dfaf6502SKonstantin Belousov 	tf->tf_r5 = (register_t)&fp->sf_uc;
347dfaf6502SKonstantin Belousov 	tf->tf_pc = (register_t)catcher;
348dfaf6502SKonstantin Belousov 	tf->tf_usr_sp = (register_t)fp;
349dfaf6502SKonstantin Belousov 	sysent = p->p_sysent;
350361971fbSKornel Dulęba 	if (PROC_HAS_SHP(p))
351f6ac79fbSKornel Dulęba 		tf->tf_usr_lr = (register_t)PROC_SIGCODE(p);
352dfaf6502SKonstantin Belousov 	else
353706f4a81SMark Johnston 		tf->tf_usr_lr = (register_t)(PROC_PS_STRINGS(p) -
354dfaf6502SKonstantin Belousov 		    *(sysent->sv_szsigcode));
355dfaf6502SKonstantin Belousov 	/* Set the mode to enter in the signal handler */
356dfaf6502SKonstantin Belousov #if __ARM_ARCH >= 7
357dfaf6502SKonstantin Belousov 	if ((register_t)catcher & 1)
358dfaf6502SKonstantin Belousov 		tf->tf_spsr |= PSR_T;
359dfaf6502SKonstantin Belousov 	else
360dfaf6502SKonstantin Belousov 		tf->tf_spsr &= ~PSR_T;
361dfaf6502SKonstantin Belousov #endif
362dfaf6502SKonstantin Belousov 
363dfaf6502SKonstantin Belousov 	CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_usr_lr,
364dfaf6502SKonstantin Belousov 	    tf->tf_usr_sp);
365dfaf6502SKonstantin Belousov 
366dfaf6502SKonstantin Belousov 	PROC_LOCK(p);
367dfaf6502SKonstantin Belousov 	mtx_lock(&psp->ps_mtx);
368dfaf6502SKonstantin Belousov }
369dfaf6502SKonstantin Belousov 
370dfaf6502SKonstantin Belousov int
sys_sigreturn(struct thread * td,struct sigreturn_args * uap)371dfaf6502SKonstantin Belousov sys_sigreturn(struct thread *td, struct sigreturn_args *uap)
372dfaf6502SKonstantin Belousov {
373dfaf6502SKonstantin Belousov 	ucontext_t uc;
374dfaf6502SKonstantin Belousov 	int error;
375dfaf6502SKonstantin Belousov 
376dfaf6502SKonstantin Belousov 	if (uap == NULL)
377dfaf6502SKonstantin Belousov 		return (EFAULT);
378dfaf6502SKonstantin Belousov 	if (copyin(uap->sigcntxp, &uc, sizeof(uc)))
379dfaf6502SKonstantin Belousov 		return (EFAULT);
380dfaf6502SKonstantin Belousov 	/* Restore register context. */
381dfaf6502SKonstantin Belousov 	error = set_mcontext(td, &uc.uc_mcontext);
382dfaf6502SKonstantin Belousov 	if (error != 0)
383dfaf6502SKonstantin Belousov 		return (error);
384dfaf6502SKonstantin Belousov 
385dfaf6502SKonstantin Belousov 	/* Restore signal mask. */
386dfaf6502SKonstantin Belousov 	kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
387dfaf6502SKonstantin Belousov 
388dfaf6502SKonstantin Belousov 	return (EJUSTRETURN);
389dfaf6502SKonstantin Belousov }
390