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 = &sc;
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