xref: /netbsd/sys/arch/arm/arm/sig_machdep.c (revision 96fe9714)
1 /*	$NetBSD: sig_machdep.c,v 1.48 2014/08/13 21:10:31 matt Exp $	*/
2 
3 /*
4  * Copyright (c) 1994-1998 Mark Brinicombe.
5  * Copyright (c) 1994 Brini.
6  * All rights reserved.
7  *
8  * This code is derived from software written for Brini by Mark Brinicombe
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by Mark Brinicombe
21  *	for the NetBSD Project.
22  * 4. The name of the company nor the name of the author may be used to
23  *    endorse or promote products derived from this software without specific
24  *    prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
27  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  * Machine dependent functions for kernel setup
39  *
40  * Created      : 17/09/94
41  */
42 
43 #include "opt_armfpe.h"
44 
45 #include <sys/param.h>
46 
47 __KERNEL_RCSID(0, "$NetBSD: sig_machdep.c,v 1.48 2014/08/13 21:10:31 matt Exp $");
48 
49 #include <sys/mount.h>		/* XXX only needed by syscallargs.h */
50 #include <sys/cpu.h>
51 #include <sys/proc.h>
52 #include <sys/signal.h>
53 #include <sys/syscallargs.h>
54 #include <sys/systm.h>
55 #include <sys/ras.h>
56 #include <sys/ucontext.h>
57 
58 #include <arm/locore.h>
59 
60 #include <machine/pcb.h>
61 #ifndef acorn26
62 #include <arm/cpufunc.h>
63 #endif
64 
65 void *
66 getframe(struct lwp *l, int sig, int *onstack)
67 {
68 	struct proc * const p = l->l_proc;
69 	struct trapframe * const tf = lwp_trapframe(l);
70 
71 	/* Do we need to jump onto the signal stack? */
72 	*onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0
73 	    && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
74 	if (*onstack)
75 		return (char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size;
76 	return (void *)tf->tf_usr_sp;
77 }
78 
79 
80 /*
81  * Send an interrupt to process.
82  *
83  * Stack is set up to allow sigcode stored
84  * in u. to call routine, followed by kcall
85  * to sigreturn routine below.  After sigreturn
86  * resets the signal mask, the stack, and the
87  * frame pointer, it returns to the user specified pc.
88  */
89 void
90 sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask)
91 {
92 	struct lwp * const l = curlwp;
93 	struct proc * const p = l->l_proc;
94 	struct sigacts * const ps = p->p_sigacts;
95 	struct trapframe * const tf = lwp_trapframe(l);
96 	struct sigframe_siginfo *fp, frame;
97 	int onstack, error;
98 	int sig = ksi->ksi_signo;
99 	sig_t catcher = SIGACTION(p, sig).sa_handler;
100 
101 	fp = getframe(l, sig, &onstack);
102 
103 	/* make room on the stack */
104 	fp--;
105 
106 	/* make the stack aligned */
107 	fp = (struct sigframe_siginfo *)STACK_ALIGN(fp, STACK_ALIGNBYTES);
108 
109 	/* populate the siginfo frame */
110 	frame.sf_si._info = ksi->ksi_info;
111 	frame.sf_uc.uc_flags = _UC_SIGMASK;
112 	frame.sf_uc.uc_sigmask = *mask;
113 	frame.sf_uc.uc_link = l->l_ctxlink;
114 	frame.sf_uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK)
115 	    ? _UC_SETSTACK : _UC_CLRSTACK;
116 	memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack));
117 	sendsig_reset(l, sig);
118 
119 	mutex_exit(p->p_lock);
120 	cpu_getmcontext(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags);
121 	error = copyout(&frame, fp, sizeof(frame));
122 	mutex_enter(p->p_lock);
123 
124 	if (error != 0) {
125 		/*
126 		 * Process has trashed its stack; give it an illegal
127 		 * instruction to halt it in its tracks.
128 		 */
129 		sigexit(l, SIGILL);
130 		/* NOTREACHED */
131 	}
132 
133 	/*
134 	 * Build context to run handler in.  We invoke the handler
135 	 * directly, only returning via the trampoline.  Note the
136 	 * trampoline version numbers are coordinated with machine-
137 	 * dependent code in libc.
138 	 */
139 
140 	tf->tf_r0 = sig;
141 	tf->tf_r1 = (int)&fp->sf_si;
142 	tf->tf_r2 = (int)&fp->sf_uc;
143 
144 	/* the trampoline uses r5 as the uc address */
145 	tf->tf_r5 = (int)&fp->sf_uc;
146 	tf->tf_pc = (int)catcher;
147 #ifdef THUMB_CODE
148 	if (((int) catcher) & 1)
149 		tf->tf_spsr |= PSR_T_bit;
150 	else
151 		tf->tf_spsr &= ~PSR_T_bit;
152 #endif
153 	tf->tf_usr_sp = (int)fp;
154 	tf->tf_usr_lr = (int)ps->sa_sigdesc[sig].sd_tramp;
155 
156 	/* Remember that we're now on the signal stack. */
157 	if (onstack)
158 		l->l_sigstk.ss_flags |= SS_ONSTACK;
159 }
160 
161 void
162 cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags)
163 {
164 	struct trapframe * const tf = lwp_trapframe(l);
165 	__greg_t * const gr = mcp->__gregs;
166 	__greg_t ras_pc;
167 
168 	/* Save General Register context. */
169 	gr[_REG_R0]   = tf->tf_r0;
170 	gr[_REG_R1]   = tf->tf_r1;
171 	gr[_REG_R2]   = tf->tf_r2;
172 	gr[_REG_R3]   = tf->tf_r3;
173 	gr[_REG_R4]   = tf->tf_r4;
174 	gr[_REG_R5]   = tf->tf_r5;
175 	gr[_REG_R6]   = tf->tf_r6;
176 	gr[_REG_R7]   = tf->tf_r7;
177 	gr[_REG_R8]   = tf->tf_r8;
178 	gr[_REG_R9]   = tf->tf_r9;
179 	gr[_REG_R10]  = tf->tf_r10;
180 	gr[_REG_R11]  = tf->tf_r11;
181 	gr[_REG_R12]  = tf->tf_r12;
182 	gr[_REG_SP]   = tf->tf_usr_sp;
183 	gr[_REG_LR]   = tf->tf_usr_lr;
184 	gr[_REG_PC]   = tf->tf_pc;
185 	gr[_REG_CPSR] = tf->tf_spsr;
186 
187 	KASSERTMSG(VALID_R15_PSR(gr[_REG_PC], gr[_REG_CPSR]), "%#x %#x",
188 	    gr[_REG_PC], gr[_REG_CPSR]);
189 
190 	if ((ras_pc = (__greg_t)ras_lookup(l->l_proc,
191 	    (void *) gr[_REG_PC])) != -1)
192 		gr[_REG_PC] = ras_pc;
193 
194 	*flags |= _UC_CPU;
195 
196 #ifdef FPU_VFP
197 	vfp_getcontext(l, mcp, flags);
198 #endif
199 
200 	mcp->_mc_tlsbase = (uintptr_t)l->l_private;
201 	*flags |= _UC_TLSBASE;
202 }
203 
204 int
205 cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
206 {
207 	const __greg_t * const gr = mcp->__gregs;
208 
209 	/* Make sure the processor mode has not been tampered with. */
210 	if (!VALID_R15_PSR(gr[_REG_PC], gr[_REG_CPSR]))
211 		return EINVAL;
212 	return 0;
213 }
214 
215 int
216 cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags)
217 {
218 	struct trapframe * const tf = lwp_trapframe(l);
219 	const __greg_t * const gr = mcp->__gregs;
220 	struct proc * const p = l->l_proc;
221 	int error;
222 
223 #ifdef FPU_VFP
224 	if ((flags & _UC_FPU)
225 	    && (curcpu()->ci_vfp_id == 0 || (flags & _UC_ARM_VFP) == 0))
226 		return EINVAL;
227 #endif
228 
229 	if ((flags & _UC_CPU) != 0) {
230 		/* Restore General Register context. */
231 		error = cpu_mcontext_validate(l, mcp);
232 		if (error)
233 			return error;
234 
235 		tf->tf_r0     = gr[_REG_R0];
236 		tf->tf_r1     = gr[_REG_R1];
237 		tf->tf_r2     = gr[_REG_R2];
238 		tf->tf_r3     = gr[_REG_R3];
239 		tf->tf_r4     = gr[_REG_R4];
240 		tf->tf_r5     = gr[_REG_R5];
241 		tf->tf_r6     = gr[_REG_R6];
242 		tf->tf_r7     = gr[_REG_R7];
243 		tf->tf_r8     = gr[_REG_R8];
244 		tf->tf_r9     = gr[_REG_R9];
245 		tf->tf_r10    = gr[_REG_R10];
246 		tf->tf_r11    = gr[_REG_R11];
247 		tf->tf_r12    = gr[_REG_R12];
248 		tf->tf_usr_sp = gr[_REG_SP];
249 		tf->tf_usr_lr = gr[_REG_LR];
250 		tf->tf_pc     = gr[_REG_PC];
251 		tf->tf_spsr   = gr[_REG_CPSR];
252 	}
253 
254 #ifdef FPU_VFP
255 	if ((flags & _UC_FPU) != 0) {
256 		/* Restore Floating Point Register context. */
257 		vfp_setcontext(l, mcp);
258 	}
259 #endif
260 
261 	if ((flags & _UC_TLSBASE) != 0)
262 		lwp_setprivate(l, (void *)(uintptr_t)mcp->_mc_tlsbase);
263 
264 	mutex_enter(p->p_lock);
265 	if (flags & _UC_SETSTACK)
266 		l->l_sigstk.ss_flags |= SS_ONSTACK;
267 	if (flags & _UC_CLRSTACK)
268 		l->l_sigstk.ss_flags &= ~SS_ONSTACK;
269 	mutex_exit(p->p_lock);
270 
271 	return (0);
272 }
273