1bdf0047cSRoger A. Faulkner /*
2bdf0047cSRoger A. Faulkner  * CDDL HEADER START
3bdf0047cSRoger A. Faulkner  *
4bdf0047cSRoger A. Faulkner  * The contents of this file are subject to the terms of the
5bdf0047cSRoger A. Faulkner  * Common Development and Distribution License (the "License").
6bdf0047cSRoger A. Faulkner  * You may not use this file except in compliance with the License.
7bdf0047cSRoger A. Faulkner  *
8bdf0047cSRoger A. Faulkner  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9bdf0047cSRoger A. Faulkner  * or http://www.opensolaris.org/os/licensing.
10bdf0047cSRoger A. Faulkner  * See the License for the specific language governing permissions
11bdf0047cSRoger A. Faulkner  * and limitations under the License.
12bdf0047cSRoger A. Faulkner  *
13bdf0047cSRoger A. Faulkner  * When distributing Covered Code, include this CDDL HEADER in each
14bdf0047cSRoger A. Faulkner  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15bdf0047cSRoger A. Faulkner  * If applicable, add the following below this CDDL HEADER, with the
16bdf0047cSRoger A. Faulkner  * fields enclosed by brackets "[]" replaced with your own identifying
17bdf0047cSRoger A. Faulkner  * information: Portions Copyright [yyyy] [name of copyright owner]
18bdf0047cSRoger A. Faulkner  *
19bdf0047cSRoger A. Faulkner  * CDDL HEADER END
20bdf0047cSRoger A. Faulkner  */
21bdf0047cSRoger A. Faulkner 
22bdf0047cSRoger A. Faulkner /*
2380e2ca85S  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24bdf0047cSRoger A. Faulkner  */
25bdf0047cSRoger A. Faulkner 
26bdf0047cSRoger A. Faulkner #include <sys/types.h>
27bdf0047cSRoger A. Faulkner #include <sys/brand.h>
28bdf0047cSRoger A. Faulkner #include <sys/errno.h>
29bdf0047cSRoger A. Faulkner #include <sys/sysconfig.h>
30bdf0047cSRoger A. Faulkner #include <sys/ucontext.h>
31bdf0047cSRoger A. Faulkner #include <sys/wait.h>
32bdf0047cSRoger A. Faulkner #include <stdlib.h>
33bdf0047cSRoger A. Faulkner #include <strings.h>
34bdf0047cSRoger A. Faulkner #include <signal.h>
35bdf0047cSRoger A. Faulkner 
36bdf0047cSRoger A. Faulkner #include <s10_brand.h>
3780e2ca85S #include <brand_misc.h>
38bdf0047cSRoger A. Faulkner #include <s10_misc.h>
39bdf0047cSRoger A. Faulkner #include <s10_signal.h>
40bdf0047cSRoger A. Faulkner 
41bdf0047cSRoger A. Faulkner s10_sighandler_t s10_handlers[S10_NSIG - 1];
42bdf0047cSRoger A. Faulkner 
43bdf0047cSRoger A. Faulkner /*
44bdf0047cSRoger A. Faulkner  * Theory of operation:
45bdf0047cSRoger A. Faulkner  *
46bdf0047cSRoger A. Faulkner  * As of now, Solaris 10 and solaris_nevada signal numbers match all the
47bdf0047cSRoger A. Faulkner  * way through SIGJVM2 (1 - 40) and the first 8 realtime signals (41 - 48).
48bdf0047cSRoger A. Faulkner  * However, solaris_nevada provides 32 realtime signals rather than 8 for S10.
49bdf0047cSRoger A. Faulkner  *
50bdf0047cSRoger A. Faulkner  * We do not assume that the current range of realtime signals is
51bdf0047cSRoger A. Faulkner  * _SIGRTMIN - _SIGRTMAX.  As a hedge against future changes,
52bdf0047cSRoger A. Faulkner  * we obtain the realtime signal range via SIGRTMIN and SIGRTMAX.
53bdf0047cSRoger A. Faulkner  *
54bdf0047cSRoger A. Faulkner  * Therefore, we must interpose on the various signal calls to translate
55bdf0047cSRoger A. Faulkner  * signal masks and signal handlers that deal with SIGRTMIN - SIGRTMAX to
56bdf0047cSRoger A. Faulkner  * refer to a potentially different range and to intercenpt any "illegal"
57bdf0047cSRoger A. Faulkner  * signals that might otherwise be sent to an S10 process.
58bdf0047cSRoger A. Faulkner  *
598f798d3aSRoger A. Faulkner  * Important exception:
608f798d3aSRoger A. Faulkner  * We cannot interpose on the SYS_context system call in order to deal with the
618f798d3aSRoger A. Faulkner  * sigset_t contained within the ucontext_t structure because the getcontext()
628f798d3aSRoger A. Faulkner  * part of this system call trap would then return an incorrect set of machine
638f798d3aSRoger A. Faulkner  * registers.  See the getcontext() functions in libc to get the gory details.
648f798d3aSRoger A. Faulkner  * The kernel code for getcontext() and setcontext() has been made brand-aware
658f798d3aSRoger A. Faulkner  * in order to deal with this.
668f798d3aSRoger A. Faulkner  *
67bdf0047cSRoger A. Faulkner  * Simple translation is all that is required to handle most system calls,
68bdf0047cSRoger A. Faulkner  * but signal handlers also must be interposed upon so that a user signal
69bdf0047cSRoger A. Faulkner  * handler sees proper signal numbers in its arguments, any passed siginfo_t
70bdf0047cSRoger A. Faulkner  * and in the signal mask reported in its ucontext_t.
71bdf0047cSRoger A. Faulkner  *
72bdf0047cSRoger A. Faulkner  * libc adds its own signal handler to handled signals such that the
73bdf0047cSRoger A. Faulkner  * signal delivery mechanism looks like:
74bdf0047cSRoger A. Faulkner  *
758f798d3aSRoger A. Faulkner  * signal ->
768f798d3aSRoger A. Faulkner  *     libc sigacthandler() ->
778f798d3aSRoger A. Faulkner  *         user signal handler()
78bdf0047cSRoger A. Faulkner  *
79bdf0047cSRoger A. Faulkner  * With interposition, this will instead look like:
80bdf0047cSRoger A. Faulkner  *
81bdf0047cSRoger A. Faulkner  * signal ->
828f798d3aSRoger A. Faulkner  *     s10_sigacthandler() ->
838f798d3aSRoger A. Faulkner  *         libc sigacthandler() ->
848f798d3aSRoger A. Faulkner  *             user signal handler()
85bdf0047cSRoger A. Faulkner  */
86bdf0047cSRoger A. Faulkner 
87bdf0047cSRoger A. Faulkner /*
88bdf0047cSRoger A. Faulkner  * A little exposition on SIGRTMIN and SIGRTMAX:
89bdf0047cSRoger A. Faulkner  *
90bdf0047cSRoger A. Faulkner  * For configurability reasons, in Solaris SIGRTMIN and SIGRTMAX are actually
91bdf0047cSRoger A. Faulkner  * #defined to be routines:
92bdf0047cSRoger A. Faulkner  *
93bdf0047cSRoger A. Faulkner  *    #define SIGRTMIN ((int)_sysconf(_SC_SIGRT_MIN))
94bdf0047cSRoger A. Faulkner  *    #define SIGRTMAX ((int)_sysconf(_SC_SIGRT_MAX))
95bdf0047cSRoger A. Faulkner  *
96bdf0047cSRoger A. Faulkner  * This means we need routines that will call the native sysconfig() system
97bdf0047cSRoger A. Faulkner  * call to find out what the native values for SIGRTMIN and SIGRTMAX are, and
98bdf0047cSRoger A. Faulkner  * those are native_sigrtmin() and native_sigrtmax(), respectively.
99bdf0047cSRoger A. Faulkner  *
100bdf0047cSRoger A. Faulkner  * To try and mitigate confusion this might cause, rather than use SIGRTMIN and
101bdf0047cSRoger A. Faulkner  * SIGRTMAX directly, mnemonic convenience macros are #defined to clarify the
102bdf0047cSRoger A. Faulkner  * matter:
103bdf0047cSRoger A. Faulkner  *
104bdf0047cSRoger A. Faulkner  *     S10_SIGRTMIN
105bdf0047cSRoger A. Faulkner  *     S10_SIGRTMAX
106bdf0047cSRoger A. Faulkner  *     NATIVE_SIGRTMIN
107bdf0047cSRoger A. Faulkner  *     NATIVE_SIGRTMAX
108bdf0047cSRoger A. Faulkner  */
109bdf0047cSRoger A. Faulkner 
110bdf0047cSRoger A. Faulkner static int
native_sigrtmin()111bdf0047cSRoger A. Faulkner native_sigrtmin()
112bdf0047cSRoger A. Faulkner {
113bdf0047cSRoger A. Faulkner 	static int sigrtmin;
114bdf0047cSRoger A. Faulkner 	sysret_t rval;
115bdf0047cSRoger A. Faulkner 
116bdf0047cSRoger A. Faulkner 	if (sigrtmin)
117bdf0047cSRoger A. Faulkner 		return (sigrtmin);
118bdf0047cSRoger A. Faulkner 	sigrtmin = __systemcall(&rval, SYS_sysconfig + 1024, _CONFIG_SIGRT_MIN)?
119bdf0047cSRoger A. Faulkner 	    _SIGRTMIN : (int)rval.sys_rval1;
120bdf0047cSRoger A. Faulkner 	return (sigrtmin);
121bdf0047cSRoger A. Faulkner }
122bdf0047cSRoger A. Faulkner 
123bdf0047cSRoger A. Faulkner static int
native_sigrtmax()124bdf0047cSRoger A. Faulkner native_sigrtmax()
125bdf0047cSRoger A. Faulkner {
126bdf0047cSRoger A. Faulkner 	static int sigrtmax;
127bdf0047cSRoger A. Faulkner 	sysret_t rval;
128bdf0047cSRoger A. Faulkner 
129bdf0047cSRoger A. Faulkner 	if (sigrtmax)
130bdf0047cSRoger A. Faulkner 		return (sigrtmax);
131bdf0047cSRoger A. Faulkner 	sigrtmax = __systemcall(&rval, SYS_sysconfig + 1024, _CONFIG_SIGRT_MAX)?
132bdf0047cSRoger A. Faulkner 	    _SIGRTMAX : (int)rval.sys_rval1;
133bdf0047cSRoger A. Faulkner 	return (sigrtmax);
134bdf0047cSRoger A. Faulkner }
135bdf0047cSRoger A. Faulkner 
136bdf0047cSRoger A. Faulkner #define	NATIVE_SIGRTMIN		(native_sigrtmin())
137bdf0047cSRoger A. Faulkner #define	NATIVE_SIGRTMAX		(native_sigrtmax())
138bdf0047cSRoger A. Faulkner 
139bdf0047cSRoger A. Faulkner /*
140bdf0047cSRoger A. Faulkner  * These #defines are setup to create the SIGADDSET and SIGISMEMBER macros,
141bdf0047cSRoger A. Faulkner  * needed because the sigaddset(3C) and sigismember(3C) calls make function
142bdf0047cSRoger A. Faulkner  * calls that end up being recursive in an interpositioned system call
143bdf0047cSRoger A. Faulkner  * environment.
144bdf0047cSRoger A. Faulkner  */
145bdf0047cSRoger A. Faulkner #define	MAXBITNO	(NBPW*8)
146bdf0047cSRoger A. Faulkner #define	SIGWORD(n)	((n-1)/MAXBITNO)
147bdf0047cSRoger A. Faulkner #define	BITMASK(n)	(1L<<((n-1)%MAXBITNO))
148bdf0047cSRoger A. Faulkner 
149bdf0047cSRoger A. Faulkner #define	SIGADDSET(sigset, sig) \
150bdf0047cSRoger A. Faulkner 	((sigset)->__sigbits[SIGWORD(sig)] |= BITMASK(sig))
151bdf0047cSRoger A. Faulkner 
152bdf0047cSRoger A. Faulkner #define	SIGISMEMBER(sigset, sig) \
153bdf0047cSRoger A. Faulkner 	(((sigset)->__sigbits[SIGWORD(sig)] & BITMASK(sig)) != 0)
154bdf0047cSRoger A. Faulkner 
155bdf0047cSRoger A. Faulkner /*
156bdf0047cSRoger A. Faulkner  * Convert an S10 signal number to its native value.
157bdf0047cSRoger A. Faulkner  */
158bdf0047cSRoger A. Faulkner static int
s10sig_to_native(int sig)159bdf0047cSRoger A. Faulkner s10sig_to_native(int sig)
160bdf0047cSRoger A. Faulkner {
161bdf0047cSRoger A. Faulkner 	/* signals 1 .. SIGJVM2 are the same between S10 and native */
162bdf0047cSRoger A. Faulkner 	if (sig <= SIGJVM2)
163bdf0047cSRoger A. Faulkner 		return (sig);
164bdf0047cSRoger A. Faulkner 
165bdf0047cSRoger A. Faulkner 	/*
166bdf0047cSRoger A. Faulkner 	 * If a signal is > SIGJVM2 but is < S10_SIGRTMIN, it's being used
167bdf0047cSRoger A. Faulkner 	 * for some private purpose we likely wouldn't emulate properly.
168bdf0047cSRoger A. Faulkner 	 */
169bdf0047cSRoger A. Faulkner 	if (sig < S10_SIGRTMIN)		/* can't happen */
170bdf0047cSRoger A. Faulkner 		return (-1);
171bdf0047cSRoger A. Faulkner 
17260242377S 	/*
17360242377S 	 * If an app passes in a signal that is out of range, it
17460242377S 	 * expects to get back EINVAL.
17560242377S 	 */
17660242377S 	if (sig > S10_MAXSIG)
17760242377S 		return (-1);
17860242377S 
179bdf0047cSRoger A. Faulkner 	/*
180bdf0047cSRoger A. Faulkner 	 * Map S10 RT signals to their native counterparts to the degree
181bdf0047cSRoger A. Faulkner 	 * possible.  If the signal would be out of the native RT signal
182bdf0047cSRoger A. Faulkner 	 * range, return an error to the caller.
183bdf0047cSRoger A. Faulkner 	 */
184bdf0047cSRoger A. Faulkner 	sig -= S10_SIGRTMIN;
185bdf0047cSRoger A. Faulkner 
186bdf0047cSRoger A. Faulkner 	if (sig > (NATIVE_SIGRTMAX - NATIVE_SIGRTMIN))
187bdf0047cSRoger A. Faulkner 		return (-1);
188bdf0047cSRoger A. Faulkner 
189bdf0047cSRoger A. Faulkner 	return (NATIVE_SIGRTMIN + sig);
190bdf0047cSRoger A. Faulkner }
191bdf0047cSRoger A. Faulkner 
192bdf0047cSRoger A. Faulkner /*
193bdf0047cSRoger A. Faulkner  * Convert an S10 sigset_t to its native version.
194bdf0047cSRoger A. Faulkner  */
195bdf0047cSRoger A. Faulkner int
s10sigset_to_native(const sigset_t * s10_set,sigset_t * native_set)196bdf0047cSRoger A. Faulkner s10sigset_to_native(const sigset_t *s10_set, sigset_t *native_set)
197bdf0047cSRoger A. Faulkner {
198bdf0047cSRoger A. Faulkner 	int sig;
199bdf0047cSRoger A. Faulkner 	int nativesig;
200bdf0047cSRoger A. Faulkner 	sigset_t srcset, newset;
201bdf0047cSRoger A. Faulkner 
20280e2ca85S 	if (brand_uucopy(s10_set, &srcset, sizeof (sigset_t)) != 0)
203bdf0047cSRoger A. Faulkner 		return (EFAULT);
204bdf0047cSRoger A. Faulkner 
205bdf0047cSRoger A. Faulkner 	(void) sigemptyset(&newset);
206bdf0047cSRoger A. Faulkner 
207bdf0047cSRoger A. Faulkner 	/*
208bdf0047cSRoger A. Faulkner 	 * Shortcut: we know the first 32 signals are the same in both
209bdf0047cSRoger A. Faulkner 	 * s10 and native Solaris.  Just assign the first word.
210bdf0047cSRoger A. Faulkner 	 */
211bdf0047cSRoger A. Faulkner 	newset.__sigbits[0] = srcset.__sigbits[0];
212bdf0047cSRoger A. Faulkner 
213bdf0047cSRoger A. Faulkner 	/*
214bdf0047cSRoger A. Faulkner 	 * Copy the remainder of the initial set of common signals.
215bdf0047cSRoger A. Faulkner 	 */
216bdf0047cSRoger A. Faulkner 	for (sig = 33; sig <= SIGJVM2; sig++)
217bdf0047cSRoger A. Faulkner 		if (SIGISMEMBER(&srcset, sig))
218bdf0047cSRoger A. Faulkner 			SIGADDSET(&newset, sig);
219bdf0047cSRoger A. Faulkner 
220bdf0047cSRoger A. Faulkner 	/* convert any S10 RT signals to their native equivalents */
221bdf0047cSRoger A. Faulkner 	for (sig = S10_SIGRTMIN; sig <= S10_SIGRTMAX; sig++) {
222bdf0047cSRoger A. Faulkner 		if (SIGISMEMBER(&srcset, sig) &&
223bdf0047cSRoger A. Faulkner 		    (nativesig = s10sig_to_native(sig)) > 0)
224bdf0047cSRoger A. Faulkner 			SIGADDSET(&newset, nativesig);
225bdf0047cSRoger A. Faulkner 	}
226bdf0047cSRoger A. Faulkner 
22780e2ca85S 	if (brand_uucopy(&newset, native_set, sizeof (sigset_t)) != 0)
228bdf0047cSRoger A. Faulkner 		return (EFAULT);
229bdf0047cSRoger A. Faulkner 
230bdf0047cSRoger A. Faulkner 	return (0);
231bdf0047cSRoger A. Faulkner }
232bdf0047cSRoger A. Faulkner 
233bdf0047cSRoger A. Faulkner /*
234bdf0047cSRoger A. Faulkner  * Convert a native signal number to its S10 value.
235bdf0047cSRoger A. Faulkner  */
236bdf0047cSRoger A. Faulkner int
nativesig_to_s10(int sig)237bdf0047cSRoger A. Faulkner nativesig_to_s10(int sig)
238bdf0047cSRoger A. Faulkner {
239bdf0047cSRoger A. Faulkner 	/* signals 1 .. SIGJVM2 are the same between native and S10 */
240bdf0047cSRoger A. Faulkner 	if (sig <= SIGJVM2)
241bdf0047cSRoger A. Faulkner 		return (sig);
242bdf0047cSRoger A. Faulkner 
243bdf0047cSRoger A. Faulkner 	/*
244bdf0047cSRoger A. Faulkner 	 * We have no way to emulate native signals between (SIGJVM2 + 1) and
245bdf0047cSRoger A. Faulkner 	 * NATIVE_SIGRTMIN, so return an error to the caller.
246bdf0047cSRoger A. Faulkner 	 */
247bdf0047cSRoger A. Faulkner 	if (sig < NATIVE_SIGRTMIN)	/* can't happen */
248bdf0047cSRoger A. Faulkner 		return (-1);
249bdf0047cSRoger A. Faulkner 
250bdf0047cSRoger A. Faulkner 	/*
251bdf0047cSRoger A. Faulkner 	 * Map native RT signals to their S10 counterparts to the degree
252bdf0047cSRoger A. Faulkner 	 * possible.  If the signal would be out of range for S10, return
253bdf0047cSRoger A. Faulkner 	 * an error to the caller.
254bdf0047cSRoger A. Faulkner 	 */
255bdf0047cSRoger A. Faulkner 	sig -= NATIVE_SIGRTMIN;
256bdf0047cSRoger A. Faulkner 
257bdf0047cSRoger A. Faulkner 	if (sig > (S10_SIGRTMAX - S10_SIGRTMIN))
258bdf0047cSRoger A. Faulkner 		return (-1);
259bdf0047cSRoger A. Faulkner 
260bdf0047cSRoger A. Faulkner 	return (S10_SIGRTMIN + sig);
261bdf0047cSRoger A. Faulkner }
262bdf0047cSRoger A. Faulkner 
263bdf0047cSRoger A. Faulkner /*
264bdf0047cSRoger A. Faulkner  * Convert a native sigset_t to its S10 version.
265bdf0047cSRoger A. Faulkner  */
266bdf0047cSRoger A. Faulkner int
nativesigset_to_s10(const sigset_t * native_set,sigset_t * s10_set)267bdf0047cSRoger A. Faulkner nativesigset_to_s10(const sigset_t *native_set, sigset_t *s10_set)
268bdf0047cSRoger A. Faulkner {
269bdf0047cSRoger A. Faulkner 	int sig;
270bdf0047cSRoger A. Faulkner 	int s10sig;
271bdf0047cSRoger A. Faulkner 	sigset_t srcset, newset;
272bdf0047cSRoger A. Faulkner 
27380e2ca85S 	if (brand_uucopy(native_set, &srcset, sizeof (sigset_t)) != 0)
274bdf0047cSRoger A. Faulkner 		return (EFAULT);
275bdf0047cSRoger A. Faulkner 
276bdf0047cSRoger A. Faulkner 	(void) sigemptyset(&newset);
277bdf0047cSRoger A. Faulkner 
278bdf0047cSRoger A. Faulkner 	/*
279bdf0047cSRoger A. Faulkner 	 * Shortcut: we know the first 32 signals are the same in both
280bdf0047cSRoger A. Faulkner 	 * s10 and native Solaris.  Just assign the first word.
281bdf0047cSRoger A. Faulkner 	 */
282bdf0047cSRoger A. Faulkner 	newset.__sigbits[0] = srcset.__sigbits[0];
283bdf0047cSRoger A. Faulkner 
284bdf0047cSRoger A. Faulkner 	/*
285bdf0047cSRoger A. Faulkner 	 * Copy the remainder of the initial set of common signals.
286bdf0047cSRoger A. Faulkner 	 */
287bdf0047cSRoger A. Faulkner 	for (sig = 33; sig <= SIGJVM2; sig++)
288bdf0047cSRoger A. Faulkner 		if (SIGISMEMBER(&srcset, sig))
289bdf0047cSRoger A. Faulkner 			SIGADDSET(&newset, sig);
290bdf0047cSRoger A. Faulkner 
291bdf0047cSRoger A. Faulkner 	/* convert any RT signals to their S10 values */
292bdf0047cSRoger A. Faulkner 	for (sig = NATIVE_SIGRTMIN; sig <= NATIVE_SIGRTMAX; sig++) {
293bdf0047cSRoger A. Faulkner 		if (SIGISMEMBER(&srcset, sig) &&
294bdf0047cSRoger A. Faulkner 		    (s10sig = nativesig_to_s10(sig)) > 0)
295bdf0047cSRoger A. Faulkner 			SIGADDSET(&newset, s10sig);
296bdf0047cSRoger A. Faulkner 	}
297bdf0047cSRoger A. Faulkner 
29880e2ca85S 	if (brand_uucopy(&newset, s10_set, sizeof (sigset_t)) != 0)
299bdf0047cSRoger A. Faulkner 		return (EFAULT);
300bdf0047cSRoger A. Faulkner 
301bdf0047cSRoger A. Faulkner 	return (0);
302bdf0047cSRoger A. Faulkner }
303bdf0047cSRoger A. Faulkner 
304bdf0047cSRoger A. Faulkner /*
305bdf0047cSRoger A. Faulkner  * This is our interposed signal handler.
306bdf0047cSRoger A. Faulkner  * Fix up the arguments received from the kernel and jump
307bdf0047cSRoger A. Faulkner  * to the s10 signal handler, normally libc's sigacthandler().
308bdf0047cSRoger A. Faulkner  */
309bdf0047cSRoger A. Faulkner static void
s10_sigacthandler(int sig,siginfo_t * sip,void * uvp)310bdf0047cSRoger A. Faulkner s10_sigacthandler(int sig, siginfo_t *sip, void *uvp)
311bdf0047cSRoger A. Faulkner {
312bdf0047cSRoger A. Faulkner 	int s10_sig;
313bdf0047cSRoger A. Faulkner 	ucontext_t *ucp;
314bdf0047cSRoger A. Faulkner 
315bdf0047cSRoger A. Faulkner 	s10_sig = nativesig_to_s10(sig);
316bdf0047cSRoger A. Faulkner 	if (s10_sig <= 0)	/* can't happen? */
31780e2ca85S 		brand_abort(sig, "Received an impossible signal");
318bdf0047cSRoger A. Faulkner 	if (sip != NULL) {
319bdf0047cSRoger A. Faulkner 		/*
320bdf0047cSRoger A. Faulkner 		 * All we really have to do is map the signal number,
321bdf0047cSRoger A. Faulkner 		 * which changes only for the realtime signals,
322bdf0047cSRoger A. Faulkner 		 * so all the rest of the siginfo structure is the
323bdf0047cSRoger A. Faulkner 		 * same between s10 and native.
324bdf0047cSRoger A. Faulkner 		 */
325bdf0047cSRoger A. Faulkner 		if (sip->si_signo != sig)	/* can't happen? */
32680e2ca85S 			brand_abort(sig, "Received an impossible siginfo");
327bdf0047cSRoger A. Faulkner 		sip->si_signo = s10_sig;
328bdf0047cSRoger A. Faulkner 	}
329bdf0047cSRoger A. Faulkner 	if ((ucp = uvp) != NULL &&
330bdf0047cSRoger A. Faulkner 	    (ucp->uc_flags & UC_SIGMASK))
331bdf0047cSRoger A. Faulkner 		(void) nativesigset_to_s10(&ucp->uc_sigmask, &ucp->uc_sigmask);
332bdf0047cSRoger A. Faulkner 
333bdf0047cSRoger A. Faulkner 	s10_handlers[s10_sig - 1](s10_sig, sip, uvp);
334bdf0047cSRoger A. Faulkner }
335bdf0047cSRoger A. Faulkner 
336bdf0047cSRoger A. Faulkner /*
337bdf0047cSRoger A. Faulkner  * Interposition upon SYS_lwp_sigmask
338bdf0047cSRoger A. Faulkner  */
339bdf0047cSRoger A. Faulkner int
s10_lwp_sigmask(sysret_t * rval,int how,uint_t bits0,uint_t bits1)340bdf0047cSRoger A. Faulkner s10_lwp_sigmask(sysret_t *rval, int how, uint_t bits0, uint_t bits1)
341bdf0047cSRoger A. Faulkner {
342bdf0047cSRoger A. Faulkner 	sigset_t s10_blockset;
343bdf0047cSRoger A. Faulkner 	sigset_t native_blockset;
344bdf0047cSRoger A. Faulkner 	int err;
345bdf0047cSRoger A. Faulkner 
346bdf0047cSRoger A. Faulkner 	s10_blockset.__sigbits[0] = bits0;
347bdf0047cSRoger A. Faulkner 	s10_blockset.__sigbits[1] = bits1;
348bdf0047cSRoger A. Faulkner 	s10_blockset.__sigbits[2] = 0;
349bdf0047cSRoger A. Faulkner 	s10_blockset.__sigbits[3] = 0;
350bdf0047cSRoger A. Faulkner 
351bdf0047cSRoger A. Faulkner 	(void) s10sigset_to_native(&s10_blockset, &native_blockset);
352bdf0047cSRoger A. Faulkner 
353bdf0047cSRoger A. Faulkner 	err = __systemcall(rval, SYS_lwp_sigmask + 1024,
354bdf0047cSRoger A. Faulkner 	    how,
355bdf0047cSRoger A. Faulkner 	    native_blockset.__sigbits[0],
356bdf0047cSRoger A. Faulkner 	    native_blockset.__sigbits[1],
357bdf0047cSRoger A. Faulkner 	    native_blockset.__sigbits[2],
358bdf0047cSRoger A. Faulkner 	    native_blockset.__sigbits[3]);
359bdf0047cSRoger A. Faulkner 
360bdf0047cSRoger A. Faulkner 	if (err != 0)
361bdf0047cSRoger A. Faulkner 		return (err);
362bdf0047cSRoger A. Faulkner 
363bdf0047cSRoger A. Faulkner 	native_blockset.__sigbits[0] = (int)rval->sys_rval1;
364bdf0047cSRoger A. Faulkner 	native_blockset.__sigbits[1] = (int)rval->sys_rval2;
365bdf0047cSRoger A. Faulkner 	native_blockset.__sigbits[2] = 0;
366bdf0047cSRoger A. Faulkner 	native_blockset.__sigbits[3] = 0;
367bdf0047cSRoger A. Faulkner 
368bdf0047cSRoger A. Faulkner 	(void) nativesigset_to_s10(&native_blockset, &s10_blockset);
369bdf0047cSRoger A. Faulkner 
370bdf0047cSRoger A. Faulkner 	rval->sys_rval1 = s10_blockset.__sigbits[0];
371bdf0047cSRoger A. Faulkner 	rval->sys_rval2 = s10_blockset.__sigbits[1];
372bdf0047cSRoger A. Faulkner 
373bdf0047cSRoger A. Faulkner 	return (0);
374bdf0047cSRoger A. Faulkner }
375bdf0047cSRoger A. Faulkner 
376bdf0047cSRoger A. Faulkner /*
377bdf0047cSRoger A. Faulkner  * Interposition upon SYS_sigprocmask
378bdf0047cSRoger A. Faulkner  */
379bdf0047cSRoger A. Faulkner int
s10_sigprocmask(sysret_t * rval,int how,const sigset_t * set,sigset_t * oset)380bdf0047cSRoger A. Faulkner s10_sigprocmask(sysret_t *rval, int how, const sigset_t *set, sigset_t *oset)
381bdf0047cSRoger A. Faulkner {
382bdf0047cSRoger A. Faulkner 	sigset_t sigset_set, sigset_oset;
383bdf0047cSRoger A. Faulkner 	sigset_t *set_ptr, *oset_ptr;
384bdf0047cSRoger A. Faulkner 	int err;
385bdf0047cSRoger A. Faulkner 
386bdf0047cSRoger A. Faulkner 	oset_ptr = (oset == NULL) ? NULL : &sigset_oset;
387bdf0047cSRoger A. Faulkner 	set_ptr = (set == NULL) ? NULL : &sigset_set;
388bdf0047cSRoger A. Faulkner 
389bdf0047cSRoger A. Faulkner 	if (set_ptr != NULL &&
390bdf0047cSRoger A. Faulkner 	    (err = s10sigset_to_native(set, set_ptr)) != 0)
391bdf0047cSRoger A. Faulkner 		return (err);
392bdf0047cSRoger A. Faulkner 
393bdf0047cSRoger A. Faulkner 	if ((err = __systemcall(rval, SYS_sigprocmask + 1024,
394bdf0047cSRoger A. Faulkner 	    how, set_ptr, oset_ptr)) != 0)
395bdf0047cSRoger A. Faulkner 		return (err);
396bdf0047cSRoger A. Faulkner 
397bdf0047cSRoger A. Faulkner 	if (oset_ptr != NULL &&
398bdf0047cSRoger A. Faulkner 	    (err = nativesigset_to_s10(oset_ptr, oset)) != 0)
399bdf0047cSRoger A. Faulkner 		return (err);
400bdf0047cSRoger A. Faulkner 
401bdf0047cSRoger A. Faulkner 	return (0);
402bdf0047cSRoger A. Faulkner }
403bdf0047cSRoger A. Faulkner 
404bdf0047cSRoger A. Faulkner /*
405bdf0047cSRoger A. Faulkner  * Interposition upon SYS_sigsuspend
406bdf0047cSRoger A. Faulkner  */
407bdf0047cSRoger A. Faulkner int
s10_sigsuspend(sysret_t * rval,const sigset_t * set)408bdf0047cSRoger A. Faulkner s10_sigsuspend(sysret_t *rval, const sigset_t *set)
409bdf0047cSRoger A. Faulkner {
410bdf0047cSRoger A. Faulkner 	sigset_t sigset_set;
411bdf0047cSRoger A. Faulkner 	int err;
412bdf0047cSRoger A. Faulkner 
413bdf0047cSRoger A. Faulkner 	if ((err = s10sigset_to_native(set, &sigset_set)) != 0) {
41480e2ca85S 		(void) B_TRUSS_POINT_1(rval, SYS_sigsuspend, err, set);
415bdf0047cSRoger A. Faulkner 		return (err);
416bdf0047cSRoger A. Faulkner 	}
417bdf0047cSRoger A. Faulkner 
418bdf0047cSRoger A. Faulkner 	return (__systemcall(rval, SYS_sigsuspend + 1024, &sigset_set));
419bdf0047cSRoger A. Faulkner }
420bdf0047cSRoger A. Faulkner 
421bdf0047cSRoger A. Faulkner /*
422bdf0047cSRoger A. Faulkner  * Interposition upon SYS_sigaction
423bdf0047cSRoger A. Faulkner  *
424bdf0047cSRoger A. Faulkner  * There is a fair amount of complexity here due to the need to interpose
425bdf0047cSRoger A. Faulkner  * on any registered user signal handler.
426bdf0047cSRoger A. Faulkner  *
427bdf0047cSRoger A. Faulkner  * The idea is that if a user signal handler is installed, we must install
428bdf0047cSRoger A. Faulkner  * our own signal handler between the system and the signal handler being
429bdf0047cSRoger A. Faulkner  * registered.  If the signal handler to be registered is SIG_DFL or SIG_IGN,
430bdf0047cSRoger A. Faulkner  * we should remove our interpositioned handler as it's no longer needed.
431bdf0047cSRoger A. Faulkner  *
432bdf0047cSRoger A. Faulkner  * The way we do this is we set the signal handler to call s10_sigacthandler(),
433bdf0047cSRoger A. Faulkner  * and then store the address of the passed signal handler in a global
434bdf0047cSRoger A. Faulkner  * per-process array, s10_handlers[].
435bdf0047cSRoger A. Faulkner  *
436bdf0047cSRoger A. Faulkner  * We rely on the fact that the s10 libc blocks all signals during
437bdf0047cSRoger A. Faulkner  * its call to the sigaction() system call to guarantee atomicity.
438bdf0047cSRoger A. Faulkner  */
439bdf0047cSRoger A. Faulkner int
s10_sigaction(sysret_t * rval,int sig,const struct sigaction * act,struct sigaction * oact)440bdf0047cSRoger A. Faulkner s10_sigaction(sysret_t *rval,
441bdf0047cSRoger A. Faulkner     int sig, const struct sigaction *act, struct sigaction *oact)
442bdf0047cSRoger A. Faulkner {
443bdf0047cSRoger A. Faulkner 	struct sigaction sigact, osigact;
444bdf0047cSRoger A. Faulkner 	struct sigaction *sigactp, *osigactp;
445bdf0047cSRoger A. Faulkner 	int err, nativesig;
446bdf0047cSRoger A. Faulkner 	void (*handler)();
447bdf0047cSRoger A. Faulkner 
448bdf0047cSRoger A. Faulkner 	if ((nativesig = s10sig_to_native(sig)) < 0) {
44980e2ca85S 		(void) B_TRUSS_POINT_3(rval, SYS_sigaction, EINVAL,
450bdf0047cSRoger A. Faulkner 		    sig, act, oact);
451bdf0047cSRoger A. Faulkner 		return (EINVAL);
452bdf0047cSRoger A. Faulkner 	}
453bdf0047cSRoger A. Faulkner 
454bdf0047cSRoger A. Faulkner 	if (act == NULL) {
455bdf0047cSRoger A. Faulkner 		sigactp = NULL;
456bdf0047cSRoger A. Faulkner 	} else {
457bdf0047cSRoger A. Faulkner 		sigactp = &sigact;
458bdf0047cSRoger A. Faulkner 
45980e2ca85S 		if (brand_uucopy(act, sigactp, sizeof (struct sigaction)) != 0)
460bdf0047cSRoger A. Faulkner 			return (EFAULT);
461bdf0047cSRoger A. Faulkner 
462bdf0047cSRoger A. Faulkner 		if ((err = s10sigset_to_native(&sigactp->sa_mask,
463bdf0047cSRoger A. Faulkner 		    &sigactp->sa_mask)) != 0) {
46480e2ca85S 			(void) B_TRUSS_POINT_3(rval, SYS_sigaction, err,
465bdf0047cSRoger A. Faulkner 			    sig, act, oact);
466bdf0047cSRoger A. Faulkner 			return (err);
467bdf0047cSRoger A. Faulkner 		}
468bdf0047cSRoger A. Faulkner 	}
469bdf0047cSRoger A. Faulkner 
470bdf0047cSRoger A. Faulkner 	osigactp = ((oact == NULL) ? NULL : &osigact);
471bdf0047cSRoger A. Faulkner 
472bdf0047cSRoger A. Faulkner 	if (sigactp != NULL) {
473bdf0047cSRoger A. Faulkner 		handler = sigactp->sa_handler;
474bdf0047cSRoger A. Faulkner 		if (handler != SIG_DFL && handler != SIG_IGN)
475*30699046SRichard Lowe 			sigactp->sa_sigaction = s10_sigacthandler;
476bdf0047cSRoger A. Faulkner 	}
477bdf0047cSRoger A. Faulkner 
478bdf0047cSRoger A. Faulkner 	if ((err = __systemcall(rval, SYS_sigaction + 1024,
479bdf0047cSRoger A. Faulkner 	    nativesig, sigactp, osigactp)) != 0)
480bdf0047cSRoger A. Faulkner 		return (err);
481bdf0047cSRoger A. Faulkner 
482bdf0047cSRoger A. Faulkner 	/*
483bdf0047cSRoger A. Faulkner 	 * Translate the old signal mask if we are supposed to return the old
484bdf0047cSRoger A. Faulkner 	 * struct sigaction.
485bdf0047cSRoger A. Faulkner 	 *
486bdf0047cSRoger A. Faulkner 	 * Note that we may have set the signal handler, but may return EFAULT
487bdf0047cSRoger A. Faulkner 	 * here if the oact parameter is bad.
488bdf0047cSRoger A. Faulkner 	 *
489bdf0047cSRoger A. Faulkner 	 * That's OK, because the direct system call acts the same way.
490bdf0047cSRoger A. Faulkner 	 */
491bdf0047cSRoger A. Faulkner 	if (osigactp != NULL) {
492bdf0047cSRoger A. Faulkner 		err = nativesigset_to_s10(&osigactp->sa_mask,
493bdf0047cSRoger A. Faulkner 		    &osigactp->sa_mask);
494bdf0047cSRoger A. Faulkner 
495*30699046SRichard Lowe 		if (osigactp->sa_sigaction == s10_sigacthandler)
496*30699046SRichard Lowe 			osigactp->sa_sigaction = s10_handlers[sig - 1];
497bdf0047cSRoger A. Faulkner 
49880e2ca85S 		if (err == 0 && brand_uucopy(osigactp, oact,
49980e2ca85S 		    sizeof (struct sigaction)) != 0)
500bdf0047cSRoger A. Faulkner 			err = EFAULT;
501bdf0047cSRoger A. Faulkner 	}
502bdf0047cSRoger A. Faulkner 
503bdf0047cSRoger A. Faulkner 	/*
504bdf0047cSRoger A. Faulkner 	 * Do not store SIG_DFL or SIG_IGN into the array of remembered
505bdf0047cSRoger A. Faulkner 	 * signal handlers.  Only store bona-fide function addresses.
506bdf0047cSRoger A. Faulkner 	 * This is to avoid a race condition in which some thread
507bdf0047cSRoger A. Faulkner 	 * sets the signal handler to SIG_DFL or SIG_IGN while some
508bdf0047cSRoger A. Faulkner 	 * other thread is fielding the signal but has not yet reached
509bdf0047cSRoger A. Faulkner 	 * s10_sigacthandler().  s10_sigacthandler() will unconditionally
510bdf0047cSRoger A. Faulkner 	 * call the remembered signal handler and it it calls SIG_DFL or
511bdf0047cSRoger A. Faulkner 	 * SIG_IGN, the process will incur a SIGSEGV or SIGBUS signal.
512bdf0047cSRoger A. Faulkner 	 * This also allows a vfork() child to set signal handlers
513bdf0047cSRoger A. Faulkner 	 * to SIG_DFL or SIG_IGN without corrupting the parent's
514bdf0047cSRoger A. Faulkner 	 * address space.
515bdf0047cSRoger A. Faulkner 	 */
516bdf0047cSRoger A. Faulkner 	if (sigactp != NULL &&
517bdf0047cSRoger A. Faulkner 	    handler != SIG_DFL && handler != SIG_IGN)
518bdf0047cSRoger A. Faulkner 		s10_handlers[sig - 1] = handler;
519bdf0047cSRoger A. Faulkner 
520bdf0047cSRoger A. Faulkner 	return (err);
521bdf0047cSRoger A. Faulkner }
522bdf0047cSRoger A. Faulkner 
523bdf0047cSRoger A. Faulkner /*
524bdf0047cSRoger A. Faulkner  * Interposition upon SYS_sigpending
525bdf0047cSRoger A. Faulkner  */
526bdf0047cSRoger A. Faulkner int
s10_sigpending(sysret_t * rval,int flag,sigset_t * set)527bdf0047cSRoger A. Faulkner s10_sigpending(sysret_t *rval, int flag, sigset_t *set)
528bdf0047cSRoger A. Faulkner {
529bdf0047cSRoger A. Faulkner 	sigset_t sigset_set;
530bdf0047cSRoger A. Faulkner 	int err;
531bdf0047cSRoger A. Faulkner 
532bdf0047cSRoger A. Faulkner 	if ((err = __systemcall(rval, SYS_sigpending + 1024,
533bdf0047cSRoger A. Faulkner 	    flag, &sigset_set)) != 0)
534bdf0047cSRoger A. Faulkner 		return (err);
535bdf0047cSRoger A. Faulkner 
536bdf0047cSRoger A. Faulkner 	if ((err = nativesigset_to_s10(&sigset_set, set)) != 0)
537bdf0047cSRoger A. Faulkner 		return (err);
538bdf0047cSRoger A. Faulkner 
539bdf0047cSRoger A. Faulkner 	return (0);
540bdf0047cSRoger A. Faulkner }
541bdf0047cSRoger A. Faulkner 
542bdf0047cSRoger A. Faulkner /*
543bdf0047cSRoger A. Faulkner  * Interposition upon SYS_sigsendsys
544bdf0047cSRoger A. Faulkner  */
545bdf0047cSRoger A. Faulkner int
s10_sigsendsys(sysret_t * rval,procset_t * psp,int sig)546bdf0047cSRoger A. Faulkner s10_sigsendsys(sysret_t *rval, procset_t *psp, int sig)
547bdf0047cSRoger A. Faulkner {
548bdf0047cSRoger A. Faulkner 	int nativesig;
549bdf0047cSRoger A. Faulkner 
550bdf0047cSRoger A. Faulkner 	if ((nativesig = s10sig_to_native(sig)) < 0) {
55180e2ca85S 		(void) B_TRUSS_POINT_2(rval, SYS_sigsendsys, EINVAL,
552bdf0047cSRoger A. Faulkner 		    psp, sig);
553bdf0047cSRoger A. Faulkner 		return (EINVAL);
554bdf0047cSRoger A. Faulkner 	}
555bdf0047cSRoger A. Faulkner 
556bdf0047cSRoger A. Faulkner 	return (__systemcall(rval, SYS_sigsendsys + 1024, psp, nativesig));
557bdf0047cSRoger A. Faulkner }
558bdf0047cSRoger A. Faulkner 
559bdf0047cSRoger A. Faulkner /*
560bdf0047cSRoger A. Faulkner  * Convert the siginfo_t code and status fields to an old style
561bdf0047cSRoger A. Faulkner  * wait status for s10_wait(), below.
562bdf0047cSRoger A. Faulkner  */
563bdf0047cSRoger A. Faulkner static int
wstat(int code,int status)564bdf0047cSRoger A. Faulkner wstat(int code, int status)
565bdf0047cSRoger A. Faulkner {
566bdf0047cSRoger A. Faulkner 	int stat = (status & 0377);
567bdf0047cSRoger A. Faulkner 
568bdf0047cSRoger A. Faulkner 	switch (code) {
569bdf0047cSRoger A. Faulkner 	case CLD_EXITED:
570bdf0047cSRoger A. Faulkner 		stat <<= 8;
571bdf0047cSRoger A. Faulkner 		break;
572bdf0047cSRoger A. Faulkner 	case CLD_DUMPED:
573bdf0047cSRoger A. Faulkner 		stat |= WCOREFLG;
574bdf0047cSRoger A. Faulkner 		break;
575bdf0047cSRoger A. Faulkner 	case CLD_KILLED:
576bdf0047cSRoger A. Faulkner 		break;
577bdf0047cSRoger A. Faulkner 	case CLD_TRAPPED:
578bdf0047cSRoger A. Faulkner 	case CLD_STOPPED:
579bdf0047cSRoger A. Faulkner 		stat <<= 8;
580bdf0047cSRoger A. Faulkner 		stat |= WSTOPFLG;
581bdf0047cSRoger A. Faulkner 		break;
582bdf0047cSRoger A. Faulkner 	case CLD_CONTINUED:
583bdf0047cSRoger A. Faulkner 		stat = WCONTFLG;
584bdf0047cSRoger A. Faulkner 		break;
585bdf0047cSRoger A. Faulkner 	}
586bdf0047cSRoger A. Faulkner 	return (stat);
587bdf0047cSRoger A. Faulkner }
588bdf0047cSRoger A. Faulkner 
589bdf0047cSRoger A. Faulkner /*
590bdf0047cSRoger A. Faulkner  * Interposition upon SYS_wait
591bdf0047cSRoger A. Faulkner  */
592bdf0047cSRoger A. Faulkner int
s10_wait(sysret_t * rval)593bdf0047cSRoger A. Faulkner s10_wait(sysret_t *rval)
594bdf0047cSRoger A. Faulkner {
595bdf0047cSRoger A. Faulkner 	int err;
596bdf0047cSRoger A. Faulkner 	siginfo_t info;
597bdf0047cSRoger A. Faulkner 
598bdf0047cSRoger A. Faulkner 	err = s10_waitid(rval, P_ALL, 0, &info, WEXITED | WTRAPPED);
599bdf0047cSRoger A. Faulkner 	if (err != 0)
600bdf0047cSRoger A. Faulkner 		return (err);
601bdf0047cSRoger A. Faulkner 
602bdf0047cSRoger A. Faulkner 	rval->sys_rval1 = info.si_pid;
603bdf0047cSRoger A. Faulkner 	rval->sys_rval2 = wstat(info.si_code, info.si_status);
604bdf0047cSRoger A. Faulkner 
605bdf0047cSRoger A. Faulkner 	return (0);
606bdf0047cSRoger A. Faulkner }
607bdf0047cSRoger A. Faulkner 
608bdf0047cSRoger A. Faulkner /*
609bdf0047cSRoger A. Faulkner  * Interposition upon SYS_waitid
610bdf0047cSRoger A. Faulkner  */
611bdf0047cSRoger A. Faulkner int
s10_waitid(sysret_t * rval,idtype_t idtype,id_t id,siginfo_t * infop,int options)612bdf0047cSRoger A. Faulkner s10_waitid(sysret_t *rval,
613bdf0047cSRoger A. Faulkner     idtype_t idtype, id_t id, siginfo_t *infop, int options)
614bdf0047cSRoger A. Faulkner {
615bdf0047cSRoger A. Faulkner 	int err, sig;
616bdf0047cSRoger A. Faulkner 
617bdf0047cSRoger A. Faulkner 	err = __systemcall(rval, SYS_waitid + 1024, idtype, id, infop, options);
618bdf0047cSRoger A. Faulkner 	if (err != 0)
619bdf0047cSRoger A. Faulkner 		return (err);
620bdf0047cSRoger A. Faulkner 
621bdf0047cSRoger A. Faulkner 	/*
622bdf0047cSRoger A. Faulkner 	 * If the process being waited for terminated or stopped due to a
623bdf0047cSRoger A. Faulkner 	 * signal, translate the signal number from its native value to its
624bdf0047cSRoger A. Faulkner 	 * S10 equivalent.
625bdf0047cSRoger A. Faulkner 	 *
626bdf0047cSRoger A. Faulkner 	 * If we can't legally translate the signal number, just sort of punt
627bdf0047cSRoger A. Faulkner 	 * and leave it untranslated.
628bdf0047cSRoger A. Faulkner 	 *
629bdf0047cSRoger A. Faulkner 	 * We shouldn't return EINVAL as the syscall didn't technically fail.
630bdf0047cSRoger A. Faulkner 	 */
631bdf0047cSRoger A. Faulkner 	if (infop->si_signo == SIGCLD && infop->si_code != CLD_EXITED &&
632bdf0047cSRoger A. Faulkner 	    (sig = nativesig_to_s10(infop->si_status)) > 0)
633bdf0047cSRoger A. Faulkner 		infop->si_status = sig;
634bdf0047cSRoger A. Faulkner 
635bdf0047cSRoger A. Faulkner 	return (0);
636bdf0047cSRoger A. Faulkner }
637bdf0047cSRoger A. Faulkner 
638bdf0047cSRoger A. Faulkner /*
639bdf0047cSRoger A. Faulkner  * Interposition upon SYS_sigtimedwait
640bdf0047cSRoger A. Faulkner  */
641bdf0047cSRoger A. Faulkner int
s10_sigtimedwait(sysret_t * rval,const sigset_t * set,siginfo_t * info,const timespec_t * timeout)642bdf0047cSRoger A. Faulkner s10_sigtimedwait(sysret_t *rval,
643bdf0047cSRoger A. Faulkner     const sigset_t *set, siginfo_t *info, const timespec_t *timeout)
644bdf0047cSRoger A. Faulkner {
645bdf0047cSRoger A. Faulkner 	sigset_t sigset_set;
646bdf0047cSRoger A. Faulkner 	int err, sig;
647bdf0047cSRoger A. Faulkner 
648bdf0047cSRoger A. Faulkner 	if ((err = s10sigset_to_native(set, &sigset_set)) != 0) {
64980e2ca85S 		(void) B_TRUSS_POINT_3(rval, SYS_sigtimedwait, err,
650bdf0047cSRoger A. Faulkner 		    set, info, timeout);
651bdf0047cSRoger A. Faulkner 		return (err);
652bdf0047cSRoger A. Faulkner 	}
653bdf0047cSRoger A. Faulkner 
654bdf0047cSRoger A. Faulkner 	if ((err = __systemcall(rval, SYS_sigtimedwait + 1024,
655bdf0047cSRoger A. Faulkner 	    &sigset_set, info, timeout)) != 0)
656bdf0047cSRoger A. Faulkner 		return (err);
657bdf0047cSRoger A. Faulkner 
658bdf0047cSRoger A. Faulkner 	if (info != NULL) {
659bdf0047cSRoger A. Faulkner 		/*
660bdf0047cSRoger A. Faulkner 		 * If we can't legally translate the signal number in the
661bdf0047cSRoger A. Faulkner 		 * siginfo_t, just sort of punt and leave it untranslated.
662bdf0047cSRoger A. Faulkner 		 *
663bdf0047cSRoger A. Faulkner 		 * We shouldn't return EINVAL as the syscall didn't technically
664bdf0047cSRoger A. Faulkner 		 * fail.
665bdf0047cSRoger A. Faulkner 		 */
666bdf0047cSRoger A. Faulkner 		if ((sig = nativesig_to_s10(info->si_signo)) > 0)
667bdf0047cSRoger A. Faulkner 			info->si_signo = sig;
668bdf0047cSRoger A. Faulkner 	}
669bdf0047cSRoger A. Faulkner 
670bdf0047cSRoger A. Faulkner 	/*
671bdf0047cSRoger A. Faulkner 	 * If we can't legally translate the signal number returned by the
672bdf0047cSRoger A. Faulkner 	 * sigtimedwait syscall, just sort of punt and leave it untranslated.
673bdf0047cSRoger A. Faulkner 	 *
674bdf0047cSRoger A. Faulkner 	 * We shouldn't return EINVAL as the syscall didn't technically
675bdf0047cSRoger A. Faulkner 	 * fail.
676bdf0047cSRoger A. Faulkner 	 */
677bdf0047cSRoger A. Faulkner 	if ((sig = nativesig_to_s10((int)rval->sys_rval1)) > 0)
678bdf0047cSRoger A. Faulkner 		rval->sys_rval1 = sig;
679bdf0047cSRoger A. Faulkner 
680bdf0047cSRoger A. Faulkner 	return (0);
681bdf0047cSRoger A. Faulkner }
682bdf0047cSRoger A. Faulkner 
683bdf0047cSRoger A. Faulkner /*
684bdf0047cSRoger A. Faulkner  * Interposition upon SYS_sigqueue
685bdf0047cSRoger A. Faulkner  */
686bdf0047cSRoger A. Faulkner int
s10_sigqueue(sysret_t * rval,pid_t pid,int signo,void * value,int si_code)687bdf0047cSRoger A. Faulkner s10_sigqueue(sysret_t *rval, pid_t pid, int signo, void *value, int si_code)
688bdf0047cSRoger A. Faulkner {
689bdf0047cSRoger A. Faulkner 	int nativesig;
690bdf0047cSRoger A. Faulkner 
691bdf0047cSRoger A. Faulkner 	if ((nativesig = s10sig_to_native(signo)) < 0) {
69280e2ca85S 		(void) B_TRUSS_POINT_4(rval, SYS_sigqueue, EINVAL,
693bdf0047cSRoger A. Faulkner 		    pid, signo, value, si_code);
694bdf0047cSRoger A. Faulkner 		return (EINVAL);
695bdf0047cSRoger A. Faulkner 	}
696bdf0047cSRoger A. Faulkner 
697bdf0047cSRoger A. Faulkner 	if (pid == 1)
698bdf0047cSRoger A. Faulkner 		pid = zone_init_pid;
699bdf0047cSRoger A. Faulkner 
700bdf0047cSRoger A. Faulkner 	/*
701bdf0047cSRoger A. Faulkner 	 * The native version of this syscall takes an extra argument.
702bdf0047cSRoger A. Faulkner 	 * The new last arg "block" flag should be zero.  The block flag
703bdf0047cSRoger A. Faulkner 	 * is used by the Opensolaris AIO implementation, which is now
704bdf0047cSRoger A. Faulkner 	 * part of libc.
705bdf0047cSRoger A. Faulkner 	 */
706bdf0047cSRoger A. Faulkner 	return (__systemcall(rval, SYS_sigqueue + 1024,
707bdf0047cSRoger A. Faulkner 	    pid, nativesig, value, si_code, 0));
708bdf0047cSRoger A. Faulkner }
709bdf0047cSRoger A. Faulkner 
710bdf0047cSRoger A. Faulkner /*
711bdf0047cSRoger A. Faulkner  * Interposition upon SYS_signotify
712bdf0047cSRoger A. Faulkner  */
713bdf0047cSRoger A. Faulkner int
s10_signotify(sysret_t * rval,int cmd,siginfo_t * siginfo,signotify_id_t * sn_id)714bdf0047cSRoger A. Faulkner s10_signotify(sysret_t *rval,
715bdf0047cSRoger A. Faulkner     int cmd, siginfo_t *siginfo, signotify_id_t *sn_id)
716bdf0047cSRoger A. Faulkner {
717bdf0047cSRoger A. Faulkner 	siginfo_t *infop, info;
718bdf0047cSRoger A. Faulkner 
719bdf0047cSRoger A. Faulkner 	infop = siginfo;
720bdf0047cSRoger A. Faulkner 
721bdf0047cSRoger A. Faulkner 	/* only check for a valid siginfo pointer in the case of SN_PROC */
722bdf0047cSRoger A. Faulkner 	if (cmd == SN_PROC) {
723bdf0047cSRoger A. Faulkner 		int nativesig;
724bdf0047cSRoger A. Faulkner 
72580e2ca85S 		if (brand_uucopy(infop, &info, sizeof (siginfo_t)) != 0)
726bdf0047cSRoger A. Faulkner 			return (EFAULT);
727bdf0047cSRoger A. Faulkner 
728bdf0047cSRoger A. Faulkner 		if ((nativesig = s10sig_to_native(info.si_signo)) < 0) {
72980e2ca85S 			(void) B_TRUSS_POINT_3(rval, SYS_signotify, EINVAL,
730bdf0047cSRoger A. Faulkner 			    cmd, siginfo, sn_id);
731bdf0047cSRoger A. Faulkner 			return (EINVAL);
732bdf0047cSRoger A. Faulkner 		}
733bdf0047cSRoger A. Faulkner 
734bdf0047cSRoger A. Faulkner 		info.si_signo = nativesig;
735bdf0047cSRoger A. Faulkner 		infop = &info;
736bdf0047cSRoger A. Faulkner 	}
737bdf0047cSRoger A. Faulkner 
738bdf0047cSRoger A. Faulkner 	return (__systemcall(rval, SYS_signotify + 1024, cmd, infop, sn_id));
739bdf0047cSRoger A. Faulkner }
740bdf0047cSRoger A. Faulkner 
741bdf0047cSRoger A. Faulkner /*
742bdf0047cSRoger A. Faulkner  * Interposition upon SYS_kill
743bdf0047cSRoger A. Faulkner  */
744bdf0047cSRoger A. Faulkner int
s10_kill(sysret_t * rval,pid_t pid,int sig)745bdf0047cSRoger A. Faulkner s10_kill(sysret_t *rval, pid_t pid, int sig)
746bdf0047cSRoger A. Faulkner {
747bdf0047cSRoger A. Faulkner 	int nativesig;
748bdf0047cSRoger A. Faulkner 
749bdf0047cSRoger A. Faulkner 	if ((nativesig = s10sig_to_native(sig)) < 0) {
75080e2ca85S 		(void) B_TRUSS_POINT_2(rval, SYS_kill, EINVAL, pid, sig);
751bdf0047cSRoger A. Faulkner 		return (EINVAL);
752bdf0047cSRoger A. Faulkner 	}
753bdf0047cSRoger A. Faulkner 
754bdf0047cSRoger A. Faulkner 	if (pid == 1)
755bdf0047cSRoger A. Faulkner 		pid = zone_init_pid;
756bdf0047cSRoger A. Faulkner 
757bdf0047cSRoger A. Faulkner 	return (__systemcall(rval, SYS_kill + 1024, pid, nativesig));
758bdf0047cSRoger A. Faulkner }
759bdf0047cSRoger A. Faulkner 
760bdf0047cSRoger A. Faulkner /*
761bdf0047cSRoger A. Faulkner  * Interposition upon SYS_lwp_create
762bdf0047cSRoger A. Faulkner  *
763bdf0047cSRoger A. Faulkner  * See also the s10_lwp_create_correct_fs() function in s10_brand.c
764bdf0047cSRoger A. Faulkner  * for the special case of creating an lwp in a 64-bit x86 process.
765bdf0047cSRoger A. Faulkner  */
766bdf0047cSRoger A. Faulkner int
s10_lwp_create(sysret_t * rval,ucontext_t * ucp,int flags,id_t * new_lwp)767bdf0047cSRoger A. Faulkner s10_lwp_create(sysret_t *rval, ucontext_t *ucp, int flags, id_t *new_lwp)
768bdf0047cSRoger A. Faulkner {
769bdf0047cSRoger A. Faulkner 	ucontext_t s10_uc;
770bdf0047cSRoger A. Faulkner 
77180e2ca85S 	if (brand_uucopy(ucp, &s10_uc, sizeof (ucontext_t)) != 0)
772bdf0047cSRoger A. Faulkner 		return (EFAULT);
773bdf0047cSRoger A. Faulkner 
774bdf0047cSRoger A. Faulkner 	if (s10_uc.uc_flags & UC_SIGMASK)
775bdf0047cSRoger A. Faulkner 		(void) s10sigset_to_native(&s10_uc.uc_sigmask,
776bdf0047cSRoger A. Faulkner 		    &s10_uc.uc_sigmask);
777bdf0047cSRoger A. Faulkner 
778bdf0047cSRoger A. Faulkner 	return (__systemcall(rval, SYS_lwp_create + 1024,
779bdf0047cSRoger A. Faulkner 	    &s10_uc, flags, new_lwp));
780bdf0047cSRoger A. Faulkner }
781bdf0047cSRoger A. Faulkner 
782bdf0047cSRoger A. Faulkner /*
783bdf0047cSRoger A. Faulkner  * Interposition upon SYS_lwp_kill
784bdf0047cSRoger A. Faulkner  */
785bdf0047cSRoger A. Faulkner int
s10_lwp_kill(sysret_t * rval,id_t lwpid,int sig)786bdf0047cSRoger A. Faulkner s10_lwp_kill(sysret_t *rval, id_t lwpid, int sig)
787bdf0047cSRoger A. Faulkner {
788bdf0047cSRoger A. Faulkner 	int nativesig;
789bdf0047cSRoger A. Faulkner 
790bdf0047cSRoger A. Faulkner 	if ((nativesig = s10sig_to_native(sig)) < 0) {
79180e2ca85S 		(void) B_TRUSS_POINT_2(rval, SYS_lwp_kill, EINVAL,
792bdf0047cSRoger A. Faulkner 		    lwpid, sig);
793bdf0047cSRoger A. Faulkner 		return (EINVAL);
794bdf0047cSRoger A. Faulkner 	}
795bdf0047cSRoger A. Faulkner 
796bdf0047cSRoger A. Faulkner 	return (__systemcall(rval, SYS_lwp_kill + 1024, lwpid, nativesig));
797bdf0047cSRoger A. Faulkner }
798