xref: /netbsd-src/sys/arch/mips/mips/compat_16_machdep.c (revision 63d4abf06d37aace2f9e41a494102a64fe3abddb)
1 /*	$NetBSD: compat_16_machdep.c,v 1.16 2009/12/14 12:53:18 uebayasi Exp $	*/
2 
3 /*-
4  * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9  * NASA Ames Research Center and by Chris Demetriou.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * Copyright 1996 The Board of Trustees of The Leland Stanford
35  * Junior University. All Rights Reserved.
36  *
37  * Permission to use, copy, modify, and distribute this
38  * software and its documentation for any purpose and without
39  * fee is hereby granted, provided that the above copyright
40  * notice appear in all copies.  Stanford University
41  * makes no representations about the suitability of this
42  * software for any purpose.  It is provided "as is" without
43  * express or implied warranty.
44  */
45 
46 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
47 
48 __KERNEL_RCSID(0, "$NetBSD: compat_16_machdep.c,v 1.16 2009/12/14 12:53:18 uebayasi Exp $");
49 
50 #ifdef _KERNEL_OPT
51 #include "opt_cputype.h"
52 #include "opt_compat_netbsd.h"
53 #include "opt_compat_ultrix.h"
54 #endif
55 
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/kernel.h>
59 #include <sys/proc.h>
60 #include <sys/signal.h>
61 #include <sys/signalvar.h>
62 #include <sys/mount.h>
63 #include <sys/syscallargs.h>
64 
65 #include <compat/sys/signal.h>
66 #include <compat/sys/signalvar.h>
67 
68 #include <machine/cpu.h>
69 
70 #include <mips/regnum.h>
71 #include <mips/frame.h>
72 #include <mips/reg.h>
73 
74 #if !defined(__mips_o32)
75 #define	fpreg		fpreg_oabi
76 #endif
77 
78 #ifdef DEBUG
79 int sigdebug = 0;
80 int sigpid = 0;
81 #define SDB_FOLLOW	0x01
82 #define SDB_KSTACK	0x02
83 #define SDB_FPSTATE	0x04
84 #endif
85 
86 /*
87  * Send a signal to process.
88  */
89 void
90 sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *returnmask)
91 {
92 	int sig = ksi->ksi_signo;
93 	struct lwp *l = curlwp;
94 	struct proc *p = l->l_proc;
95 	struct pcb *pcb;
96 	struct sigacts *ps = p->p_sigacts;
97 	int onstack, error;
98 	struct sigcontext *scp = getframe(l, sig, &onstack);
99 	struct sigcontext ksc;
100 	struct frame *f = l->l_md.md_regs;
101 	sig_t catcher = SIGACTION(p, sig).sa_handler;
102 
103 #if !defined(__mips_o32)
104 	if (p->p_md.md_abi != _MIPS_BSD_API_O32)
105 		sigexit(l, SIGILL);
106 #endif
107 
108 	scp--;
109 
110 #ifdef DEBUG
111 	if ((sigdebug & SDB_FOLLOW) ||
112 	    ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid))
113 		printf("sendsig(%d): sig %d ssp %p scp %p\n",
114 		       p->p_pid, sig, &onstack, scp);
115 #endif
116 
117 	/* Build stack frame for signal trampoline. */
118 	ksc.sc_pc = f->f_regs[_R_PC];
119 	ksc.mullo = f->f_regs[_R_MULLO];
120 	ksc.mulhi = f->f_regs[_R_MULHI];
121 
122 	/* Save register context. */
123 	ksc.sc_regs[_R_ZERO] = 0xACEDBADE;		/* magic number */
124 #if defined(__mips_o32)
125 	memcpy(&ksc.sc_regs[1], &f->f_regs[1],
126 	    sizeof(ksc.sc_regs) - sizeof(ksc.sc_regs[0]));
127 #else
128 	size_t i;
129 	for (i = 1; i < 32; i++)
130 		ksc.sc_regs[i] = f->f_regs[i];
131 #endif
132 
133 	/* Save the FP state, if necessary, then copy it. */
134 	pcb = lwp_getpcb(l);
135 #ifndef SOFTFLOAT
136 	ksc.sc_fpused = l->l_md.md_flags & MDP_FPUSED;
137 	if (ksc.sc_fpused) {
138 		/* if FPU has current state, save it first */
139 		savefpregs(l);
140 	}
141 #endif
142 	*(struct fpreg *)ksc.sc_fpregs = *(struct fpreg *)&pcb->pcb_fpregs;
143 
144 	/* Save signal stack. */
145 	ksc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;
146 
147 	/* Save signal mask. */
148 	ksc.sc_mask = *returnmask;
149 
150 #if defined(COMPAT_13) || defined(COMPAT_ULTRIX)
151 	/*
152 	 * XXX We always have to save an old style signal mask because
153 	 * XXX we might be delivering a signal to a process which will
154 	 * XXX escape from the signal in a non-standard way and invoke
155 	 * XXX sigreturn() directly.
156 	 */
157 	native_sigset_to_sigset13(returnmask, &ksc.__sc_mask13);
158 #endif
159 
160 	sendsig_reset(l, sig);
161 
162 	mutex_exit(p->p_lock);
163 	error = copyout(&ksc, (void *)scp, sizeof(ksc));
164 	mutex_enter(p->p_lock);
165 
166 	if (error != 0) {
167 		/*
168 		 * Process has trashed its stack; give it an illegal
169 		 * instruction to halt it in its tracks.
170 		 */
171 #ifdef DEBUG
172 		if ((sigdebug & SDB_FOLLOW) ||
173 		    ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid))
174 			printf("sendsig(%d): copyout failed on sig %d\n",
175 			    p->p_pid, sig);
176 #endif
177 		sigexit(l, SIGILL);
178 		/* NOTREACHED */
179 	}
180 
181 	/*
182 	 * Set up the registers to directly invoke the signal
183 	 * handler.  The return address will be set up to point
184 	 * to the signal trampoline to bounce us back.
185 	 */
186 	f->f_regs[_R_A0] = sig;
187 	f->f_regs[_R_A1] = ksi->ksi_trap;
188 	f->f_regs[_R_A2] = (intptr_t)scp;
189 	f->f_regs[_R_A3] = (intptr_t)catcher;		/* XXX ??? */
190 
191 	f->f_regs[_R_PC] = (intptr_t)catcher;
192 	f->f_regs[_R_T9] = (intptr_t)catcher;
193 	f->f_regs[_R_SP] = (intptr_t)scp;
194 
195 	switch (ps->sa_sigdesc[sig].sd_vers) {
196 	case 0:		/* legacy on-stack sigtramp */
197 		f->f_regs[_R_RA] = (intptr_t)p->p_sigctx.ps_sigcode;
198 		break;
199 #ifdef COMPAT_16
200 	case 1:
201 		f->f_regs[_R_RA] = (intptr_t)ps->sa_sigdesc[sig].sd_tramp;
202 		break;
203 #endif
204 	default:
205 		/* Don't know what trampoline version; kill it. */
206 		sigexit(l, SIGILL);
207 	}
208 
209 	/* Remember that we're now on the signal stack. */
210 	if (onstack)
211 		l->l_sigstk.ss_flags |= SS_ONSTACK;
212 
213 #ifdef DEBUG
214 	if ((sigdebug & SDB_FOLLOW) ||
215 	    ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid))
216 		printf("sendsig(%d): sig %d returns\n",
217 		       p->p_pid, sig);
218 #endif
219 }
220 
221 #ifdef COMPAT_16 /* not needed if COMPAT_ULTRIX only */
222 /*
223  * System call to cleanup state after a signal
224  * has been taken.  Reset signal mask and
225  * stack state from context left by sendsig (above).
226  * Return to previous pc and psl as specified by
227  * context left by sendsig. Check carefully to
228  * make sure that the user has not modified the
229  * psl to gain improper privileges or to cause
230  * a machine fault.
231  */
232 /* ARGSUSED */
233 int
234 compat_16_sys___sigreturn14(struct lwp *l, const struct compat_16_sys___sigreturn14_args *uap, register_t *retval)
235 {
236 	/* {
237 		syscallarg(struct sigcontext *) sigcntxp;
238 	} */
239 	struct sigcontext *scp, ksc;
240 	struct frame *f;
241 	struct proc *p = l->l_proc;
242 	struct pcb *pcb;
243 	int error;
244 
245 #if !defined(__mips_o32)
246 	if (p->p_md.md_abi != _MIPS_BSD_API_O32)
247 		return ENOSYS;
248 #endif
249 
250 	/*
251 	 * The trampoline code hands us the context.
252 	 * It is unsafe to keep track of it ourselves, in the event that a
253 	 * program jumps out of a signal handler.
254 	 */
255 	scp = SCARG(uap, sigcntxp);
256 #ifdef DEBUG
257 	if (sigdebug & SDB_FOLLOW)
258 		printf("sigreturn: pid %d, scp %p\n", l->l_proc->p_pid, scp);
259 #endif
260 	if ((error = copyin(scp, &ksc, sizeof(ksc))) != 0)
261 		return (error);
262 
263 	if ((u_int) ksc.sc_regs[_R_ZERO] != 0xacedbadeU)/* magic number */
264 		return (EINVAL);
265 
266 	/* Restore the register context. */
267 	f = l->l_md.md_regs;
268 	f->f_regs[_R_PC] = ksc.sc_pc;
269 	f->f_regs[_R_MULLO] = ksc.mullo;
270 	f->f_regs[_R_MULHI] = ksc.mulhi;
271 #if defined(__mips_o32)
272 	memcpy(&f->f_regs[1], &scp->sc_regs[1],
273 	    sizeof(scp->sc_regs) - sizeof(scp->sc_regs[0]));
274 
275 #else
276 	size_t i;
277 	for (i = 1; i < __arraycount(f->f_regs); i++)
278 		f->f_regs[i] = ksc.sc_regs[i];
279 #endif
280 #ifndef	SOFTFLOAT
281 	if (scp->sc_fpused) {
282 		/* Disable the FPU to fault in FP registers. */
283 		f->f_regs[_R_SR] &= ~MIPS_SR_COP_1_BIT;
284 		fpcurlwp = &lwp0;
285 	}
286 #endif
287 	pcb = lwp_getpcb(l);
288 	*(struct fpreg *)&pcb->pcb_fpregs = *(struct fpreg *)scp->sc_fpregs;
289 
290 	mutex_enter(p->p_lock);
291 	/* Restore signal stack. */
292 	if (ksc.sc_onstack & SS_ONSTACK)
293 		l->l_sigstk.ss_flags |= SS_ONSTACK;
294 	else
295 		l->l_sigstk.ss_flags &= ~SS_ONSTACK;
296 	/* Restore signal mask. */
297 	(void) sigprocmask1(l, SIG_SETMASK, &ksc.sc_mask, 0);
298 	mutex_exit(p->p_lock);
299 
300 	return (EJUSTRETURN);
301 }
302 #endif /* COMPAT_16 */
303