1 /* $NetBSD: sunos32_machdep.c,v 1.33 2016/07/07 06:55:38 msaitoh Exp $ */
2 /* from: NetBSD: sunos_machdep.c,v 1.14 2001/01/29 01:37:56 mrg Exp */
3
4 /*
5 * Copyright (c) 1995, 2001 Matthew R. Green
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: sunos32_machdep.c,v 1.33 2016/07/07 06:55:38 msaitoh Exp $");
32
33 #ifdef _KERNEL_OPT
34 #include "opt_ddb.h"
35 #include "firm_events.h"
36 #endif
37
38 #include <sys/param.h>
39 #include <sys/exec.h>
40 #include <sys/systm.h>
41 #include <sys/proc.h>
42 #include <sys/namei.h>
43 #include <sys/filedesc.h>
44 #include <sys/ioctl.h>
45 #include <sys/mount.h>
46 #include <sys/kernel.h>
47 #include <sys/signal.h>
48 #include <sys/signalvar.h>
49 #include <sys/select.h>
50
51 #include <sys/syscallargs.h>
52 #include <compat/sunos/sunos.h>
53 #include <compat/sunos/sunos_syscallargs.h>
54 #include <compat/netbsd32/netbsd32.h>
55 #include <compat/sunos32/sunos32.h>
56 #include <compat/sunos32/sunos32_syscallargs.h>
57 #include <compat/sunos32/sunos32_exec.h>
58
59 #include <compat/sys/signal.h>
60 #include <compat/sys/signalvar.h>
61
62 #include <machine/frame.h>
63 #include <machine/cpu.h>
64 #include <machine/vuid_event.h>
65 #include <machine/reg.h>
66
67 #include <dev/sun/event_var.h>
68
69 #ifdef DEBUG
70 #include <sparc64/sparc64/sigdebug.h>
71 #endif
72
73 struct sunos32_sigcontext {
74 uint32_t sc_onstack; /* sigstack state to restore */
75 uint32_t sc_mask; /* signal mask to restore (old style) */
76 /* begin machine dependent portion */
77 uint32_t sc_sp; /* %sp to restore */
78 uint32_t sc_pc; /* pc to restore */
79 uint32_t sc_npc; /* npc to restore */
80 uint32_t sc_psr; /* pstate to restore */
81 uint32_t sc_g1; /* %g1 to restore */
82 uint32_t sc_o0; /* %o0 to restore */
83 };
84
85 struct sunos32_sigframe {
86 uint32_t sf_signo; /* signal number */
87 uint32_t sf_code; /* code */
88 uint32_t sf_scp; /* SunOS user addr of sigcontext */
89 uint32_t sf_addr; /* SunOS compat, always 0 for now */
90 struct sunos32_sigcontext sf_sc; /* actual sigcontext */
91 };
92
93 #if NFIRM_EVENTS > 0
94 static int ev_out32(struct firm_event *, int, struct uio *);
95 #endif
96
97 /*
98 * Set up registers on exec.
99 *
100 * XXX this entire mess must be fixed
101 */
102 /* ARGSUSED */
103 void
sunos32_setregs(struct lwp * l,struct exec_package * pack,vaddr_t stack)104 sunos32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
105 /* stack: XXX */
106 {
107 struct trapframe64 *tf = l->l_md.md_tf;
108 struct fpstate64 *fs;
109 int64_t tstate;
110 struct proc *p = l->l_proc;
111
112 /* Don't allow misaligned code by default */
113 p->p_md.md_flags &= ~MDP_FIXALIGN;
114
115 /* Mark this as a 32-bit emulation */
116 mutex_enter(p->p_lock);
117 p->p_flag |= PK_32;
118 mutex_exit(p->p_lock);
119
120 /* Setup the ev_out32 hook */
121 #if NFIRM_EVENTS > 0
122 if (ev_out32_hook == NULL)
123 ev_out32_hook = ev_out32;
124 #endif
125
126 /*
127 * Set the registers to 0 except for:
128 * %o6: stack pointer, built in exec())
129 * %tstate: (retain icc and xcc and cwp bits)
130 * %g1: p->p_psstrp (used by crt0)
131 * %tpc,%tnpc: entry point of program
132 */
133 tstate = ((PSTATE_USER32)<<TSTATE_PSTATE_SHIFT)
134 | (tf->tf_tstate & TSTATE_CWP);
135 if ((fs = l->l_md.md_fpstate) != NULL) {
136 /*
137 * We hold an FPU state. If we own *the* FPU chip state
138 * we must get rid of it, and the only way to do that is
139 * to save it. In any case, get rid of our FPU state.
140 */
141 if (l == fplwp) {
142 savefpstate(fs);
143 fplwp = NULL;
144 }
145 pool_cache_put(fpstate_cache, fs);
146 l->l_md.md_fpstate = NULL;
147 }
148 memset(tf, 0, sizeof *tf);
149 tf->tf_tstate = tstate;
150 tf->tf_global[1] = (u_int)p->p_psstrp;
151 tf->tf_pc = pack->ep_entry & ~3;
152 tf->tf_npc = tf->tf_pc + 4;
153
154 stack -= sizeof(struct rwindow32);
155 tf->tf_out[6] = stack;
156 tf->tf_out[7] = 0;
157 }
158
159 void
sunos32_sendsig(const ksiginfo_t * ksi,const sigset_t * mask)160 sunos32_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
161 {
162 int sig = ksi->ksi_signo;
163 struct lwp *l = curlwp; /* XXX */
164 struct proc *p = l->l_proc;
165 struct sunos32_sigframe *fp;
166 struct trapframe64 *tf;
167 struct rwindow32 *oldsp, *newsp;
168 struct sunos32_sigframe sf;
169 struct sunos32_sigcontext *scp;
170 uint32_t addr, oldsp32;
171 int onstack, error;
172 sig_t catcher = SIGACTION(p, sig).sa_handler;
173
174 tf = l->l_md.md_tf;
175 /* Need to attempt to zero extend this 32-bit pointer */
176 oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6];
177 oldsp32 = (uint32_t)(u_long)oldsp;
178
179 /*
180 * Compute new user stack addresses, subtract off
181 * one signal frame, and align.
182 */
183 onstack =
184 (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
185 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
186
187 if (onstack)
188 fp = (struct sunos32_sigframe *)
189 ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size);
190 else
191 fp = (struct sunos32_sigframe *)oldsp;
192
193 fp = (struct sunos32_sigframe *)((u_long)(fp - 1) & ~7);
194
195 #ifdef DEBUG
196 sigpid = p->p_pid;
197 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
198 mutex_exit(p->p_lock);
199 printf("sunos32_sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n",
200 p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp);
201 #ifdef DDB
202 if (sigdebug & SDB_DDB) Debugger();
203 #endif
204 mutex_enter(p->p_lock);
205 }
206 #endif
207 /*
208 * Now set up the signal frame. We build it in kernel space
209 * and then copy it out. We probably ought to just build it
210 * directly in user space....
211 */
212 sf.sf_signo = sig;
213 sf.sf_code = (uint32_t)ksi->ksi_trap;
214 scp = &fp->sf_sc;
215 if ((u_long)scp >= 0x100000000)
216 printf("sunos32_sendsig: sf_scp overflow %p > 0x100000000\n", scp);
217 sf.sf_scp = (uint32_t)(u_long)scp;
218 sf.sf_addr = 0; /* XXX */
219
220 /*
221 * Build the signal context to be used by sigreturn.
222 */
223 sf.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;
224 native_sigset_to_sigset13(mask, &sf.sf_sc.sc_mask);
225 sf.sf_sc.sc_sp = (u_int)(u_long)oldsp;
226 sf.sf_sc.sc_pc = tf->tf_pc;
227 sf.sf_sc.sc_npc = tf->tf_npc;
228 sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */
229 sf.sf_sc.sc_g1 = tf->tf_global[1];
230 sf.sf_sc.sc_o0 = tf->tf_out[0];
231
232 /*
233 * Put the stack in a consistent state before we whack away
234 * at it. Note that write_user_windows may just dump the
235 * registers into the pcb; we need them in the process's memory.
236 * We also need to make sure that when we start the signal handler,
237 * its %i6 (%fp), which is loaded from the newly allocated stack area,
238 * joins seamlessly with the frame it was in when the signal occurred,
239 * so that the debugger and _longjmp code can back up through it.
240 */
241 sendsig_reset(l, sig);
242 mutex_exit(p->p_lock);
243 newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32));
244 write_user_windows();
245 #ifdef DEBUG
246 if ((sigdebug & SDB_KSTACK))
247 printf("sunos32_sendsig: saving sf to %p, setting stack pointer %p to %p\n",
248 fp, &(((struct rwindow32 *)newsp)->rw_in[6]), oldsp);
249 #endif
250 error = (rwindow_save(l) || copyout((void *)&sf, (void *)fp, sizeof sf) ||
251 copyout((void *)&oldsp32, &(((struct rwindow32 *)newsp)->rw_in[6]), sizeof oldsp32));
252 mutex_enter(p->p_lock);
253 if (error) {
254 /*
255 * Process has trashed its stack; give it an illegal
256 * instruction to halt it in its tracks.
257 */
258 #ifdef DEBUG
259 mutex_exit(p->p_lock);
260 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
261 printf("sunos32_sendsig: window save or copyout error\n");
262 printf("sunos32_sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig);
263 #ifdef DDB
264 if (sigdebug & SDB_DDB) Debugger();
265 #endif
266 mutex_enter(p->p_lock);
267 #endif
268 sigexit(l, SIGILL);
269 /* NOTREACHED */
270 }
271
272 #ifdef DEBUG
273 if ((sigdebug & SDB_FOLLOW)) {
274 printf("sunos32_sendsig: %s[%d] sig %d scp %p\n",
275 p->p_comm, p->p_pid, sig, &fp->sf_sc);
276 }
277 #endif
278 /*
279 * Arrange to continue execution at the code copied out in exec().
280 * It needs the function to call in %g1, and a new stack pointer.
281 */
282 addr = (uint32_t)(u_long)catcher; /* user does his own trampolining */
283 tf->tf_pc = addr;
284 tf->tf_npc = addr + 4;
285 tf->tf_out[6] = (uint64_t)(u_int)(u_long)newsp;
286 #ifdef DEBUG
287 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
288 mutex_exit(p->p_lock);
289 printf("sunos32_sendsig: about to return to catcher %p thru %p\n",
290 catcher, (void *)(u_long)addr);
291 #ifdef DDB
292 if (sigdebug & SDB_DDB) Debugger();
293 #endif
294 mutex_enter(p->p_lock);
295 }
296 #endif
297 }
298
299 int
sunos32_sys_sigreturn(struct lwp * l,const struct sunos32_sys_sigreturn_args * uap,register_t * retval)300 sunos32_sys_sigreturn(struct lwp *l, const struct sunos32_sys_sigreturn_args *uap, register_t *retval)
301 {
302 /* {
303 syscallarg(netbsd32_sigcontextp_t) sigcntxp;
304 } */
305 struct proc *p = l->l_proc;
306 struct sunos32_sigcontext sc, *scp;
307 sigset_t mask;
308 struct trapframe64 *tf;
309
310 /* First ensure consistent stack state (see sendsig). */
311 write_user_windows();
312 if (rwindow_save(l)) {
313 mutex_enter(p->p_lock);
314 sigexit(l, SIGILL);
315 }
316 #ifdef DEBUG
317 if (sigdebug & SDB_FOLLOW) {
318 printf("sunos32_sigreturn: %s[%d], sigcntxp %p\n",
319 p->p_comm, p->p_pid, (void *)(u_long)SCARG(uap, sigcntxp));
320 #ifdef DDB
321 if (sigdebug & SDB_DDB) Debugger();
322 #endif
323 }
324 #endif
325
326 scp = (struct sunos32_sigcontext *)(u_long)SCARG(uap, sigcntxp);
327 if ((vaddr_t)scp & 3 || (copyin((void *)scp, &sc, sizeof sc) != 0))
328 return (EFAULT);
329 scp = ≻
330
331 tf = l->l_md.md_tf;
332 /*
333 * Only the icc bits in the psr are used, so it need not be
334 * verified. pc and npc must be multiples of 4. This is all
335 * that is required; if it holds, just do it.
336 */
337 if (((scp->sc_pc | scp->sc_npc) & 3) != 0 || scp->sc_pc == 0 || scp->sc_npc == 0)
338 {
339 #ifdef DEBUG
340 printf("sunos32_sigreturn: pc %x or npc %x invalid\n", scp->sc_pc, scp->sc_npc);
341 #ifdef DDB
342 Debugger();
343 #endif
344 #endif
345 return (EINVAL);
346 }
347 /* take only psr ICC field */
348 tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(scp->sc_psr);
349 tf->tf_pc = scp->sc_pc;
350 tf->tf_npc = scp->sc_npc;
351 tf->tf_global[1] = scp->sc_g1;
352 tf->tf_out[0] = scp->sc_o0;
353 tf->tf_out[6] = scp->sc_sp;
354 #ifdef DEBUG
355 if (sigdebug & SDB_FOLLOW) {
356 printf("sunos32_sigreturn: return trapframe pc=%p sp=%p tstate=%llx\n",
357 (void *)(u_long)tf->tf_pc, (void *)(u_long)tf->tf_out[6], (unsigned long long)tf->tf_tstate);
358 #ifdef DDB
359 if (sigdebug & SDB_DDB) Debugger();
360 #endif
361 }
362 #endif
363
364 mutex_enter(p->p_lock);
365 if (scp->sc_onstack & SS_ONSTACK)
366 l->l_sigstk.ss_flags |= SS_ONSTACK;
367 else
368 l->l_sigstk.ss_flags &= ~SS_ONSTACK;
369 /* Restore signal mask */
370 native_sigset13_to_sigset(&scp->sc_mask, &mask);
371 (void) sigprocmask1(l, SIG_SETMASK, &mask, 0);
372 mutex_exit(p->p_lock);
373
374 return (EJUSTRETURN);
375 }
376
377 #if NFIRM_EVENTS > 0
378 /*
379 * Write out a series of 32-bit firm_events.
380 */
381 static int
ev_out32(struct firm_event * e,int n,struct uio * uio)382 ev_out32(struct firm_event *e, int n, struct uio *uio)
383 {
384 struct firm_event32 e32;
385 int error = 0;
386
387 while (n-- && error == 0) {
388 e32.id = e->id;
389 e32.value = e->value;
390 e32.time.tv_sec = e->time.tv_sec;
391 e32.time.tv_usec = e->time.tv_usec;
392 error = uiomove((void *)&e32, sizeof(e32), uio);
393 e++;
394 }
395 return (error);
396 }
397 #endif
398