xref: /titanic_51/usr/src/ucblib/libucb/sparc/sys/signal.c (revision be10f7d91e42e379302ee5ead703b5f0bf8b47c6)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley 4.3 BSD
327c478bd9Sstevel@tonic-gate  * under license from the Regents of the University of California.
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate  * 4.3BSD signal compatibility functions
417c478bd9Sstevel@tonic-gate  *
427c478bd9Sstevel@tonic-gate  * the implementation interprets signal masks equal to -1 as "all of the
437c478bd9Sstevel@tonic-gate  * signals in the signal set", thereby allowing signals with numbers
447c478bd9Sstevel@tonic-gate  * above 32 to be blocked when referenced in code such as:
457c478bd9Sstevel@tonic-gate  *
467c478bd9Sstevel@tonic-gate  *	for (i = 0; i < NSIG; i++)
477c478bd9Sstevel@tonic-gate  *		mask |= sigmask(i)
487c478bd9Sstevel@tonic-gate  */
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #include <sys/types.h>
517c478bd9Sstevel@tonic-gate #include <ucontext.h>
527c478bd9Sstevel@tonic-gate #include <signal.h>
537c478bd9Sstevel@tonic-gate #include <errno.h>
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate #undef	BUS_OBJERR	/* namespace conflict */
567c478bd9Sstevel@tonic-gate #include <sys/siginfo.h>
577c478bd9Sstevel@tonic-gate #include "libc.h"
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #pragma weak sigvechandler = _sigvechandler
607c478bd9Sstevel@tonic-gate #pragma weak sigsetmask = _sigsetmask
617c478bd9Sstevel@tonic-gate #pragma weak sigblock = _sigblock
627c478bd9Sstevel@tonic-gate #pragma weak sigpause = usigpause
637c478bd9Sstevel@tonic-gate #pragma weak sigvec = _sigvec
647c478bd9Sstevel@tonic-gate #pragma weak sigstack = _sigstack
657c478bd9Sstevel@tonic-gate #pragma weak signal = usignal
667c478bd9Sstevel@tonic-gate #pragma weak siginterrupt = _siginterrupt
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate /*
697c478bd9Sstevel@tonic-gate  * DO NOT remove the _ from these 3 functions or the subsequent
707c478bd9Sstevel@tonic-gate  * calls to them below.  The non _ versions of these functions
717c478bd9Sstevel@tonic-gate  * are the wrong functions to call.  This is BCP.  Extra
727c478bd9Sstevel@tonic-gate  * care should be taken when modifying this code.
737c478bd9Sstevel@tonic-gate  */
747c478bd9Sstevel@tonic-gate extern int _sigfillset(sigset_t *);
757c478bd9Sstevel@tonic-gate extern int _sigemptyset(sigset_t *);
767c478bd9Sstevel@tonic-gate extern int _sigprocmask(int, const sigset_t *, sigset_t *);
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate #define	set2mask(setp) ((setp)->__sigbits[0])
797c478bd9Sstevel@tonic-gate #define	mask2set(mask, setp) \
807c478bd9Sstevel@tonic-gate 	((mask) == -1 ? _sigfillset(setp) : \
817c478bd9Sstevel@tonic-gate 	    ((void) _sigemptyset(setp), (((setp)->__sigbits[0]) = (int)(mask))))
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate void (*_siguhandler[NSIG])() = { 0 };
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate /*
867c478bd9Sstevel@tonic-gate  * forward declarations
877c478bd9Sstevel@tonic-gate  */
887c478bd9Sstevel@tonic-gate int ucbsiginterrupt(int, int);
897c478bd9Sstevel@tonic-gate int ucbsigvec(int, struct sigvec *, struct sigvec *);
907c478bd9Sstevel@tonic-gate int ucbsigpause(int);
917c478bd9Sstevel@tonic-gate int ucbsigblock(int);
927c478bd9Sstevel@tonic-gate int ucbsigsetmask(int);
937c478bd9Sstevel@tonic-gate static void ucbsigvechandler(int, siginfo_t *, ucontext_t *);
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate  * sigvechandler is the real signal handler installed for all
977c478bd9Sstevel@tonic-gate  * signals handled in the 4.3BSD compatibility interface - it translates
987c478bd9Sstevel@tonic-gate  * SVR4 signal hander arguments into 4.3BSD signal handler arguments
997c478bd9Sstevel@tonic-gate  * and then calls the real handler
1007c478bd9Sstevel@tonic-gate  */
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate int
1037c478bd9Sstevel@tonic-gate _sigvechandler(int sig, siginfo_t *sip, ucontext_t *ucp)
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate 	ucbsigvechandler(sig, sip, ucp);
1067c478bd9Sstevel@tonic-gate 	return (0);	/* keep the same as the original prototype */
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate static void
1107c478bd9Sstevel@tonic-gate ucbsigvechandler(int sig, siginfo_t *sip, ucontext_t *ucp)
1117c478bd9Sstevel@tonic-gate {
1127c478bd9Sstevel@tonic-gate 	struct sigcontext sc;
1137c478bd9Sstevel@tonic-gate 	int code;
1147c478bd9Sstevel@tonic-gate 	char *addr;
1157c478bd9Sstevel@tonic-gate #ifdef NEVER
1167c478bd9Sstevel@tonic-gate 	int gwinswitch = 0;
1177c478bd9Sstevel@tonic-gate #endif
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	sc.sc_onstack = ((ucp->uc_stack.ss_flags & SS_ONSTACK) != 0);
1207c478bd9Sstevel@tonic-gate 	sc.sc_mask = set2mask(&ucp->uc_sigmask);
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate #if defined(__sparc)
1237c478bd9Sstevel@tonic-gate 	if (sig == SIGFPE && sip != NULL && SI_FROMKERNEL(sip) &&
1247c478bd9Sstevel@tonic-gate 	    (sip->si_code == FPE_INTDIV || sip->si_code == FPE_INTOVF)) {
1257c478bd9Sstevel@tonic-gate 		/*
1267c478bd9Sstevel@tonic-gate 		 * Hack to emulate the 4.x kernel behavior of incrementing
1277c478bd9Sstevel@tonic-gate 		 * the PC on integer divide by zero and integer overflow
1287c478bd9Sstevel@tonic-gate 		 * on sparc machines.  (5.x does not increment the PC.)
1297c478bd9Sstevel@tonic-gate 		 */
1307c478bd9Sstevel@tonic-gate 		ucp->uc_mcontext.gregs[REG_PC] =
1317c478bd9Sstevel@tonic-gate 		    ucp->uc_mcontext.gregs[REG_nPC];
1327c478bd9Sstevel@tonic-gate 		ucp->uc_mcontext.gregs[REG_nPC] += 4;
1337c478bd9Sstevel@tonic-gate 	}
1347c478bd9Sstevel@tonic-gate 	sc.sc_sp = ucp->uc_mcontext.gregs[REG_SP];
1357c478bd9Sstevel@tonic-gate 	sc.sc_pc = ucp->uc_mcontext.gregs[REG_PC];
1367c478bd9Sstevel@tonic-gate 	sc.sc_npc = ucp->uc_mcontext.gregs[REG_nPC];
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	/* XX64 There is no REG_PSR for sparcv9, we map in REG_CCR for now */
1397c478bd9Sstevel@tonic-gate #if defined(__sparcv9)
1407c478bd9Sstevel@tonic-gate 	sc.sc_psr = ucp->uc_mcontext.gregs[REG_CCR];
1417c478bd9Sstevel@tonic-gate #else
1427c478bd9Sstevel@tonic-gate 	sc.sc_psr = ucp->uc_mcontext.gregs[REG_PSR];
1437c478bd9Sstevel@tonic-gate #endif
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	sc.sc_g1 = ucp->uc_mcontext.gregs[REG_G1];
1467c478bd9Sstevel@tonic-gate 	sc.sc_o0 = ucp->uc_mcontext.gregs[REG_O0];
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	/*
1497c478bd9Sstevel@tonic-gate 	 * XXX - What a kludge!
1507c478bd9Sstevel@tonic-gate 	 * Store a pointer to the original ucontext_t in the sigcontext
1517c478bd9Sstevel@tonic-gate 	 * so that it's available to the sigcleanup call that needs to
1527c478bd9Sstevel@tonic-gate 	 * return from the signal handler.  Otherwise, vital information
1537c478bd9Sstevel@tonic-gate 	 * (e.g., the "out" registers) that's only saved in the
1547c478bd9Sstevel@tonic-gate 	 * ucontext_t isn't available to sigcleanup.
1557c478bd9Sstevel@tonic-gate 	 */
1567c478bd9Sstevel@tonic-gate 	sc.sc_wbcnt = (int)(sizeof (*ucp));
157*be10f7d9Smuffin 	sc.sc_spbuf[0] = (char *)(uintptr_t)sig;
1587c478bd9Sstevel@tonic-gate 	sc.sc_spbuf[1] = (char *)ucp;
1597c478bd9Sstevel@tonic-gate #ifdef NEVER
1607c478bd9Sstevel@tonic-gate 	/*
1617c478bd9Sstevel@tonic-gate 	 * XXX - Sorry, we can never pass the saved register windows
1627c478bd9Sstevel@tonic-gate 	 * on in the sigcontext because we use that space to save the
1637c478bd9Sstevel@tonic-gate 	 * ucontext_t.
1647c478bd9Sstevel@tonic-gate 	 */
1657c478bd9Sstevel@tonic-gate 	if (ucp->uc_mcontext.gwins != (gwindows_t *)0) {
1667c478bd9Sstevel@tonic-gate 		int i, j;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 		gwinswitch = 1;
1697c478bd9Sstevel@tonic-gate 		sc.sc_wbcnt = ucp->uc_mcontext.gwins->wbcnt;
1707c478bd9Sstevel@tonic-gate 		/* XXX - should use bcopy to move this in bulk */
1717c478bd9Sstevel@tonic-gate 		for (i = 0; i < ucp->uc_mcontext.gwins; i++) {
1727c478bd9Sstevel@tonic-gate 			sc.sc_spbuf[i] = ucp->uc_mcontext.gwins->spbuf[i];
1737c478bd9Sstevel@tonic-gate 			for (j = 0; j < 8; j++)
1747c478bd9Sstevel@tonic-gate 				sc.sc_wbuf[i][j] =
1757c478bd9Sstevel@tonic-gate 				    ucp->uc_mcontext.gwins->wbuf[i].rw_local[j];
1767c478bd9Sstevel@tonic-gate 			for (j = 0; j < 8; j++)
1777c478bd9Sstevel@tonic-gate 				sc.sc_wbuf[i][j+8] =
1787c478bd9Sstevel@tonic-gate 				    ucp->uc_mcontext.gwins->wbuf[i].rw_in[j];
1797c478bd9Sstevel@tonic-gate 		}
1807c478bd9Sstevel@tonic-gate 	}
1817c478bd9Sstevel@tonic-gate #endif
1827c478bd9Sstevel@tonic-gate #endif
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	/*
1857c478bd9Sstevel@tonic-gate 	 * Translate signal codes from new to old.
1867c478bd9Sstevel@tonic-gate 	 * /usr/include/sys/siginfo.h contains new codes.
1877c478bd9Sstevel@tonic-gate 	 * /usr/ucbinclude/sys/signal.h contains old codes.
1887c478bd9Sstevel@tonic-gate 	 */
1897c478bd9Sstevel@tonic-gate 	code = 0;
1907c478bd9Sstevel@tonic-gate 	addr = SIG_NOADDR;
1917c478bd9Sstevel@tonic-gate 	if (sip != NULL && SI_FROMKERNEL(sip)) {
1927c478bd9Sstevel@tonic-gate 		addr = sip->si_addr;
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 		switch (sig) {
1957c478bd9Sstevel@tonic-gate 		case SIGILL:
1967c478bd9Sstevel@tonic-gate 			switch (sip->si_code) {
1977c478bd9Sstevel@tonic-gate 			case ILL_PRVOPC:
1987c478bd9Sstevel@tonic-gate 				code = ILL_PRIVINSTR_FAULT;
1997c478bd9Sstevel@tonic-gate 				break;
2007c478bd9Sstevel@tonic-gate 			case ILL_BADSTK:
2017c478bd9Sstevel@tonic-gate 				code = ILL_STACK;
2027c478bd9Sstevel@tonic-gate 				break;
2037c478bd9Sstevel@tonic-gate 			case ILL_ILLTRP:
2047c478bd9Sstevel@tonic-gate 				code = ILL_TRAP_FAULT(sip->si_trapno);
2057c478bd9Sstevel@tonic-gate 				break;
2067c478bd9Sstevel@tonic-gate 			default:
2077c478bd9Sstevel@tonic-gate 				code = ILL_ILLINSTR_FAULT;
2087c478bd9Sstevel@tonic-gate 				break;
2097c478bd9Sstevel@tonic-gate 			}
2107c478bd9Sstevel@tonic-gate 			break;
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 		case SIGEMT:
2137c478bd9Sstevel@tonic-gate 			code = EMT_TAG;
2147c478bd9Sstevel@tonic-gate 			break;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 		case SIGFPE:
2177c478bd9Sstevel@tonic-gate 			switch (sip->si_code) {
2187c478bd9Sstevel@tonic-gate 			case FPE_INTDIV:
2197c478bd9Sstevel@tonic-gate 				code = FPE_INTDIV_TRAP;
2207c478bd9Sstevel@tonic-gate 				break;
2217c478bd9Sstevel@tonic-gate 			case FPE_INTOVF:
2227c478bd9Sstevel@tonic-gate 				code = FPE_INTOVF_TRAP;
2237c478bd9Sstevel@tonic-gate 				break;
2247c478bd9Sstevel@tonic-gate 			case FPE_FLTDIV:
2257c478bd9Sstevel@tonic-gate 				code = FPE_FLTDIV_TRAP;
2267c478bd9Sstevel@tonic-gate 				break;
2277c478bd9Sstevel@tonic-gate 			case FPE_FLTOVF:
2287c478bd9Sstevel@tonic-gate 				code = FPE_FLTOVF_TRAP;
2297c478bd9Sstevel@tonic-gate 				break;
2307c478bd9Sstevel@tonic-gate 			case FPE_FLTUND:
2317c478bd9Sstevel@tonic-gate 				code = FPE_FLTUND_TRAP;
2327c478bd9Sstevel@tonic-gate 				break;
2337c478bd9Sstevel@tonic-gate 			case FPE_FLTRES:
2347c478bd9Sstevel@tonic-gate 				code = FPE_FLTINEX_TRAP;
2357c478bd9Sstevel@tonic-gate 				break;
2367c478bd9Sstevel@tonic-gate 			default:
2377c478bd9Sstevel@tonic-gate 				code = FPE_FLTOPERR_TRAP;
2387c478bd9Sstevel@tonic-gate 				break;
2397c478bd9Sstevel@tonic-gate 			}
2407c478bd9Sstevel@tonic-gate 			break;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 		case SIGBUS:
2437c478bd9Sstevel@tonic-gate 			switch (sip->si_code) {
2447c478bd9Sstevel@tonic-gate 			case BUS_ADRALN:
2457c478bd9Sstevel@tonic-gate 				code = BUS_ALIGN;
2467c478bd9Sstevel@tonic-gate 				break;
2477c478bd9Sstevel@tonic-gate 			case BUS_ADRERR:
2487c478bd9Sstevel@tonic-gate 				code = BUS_HWERR;
2497c478bd9Sstevel@tonic-gate 				break;
2507c478bd9Sstevel@tonic-gate 			default:	/* BUS_OBJERR */
2517c478bd9Sstevel@tonic-gate 				code = FC_MAKE_ERR(sip->si_errno);
2527c478bd9Sstevel@tonic-gate 				break;
2537c478bd9Sstevel@tonic-gate 			}
2547c478bd9Sstevel@tonic-gate 			break;
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 		case SIGSEGV:
2577c478bd9Sstevel@tonic-gate 			switch (sip->si_code) {
2587c478bd9Sstevel@tonic-gate 			case SEGV_MAPERR:
2597c478bd9Sstevel@tonic-gate 				code = SEGV_NOMAP;
2607c478bd9Sstevel@tonic-gate 				break;
2617c478bd9Sstevel@tonic-gate 			case SEGV_ACCERR:
2627c478bd9Sstevel@tonic-gate 				code = SEGV_PROT;
2637c478bd9Sstevel@tonic-gate 				break;
2647c478bd9Sstevel@tonic-gate 			default:
2657c478bd9Sstevel@tonic-gate 				code = FC_MAKE_ERR(sip->si_errno);
2667c478bd9Sstevel@tonic-gate 				break;
2677c478bd9Sstevel@tonic-gate 			}
2687c478bd9Sstevel@tonic-gate 			break;
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 		default:
2717c478bd9Sstevel@tonic-gate 			addr = SIG_NOADDR;
2727c478bd9Sstevel@tonic-gate 			break;
2737c478bd9Sstevel@tonic-gate 		}
2747c478bd9Sstevel@tonic-gate 	}
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	(*_siguhandler[sig])(sig, code, &sc, addr);
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	if (sc.sc_onstack)
2797c478bd9Sstevel@tonic-gate 		ucp->uc_stack.ss_flags |= SS_ONSTACK;
2807c478bd9Sstevel@tonic-gate 	else
2817c478bd9Sstevel@tonic-gate 		ucp->uc_stack.ss_flags &= ~SS_ONSTACK;
2827c478bd9Sstevel@tonic-gate 	mask2set(sc.sc_mask, &ucp->uc_sigmask);
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate #if defined(__sparc)
2857c478bd9Sstevel@tonic-gate 	ucp->uc_mcontext.gregs[REG_SP] = sc.sc_sp;
2867c478bd9Sstevel@tonic-gate 	ucp->uc_mcontext.gregs[REG_PC] = sc.sc_pc;
2877c478bd9Sstevel@tonic-gate 	ucp->uc_mcontext.gregs[REG_nPC] = sc.sc_npc;
2887c478bd9Sstevel@tonic-gate #if defined(__sparcv9)
2897c478bd9Sstevel@tonic-gate 	ucp->uc_mcontext.gregs[REG_CCR] = sc.sc_psr;
2907c478bd9Sstevel@tonic-gate #else
2917c478bd9Sstevel@tonic-gate 	ucp->uc_mcontext.gregs[REG_PSR] = sc.sc_psr;
2927c478bd9Sstevel@tonic-gate #endif
2937c478bd9Sstevel@tonic-gate 	ucp->uc_mcontext.gregs[REG_G1] = sc.sc_g1;
2947c478bd9Sstevel@tonic-gate 	ucp->uc_mcontext.gregs[REG_O0] = sc.sc_o0;
2957c478bd9Sstevel@tonic-gate #ifdef NEVER
2967c478bd9Sstevel@tonic-gate 	if (gwinswitch == 1) {
2977c478bd9Sstevel@tonic-gate 		int i, j;
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 		ucp->uc_mcontext.gwins->wbcnt = sc.sc_wbcnt;
3007c478bd9Sstevel@tonic-gate 		/* XXX - should use bcopy to move this in bulk */
3017c478bd9Sstevel@tonic-gate 		for (i = 0; i < sc.sc_wbcnt; i++) {
3027c478bd9Sstevel@tonic-gate 			ucp->uc_mcontext.gwins->spbuf[i] = sc.sc_spbuf[i];
3037c478bd9Sstevel@tonic-gate 			for (j = 0; j < 8; j++)
3047c478bd9Sstevel@tonic-gate 				ucp->uc_mcontext.gwins->wbuf[i].rw_local[j] =
3057c478bd9Sstevel@tonic-gate 				    sc.sc_wbuf[i][j];
3067c478bd9Sstevel@tonic-gate 			for (j = 0; j < 8; j++)
3077c478bd9Sstevel@tonic-gate 				ucp->uc_mcontext.gwins->wbuf[i].rw_in[j] =
3087c478bd9Sstevel@tonic-gate 				    sc.sc_wbuf[i][j+8];
3097c478bd9Sstevel@tonic-gate 		}
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate #endif
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 	if (sig == SIGFPE) {
3147c478bd9Sstevel@tonic-gate 		if (ucp->uc_mcontext.fpregs.fpu_qcnt > 0) {
3157c478bd9Sstevel@tonic-gate 			ucp->uc_mcontext.fpregs.fpu_qcnt--;
3167c478bd9Sstevel@tonic-gate 			ucp->uc_mcontext.fpregs.fpu_q++;
3177c478bd9Sstevel@tonic-gate 		}
3187c478bd9Sstevel@tonic-gate 	}
3197c478bd9Sstevel@tonic-gate #endif
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	(void) setcontext(ucp);
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate #if defined(__sparc)
3257c478bd9Sstevel@tonic-gate /*
3267c478bd9Sstevel@tonic-gate  * Emulate the special sigcleanup trap.
3277c478bd9Sstevel@tonic-gate  * This is only used by statically linked 4.x applications
3287c478bd9Sstevel@tonic-gate  * and thus is only called by the static BCP support.
3297c478bd9Sstevel@tonic-gate  * It lives here because of its close relationship with
3307c478bd9Sstevel@tonic-gate  * the ucbsigvechandler code above.
3317c478bd9Sstevel@tonic-gate  *
3327c478bd9Sstevel@tonic-gate  * It's used by 4.x applications to:
3337c478bd9Sstevel@tonic-gate  *	1. return from a signal handler (in __sigtramp)
3347c478bd9Sstevel@tonic-gate  *	2. [sig]longjmp
3357c478bd9Sstevel@tonic-gate  *	3. context switch, in the old 4.x liblwp
3367c478bd9Sstevel@tonic-gate  */
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate void
3397c478bd9Sstevel@tonic-gate __sigcleanup(struct sigcontext *scp)
3407c478bd9Sstevel@tonic-gate {
3417c478bd9Sstevel@tonic-gate 	ucontext_t uc, *ucp;
3427c478bd9Sstevel@tonic-gate 	int sig;
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	/*
3457c478bd9Sstevel@tonic-gate 	 * If there's a pointer to a ucontext_t hiding in the sigcontext,
3467c478bd9Sstevel@tonic-gate 	 * we *must* use that to return, since it contains important data
3477c478bd9Sstevel@tonic-gate 	 * such as the original "out" registers when the signal occurred.
3487c478bd9Sstevel@tonic-gate 	 */
3497c478bd9Sstevel@tonic-gate 	if (scp->sc_wbcnt == sizeof (*ucp)) {
350*be10f7d9Smuffin 		sig = (int)(uintptr_t)scp->sc_spbuf[0];
3517c478bd9Sstevel@tonic-gate 		ucp = (ucontext_t *)scp->sc_spbuf[1];
3527c478bd9Sstevel@tonic-gate 	} else {
3537c478bd9Sstevel@tonic-gate 		/*
3547c478bd9Sstevel@tonic-gate 		 * Otherwise, use a local ucontext_t and
3557c478bd9Sstevel@tonic-gate 		 * initialize it with getcontext.
3567c478bd9Sstevel@tonic-gate 		 */
3577c478bd9Sstevel@tonic-gate 		sig = 0;
3587c478bd9Sstevel@tonic-gate 		ucp = &uc;
3597c478bd9Sstevel@tonic-gate 		(void) getcontext(ucp);
3607c478bd9Sstevel@tonic-gate 	}
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	if (scp->sc_onstack) {
3637c478bd9Sstevel@tonic-gate 		ucp->uc_stack.ss_flags |= SS_ONSTACK;
3647c478bd9Sstevel@tonic-gate 	} else
3657c478bd9Sstevel@tonic-gate 		ucp->uc_stack.ss_flags &= ~SS_ONSTACK;
3667c478bd9Sstevel@tonic-gate 	mask2set(scp->sc_mask, &ucp->uc_sigmask);
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	ucp->uc_mcontext.gregs[REG_SP] = scp->sc_sp;
3697c478bd9Sstevel@tonic-gate 	ucp->uc_mcontext.gregs[REG_PC] = scp->sc_pc;
3707c478bd9Sstevel@tonic-gate 	ucp->uc_mcontext.gregs[REG_nPC] = scp->sc_npc;
3717c478bd9Sstevel@tonic-gate #if defined(__sparcv9)
3727c478bd9Sstevel@tonic-gate 	ucp->uc_mcontext.gregs[REG_CCR] = scp->sc_psr;
3737c478bd9Sstevel@tonic-gate #else
3747c478bd9Sstevel@tonic-gate 	ucp->uc_mcontext.gregs[REG_PSR] = scp->sc_psr;
3757c478bd9Sstevel@tonic-gate #endif
3767c478bd9Sstevel@tonic-gate 	ucp->uc_mcontext.gregs[REG_G1] = scp->sc_g1;
3777c478bd9Sstevel@tonic-gate 	ucp->uc_mcontext.gregs[REG_O0] = scp->sc_o0;
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	if (sig == SIGFPE) {
3807c478bd9Sstevel@tonic-gate 		if (ucp->uc_mcontext.fpregs.fpu_qcnt > 0) {
3817c478bd9Sstevel@tonic-gate 			ucp->uc_mcontext.fpregs.fpu_qcnt--;
3827c478bd9Sstevel@tonic-gate 			ucp->uc_mcontext.fpregs.fpu_q++;
3837c478bd9Sstevel@tonic-gate 		}
3847c478bd9Sstevel@tonic-gate 	}
3857c478bd9Sstevel@tonic-gate 	(void) setcontext(ucp);
3867c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate #endif
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate int
3917c478bd9Sstevel@tonic-gate _sigsetmask(int mask)
3927c478bd9Sstevel@tonic-gate {
3937c478bd9Sstevel@tonic-gate 	return (ucbsigsetmask(mask));
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate int
3977c478bd9Sstevel@tonic-gate ucbsigsetmask(int mask)
3987c478bd9Sstevel@tonic-gate {
3997c478bd9Sstevel@tonic-gate 	sigset_t oset;
4007c478bd9Sstevel@tonic-gate 	sigset_t nset;
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	(void) _sigprocmask(0, (sigset_t *)0, &nset);
4037c478bd9Sstevel@tonic-gate 	mask2set(mask, &nset);
4047c478bd9Sstevel@tonic-gate 	(void) _sigprocmask(SIG_SETMASK, &nset, &oset);
4057c478bd9Sstevel@tonic-gate 	return (set2mask(&oset));
4067c478bd9Sstevel@tonic-gate }
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate int
4097c478bd9Sstevel@tonic-gate _sigblock(int mask)
4107c478bd9Sstevel@tonic-gate {
4117c478bd9Sstevel@tonic-gate 	return (ucbsigblock(mask));
4127c478bd9Sstevel@tonic-gate }
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate int
4157c478bd9Sstevel@tonic-gate ucbsigblock(int mask)
4167c478bd9Sstevel@tonic-gate {
4177c478bd9Sstevel@tonic-gate 	sigset_t oset;
4187c478bd9Sstevel@tonic-gate 	sigset_t nset;
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	(void) _sigprocmask(0, (sigset_t *)0, &nset);
4217c478bd9Sstevel@tonic-gate 	mask2set(mask, &nset);
4227c478bd9Sstevel@tonic-gate 	(void) _sigprocmask(SIG_BLOCK, &nset, &oset);
4237c478bd9Sstevel@tonic-gate 	return (set2mask(&oset));
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate int
4277c478bd9Sstevel@tonic-gate usigpause(int mask)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate 	return (ucbsigpause(mask));
4307c478bd9Sstevel@tonic-gate }
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate int
4337c478bd9Sstevel@tonic-gate ucbsigpause(int mask)
4347c478bd9Sstevel@tonic-gate {
4357c478bd9Sstevel@tonic-gate 	sigset_t set, oset;
4367c478bd9Sstevel@tonic-gate 	int ret;
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 	(void) _sigprocmask(0, (sigset_t *)0, &set);
4397c478bd9Sstevel@tonic-gate 	oset = set;
4407c478bd9Sstevel@tonic-gate 	mask2set(mask, &set);
4417c478bd9Sstevel@tonic-gate 	ret = sigsuspend(&set);
4427c478bd9Sstevel@tonic-gate 	(void) _sigprocmask(SIG_SETMASK, &oset, (sigset_t *)0);
4437c478bd9Sstevel@tonic-gate 	return (ret);
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate int
4477c478bd9Sstevel@tonic-gate _sigvec(int sig, struct sigvec *nvec, struct sigvec *ovec)
4487c478bd9Sstevel@tonic-gate {
4497c478bd9Sstevel@tonic-gate 	return (ucbsigvec(sig, nvec, ovec));
4507c478bd9Sstevel@tonic-gate }
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate int
4537c478bd9Sstevel@tonic-gate ucbsigvec(int sig, struct sigvec *nvec, struct sigvec *ovec)
4547c478bd9Sstevel@tonic-gate {
4557c478bd9Sstevel@tonic-gate 	struct sigaction nact;
4567c478bd9Sstevel@tonic-gate 	struct sigaction oact;
4577c478bd9Sstevel@tonic-gate 	struct sigaction *nactp;
4587c478bd9Sstevel@tonic-gate 	void (*ohandler)(int, int, struct sigcontext *, char *);
4597c478bd9Sstevel@tonic-gate 	void (*nhandler)(int, int, struct sigcontext *, char *);
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	if (sig <= 0 || sig >= NSIG) {
4627c478bd9Sstevel@tonic-gate 		errno = EINVAL;
4637c478bd9Sstevel@tonic-gate 		return (-1);
4647c478bd9Sstevel@tonic-gate 	}
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	if ((long)ovec == -1L || (long)nvec == -1L) {
4677c478bd9Sstevel@tonic-gate 		errno = EFAULT;
4687c478bd9Sstevel@tonic-gate 		return (-1);
4697c478bd9Sstevel@tonic-gate 	}
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 	ohandler = _siguhandler[sig];
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	if (nvec) {
4747c478bd9Sstevel@tonic-gate 		(void) _sigaction(sig, (struct sigaction *)0, &nact);
4757c478bd9Sstevel@tonic-gate 		nhandler = nvec->sv_handler;
4767c478bd9Sstevel@tonic-gate 		/*
4777c478bd9Sstevel@tonic-gate 		 * To be compatible with the behavior of SunOS 4.x:
4787c478bd9Sstevel@tonic-gate 		 * If the new signal handler is SIG_IGN or SIG_DFL,
4797c478bd9Sstevel@tonic-gate 		 * do not change the signal's entry in the handler array.
4807c478bd9Sstevel@tonic-gate 		 * This allows a child of vfork(2) to set signal handlers
4817c478bd9Sstevel@tonic-gate 		 * to SIG_IGN or SIG_DFL without affecting the parent.
4827c478bd9Sstevel@tonic-gate 		 */
4837c478bd9Sstevel@tonic-gate 		if ((void (*)(int))nhandler != SIG_DFL &&
4847c478bd9Sstevel@tonic-gate 		    (void (*)(int))nhandler != SIG_IGN) {
4857c478bd9Sstevel@tonic-gate 			_siguhandler[sig] = nhandler;
4867c478bd9Sstevel@tonic-gate 			nact.sa_handler = (void (*)(int))ucbsigvechandler;
4877c478bd9Sstevel@tonic-gate 		} else {
4887c478bd9Sstevel@tonic-gate 			nact.sa_handler = (void (*)(int))nhandler;
4897c478bd9Sstevel@tonic-gate 		}
4907c478bd9Sstevel@tonic-gate 		mask2set(nvec->sv_mask, &nact.sa_mask);
4917c478bd9Sstevel@tonic-gate 		if (sig == SIGKILL || sig == SIGSTOP)
4927c478bd9Sstevel@tonic-gate 			nact.sa_handler = SIG_DFL;
4937c478bd9Sstevel@tonic-gate 		nact.sa_flags = SA_SIGINFO;
4947c478bd9Sstevel@tonic-gate 		if (!(nvec->sv_flags & SV_INTERRUPT))
4957c478bd9Sstevel@tonic-gate 			nact.sa_flags |= SA_RESTART;
4967c478bd9Sstevel@tonic-gate 		if (nvec->sv_flags & SV_RESETHAND)
4977c478bd9Sstevel@tonic-gate 			nact.sa_flags |= SA_RESETHAND;
4987c478bd9Sstevel@tonic-gate 		if (nvec->sv_flags & SV_ONSTACK)
4997c478bd9Sstevel@tonic-gate 			nact.sa_flags |= SA_ONSTACK;
5007c478bd9Sstevel@tonic-gate 		nactp = &nact;
5017c478bd9Sstevel@tonic-gate 	} else
5027c478bd9Sstevel@tonic-gate 		nactp = (struct sigaction *)0;
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	if (_sigaction(sig, nactp, &oact) < 0) {
5057c478bd9Sstevel@tonic-gate 		_siguhandler[sig] = ohandler;
5067c478bd9Sstevel@tonic-gate 		return (-1);
5077c478bd9Sstevel@tonic-gate 	}
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 	if (ovec) {
5107c478bd9Sstevel@tonic-gate 		if (oact.sa_handler == SIG_DFL || oact.sa_handler == SIG_IGN)
5117c478bd9Sstevel@tonic-gate 			ovec->sv_handler =
5127c478bd9Sstevel@tonic-gate 			    (void (*) (int, int, struct sigcontext *, char *))
5137c478bd9Sstevel@tonic-gate 			    oact.sa_handler;
5147c478bd9Sstevel@tonic-gate 		else
5157c478bd9Sstevel@tonic-gate 			ovec->sv_handler = ohandler;
5167c478bd9Sstevel@tonic-gate 		ovec->sv_mask = set2mask(&oact.sa_mask);
5177c478bd9Sstevel@tonic-gate 		ovec->sv_flags = 0;
5187c478bd9Sstevel@tonic-gate 		if (oact.sa_flags & SA_ONSTACK)
5197c478bd9Sstevel@tonic-gate 			ovec->sv_flags |= SV_ONSTACK;
5207c478bd9Sstevel@tonic-gate 		if (oact.sa_flags & SA_RESETHAND)
5217c478bd9Sstevel@tonic-gate 			ovec->sv_flags |= SV_RESETHAND;
5227c478bd9Sstevel@tonic-gate 		if (!(oact.sa_flags & SA_RESTART))
5237c478bd9Sstevel@tonic-gate 			ovec->sv_flags |= SV_INTERRUPT;
5247c478bd9Sstevel@tonic-gate 	}
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	return (0);
5277c478bd9Sstevel@tonic-gate }
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate int
5307c478bd9Sstevel@tonic-gate _sigstack(struct sigstack *nss, struct sigstack *oss)
5317c478bd9Sstevel@tonic-gate {
5327c478bd9Sstevel@tonic-gate 	struct sigaltstack nalt;
5337c478bd9Sstevel@tonic-gate 	struct sigaltstack oalt;
5347c478bd9Sstevel@tonic-gate 	struct sigaltstack *naltp;
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 	if (nss) {
5377c478bd9Sstevel@tonic-gate 		/*
5387c478bd9Sstevel@tonic-gate 		 * XXX: assumes stack growth is down (like sparc)
5397c478bd9Sstevel@tonic-gate 		 */
5407c478bd9Sstevel@tonic-gate 		nalt.ss_sp = nss->ss_sp - SIGSTKSZ;
5417c478bd9Sstevel@tonic-gate 		nalt.ss_size = SIGSTKSZ;
5427c478bd9Sstevel@tonic-gate 		nalt.ss_flags = 0;
5437c478bd9Sstevel@tonic-gate 		naltp = &nalt;
5447c478bd9Sstevel@tonic-gate 	} else
5457c478bd9Sstevel@tonic-gate 		naltp = (struct sigaltstack *)0;
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	if (sigaltstack(naltp, &oalt) < 0)
5487c478bd9Sstevel@tonic-gate 		return (-1);
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	if (oss) {
5517c478bd9Sstevel@tonic-gate 		/*
5527c478bd9Sstevel@tonic-gate 		 * XXX: assumes stack growth is down (like sparc)
5537c478bd9Sstevel@tonic-gate 		 */
5547c478bd9Sstevel@tonic-gate 		oss->ss_sp = oalt.ss_sp + oalt.ss_size;
5557c478bd9Sstevel@tonic-gate 		oss->ss_onstack = ((oalt.ss_flags & SS_ONSTACK) != 0);
5567c478bd9Sstevel@tonic-gate 	}
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	return (0);
5597c478bd9Sstevel@tonic-gate }
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate void (*
5627c478bd9Sstevel@tonic-gate ucbsignal(int s, void (*a)(int)))(int)
5637c478bd9Sstevel@tonic-gate {
5647c478bd9Sstevel@tonic-gate 	struct sigvec osv;
5657c478bd9Sstevel@tonic-gate 	struct sigvec nsv;
5667c478bd9Sstevel@tonic-gate 	static int mask[NSIG];
5677c478bd9Sstevel@tonic-gate 	static int flags[NSIG];
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate 	nsv.sv_handler = (void (*) (int, int, struct sigcontext *, char *)) a;
5707c478bd9Sstevel@tonic-gate 	nsv.sv_mask = mask[s];
5717c478bd9Sstevel@tonic-gate 	nsv.sv_flags = flags[s];
5727c478bd9Sstevel@tonic-gate 	if (ucbsigvec(s, &nsv, &osv) < 0)
5737c478bd9Sstevel@tonic-gate 		return (SIG_ERR);
5747c478bd9Sstevel@tonic-gate 	if (nsv.sv_mask != osv.sv_mask || nsv.sv_flags != osv.sv_flags) {
5757c478bd9Sstevel@tonic-gate 		mask[s] = nsv.sv_mask = osv.sv_mask;
5767c478bd9Sstevel@tonic-gate 		flags[s] = nsv.sv_flags =
5777c478bd9Sstevel@tonic-gate 		    osv.sv_flags & ~(SV_RESETHAND|SV_INTERRUPT);
5787c478bd9Sstevel@tonic-gate 		if (ucbsigvec(s, &nsv, (struct sigvec *)0) < 0)
5797c478bd9Sstevel@tonic-gate 			return (SIG_ERR);
5807c478bd9Sstevel@tonic-gate 	}
5817c478bd9Sstevel@tonic-gate 	return ((void (*) (int)) osv.sv_handler);
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate void (*
5857c478bd9Sstevel@tonic-gate usignal(int s, void (*a) (int)))(int)
5867c478bd9Sstevel@tonic-gate {
5877c478bd9Sstevel@tonic-gate 	return (ucbsignal(s, a));
5887c478bd9Sstevel@tonic-gate }
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate /*
5917c478bd9Sstevel@tonic-gate  * Set signal state to prevent restart of system calls
5927c478bd9Sstevel@tonic-gate  * after an instance of the indicated signal.
5937c478bd9Sstevel@tonic-gate  */
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate int
5967c478bd9Sstevel@tonic-gate _siginterrupt(int sig, int flag)
5977c478bd9Sstevel@tonic-gate {
5987c478bd9Sstevel@tonic-gate 	return (ucbsiginterrupt(sig, flag));
5997c478bd9Sstevel@tonic-gate }
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate int
6027c478bd9Sstevel@tonic-gate ucbsiginterrupt(int sig, int flag)
6037c478bd9Sstevel@tonic-gate {
6047c478bd9Sstevel@tonic-gate 	struct sigvec sv;
6057c478bd9Sstevel@tonic-gate 	int ret;
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 	if ((ret = ucbsigvec(sig, 0, &sv)) < 0)
6087c478bd9Sstevel@tonic-gate 		return (ret);
6097c478bd9Sstevel@tonic-gate 	if (flag)
6107c478bd9Sstevel@tonic-gate 		sv.sv_flags |= SV_INTERRUPT;
6117c478bd9Sstevel@tonic-gate 	else
6127c478bd9Sstevel@tonic-gate 		sv.sv_flags &= ~SV_INTERRUPT;
6137c478bd9Sstevel@tonic-gate 	return (ucbsigvec(sig, &sv, 0));
6147c478bd9Sstevel@tonic-gate }
615