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