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