xref: /netbsd/sys/arch/powerpc/powerpc/sig_machdep.c (revision bf9ec67e)
1 /*	$NetBSD: sig_machdep.c,v 1.5 2001/05/28 00:12:21 matt Exp $	*/
2 
3 /*
4  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5  * Copyright (C) 1995, 1996 TooLs GmbH.
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  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by TooLs GmbH.
19  * 4. The name of TooLs GmbH may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "opt_compat_netbsd.h"
35 
36 #include <sys/param.h>
37 #include <sys/mount.h>
38 #include <sys/proc.h>
39 #include <sys/syscallargs.h>
40 #include <sys/systm.h>
41 #include <sys/user.h>
42 
43 /*
44  * Send a signal to process.
45  */
46 void
47 sendsig(catcher, sig, mask, code)
48 	sig_t catcher;
49 	int sig;
50 	sigset_t *mask;
51 	u_long code;
52 {
53 	struct proc *p = curproc;
54 	struct trapframe *tf;
55 	struct sigframe *fp, frame;
56 	int onstack;
57 
58 	tf = trapframe(p);
59 
60 	/* Do we need to jump onto the signal stack? */
61 	onstack =
62 	    (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
63 	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
64 
65 	/* Allocate space for the signal handler context. */
66 	if (onstack)
67 		fp = (struct sigframe *)((caddr_t)p->p_sigctx.ps_sigstk.ss_sp +
68 						p->p_sigctx.ps_sigstk.ss_size);
69 	else
70 		fp = (struct sigframe *)tf->fixreg[1];
71 	fp = (struct sigframe *)((int)(fp - 1) & ~0xf);
72 
73 	/* Build stack frame for signal trampoline. */
74 	frame.sf_signum = sig;
75 	frame.sf_code = code;
76 
77 	/* Save register context. */
78 	frame.sf_sc.sc_frame = *tf;
79 
80 	/* Save signal stack. */
81 	frame.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK;
82 
83 	/* Save signal mask. */
84 	frame.sf_sc.sc_mask = *mask;
85 
86 #ifdef COMPAT_13
87 	/*
88 	 * XXX We always have to save an old style signal mask because
89 	 * XXX we might be delivering a signal to a process which will
90 	 * XXX escape from the signal in a non-standard way and invoke
91 	 * XXX sigreturn() directly.
92 	 */
93 	native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13);
94 #endif
95 
96 	if (copyout(&frame, fp, sizeof frame) != 0) {
97 		/*
98 		 * Process has trashed its stack; give it an illegal
99 		 * instructoin to halt it in its tracks.
100 		 */
101 		sigexit(p, SIGILL);
102 		/* NOTREACHED */
103 	}
104 
105 	/*
106 	 * Build context to run handler in.
107 	 */
108 	tf->fixreg[1] = (int)fp;
109 	tf->lr = (int)catcher;
110 	tf->fixreg[3] = (int)sig;
111 	tf->fixreg[4] = (int)code;
112 	tf->fixreg[5] = (int)&fp->sf_sc;
113 	tf->srr0 = (int)p->p_sigctx.ps_sigcode;
114 
115 	/* Remember that we're now on the signal stack. */
116 	if (onstack)
117 		p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
118 }
119 
120 /*
121  * System call to cleanup state after a signal handler returns.
122  */
123 int
124 sys___sigreturn14(p, v, retval)
125 	struct proc *p;
126 	void *v;
127 	register_t *retval;
128 {
129 	struct sys___sigreturn14_args /* {
130 		syscallarg(struct sigcontext *) sigcntxp;
131 	} */ *uap = v;
132 	struct sigcontext sc;
133 	struct trapframe *tf;
134 	int error;
135 
136 	/*
137 	 * The trampoline hands us the context.
138 	 * It is unsafe to keep track of it ourselves, in the event that a
139 	 * program jumps out of a signal hander.
140 	 */
141 	if ((error = copyin(SCARG(uap, sigcntxp), &sc, sizeof sc)) != 0)
142 		return (error);
143 
144 	/* Restore the register context. */
145 	tf = trapframe(p);
146 	if ((sc.sc_frame.srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC))
147 		return (EINVAL);
148 	*tf = sc.sc_frame;
149 
150 	/* Restore signal stack. */
151 	if (sc.sc_onstack & SS_ONSTACK)
152 		p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
153 	else
154 		p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK;
155 
156 	/* Restore signal mask. */
157 	(void) sigprocmask1(p, SIG_SETMASK, &sc.sc_mask, 0);
158 
159 	return (EJUSTRETURN);
160 }
161