11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * linux/arch/alpha/kernel/signal.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 1995 Linus Torvalds 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * 1997-11-02 Modified for POSIX.1b signals by Richard Henderson 71da177e4SLinus Torvalds */ 81da177e4SLinus Torvalds 91da177e4SLinus Torvalds #include <linux/sched.h> 101da177e4SLinus Torvalds #include <linux/kernel.h> 111da177e4SLinus Torvalds #include <linux/signal.h> 121da177e4SLinus Torvalds #include <linux/errno.h> 131da177e4SLinus Torvalds #include <linux/wait.h> 141da177e4SLinus Torvalds #include <linux/ptrace.h> 151da177e4SLinus Torvalds #include <linux/unistd.h> 161da177e4SLinus Torvalds #include <linux/mm.h> 171da177e4SLinus Torvalds #include <linux/smp.h> 181da177e4SLinus Torvalds #include <linux/stddef.h> 191da177e4SLinus Torvalds #include <linux/tty.h> 201da177e4SLinus Torvalds #include <linux/binfmts.h> 211da177e4SLinus Torvalds #include <linux/bitops.h> 22e5d9a90cSIvan Kokshaysky #include <linux/syscalls.h> 23733e5e4bSDavid Howells #include <linux/tracehook.h> 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds #include <asm/uaccess.h> 261da177e4SLinus Torvalds #include <asm/sigcontext.h> 271da177e4SLinus Torvalds #include <asm/ucontext.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #include "proto.h" 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds #define DEBUG_SIG 0 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds asmlinkage void ret_from_sys_call(void); 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds /* 391da177e4SLinus Torvalds * The OSF/1 sigprocmask calling sequence is different from the 401da177e4SLinus Torvalds * C sigprocmask() sequence.. 411da177e4SLinus Torvalds */ 42c52c2ddcSAl Viro SYSCALL_DEFINE2(osf_sigprocmask, int, how, unsigned long, newmask) 431da177e4SLinus Torvalds { 44c52c2ddcSAl Viro sigset_t oldmask; 45c52c2ddcSAl Viro sigset_t mask; 46c52c2ddcSAl Viro unsigned long res; 471da177e4SLinus Torvalds 4887400e54SLinus Torvalds siginitset(&mask, newmask & _BLOCKABLE); 490f44fbd2SLinus Torvalds res = sigprocmask(how, &mask, &oldmask); 50c52c2ddcSAl Viro if (!res) { 51c52c2ddcSAl Viro force_successful_syscall_return(); 520f44fbd2SLinus Torvalds res = oldmask.sig[0]; 531da177e4SLinus Torvalds } 54c52c2ddcSAl Viro return res; 551da177e4SLinus Torvalds } 561da177e4SLinus Torvalds 57e5d9a90cSIvan Kokshaysky SYSCALL_DEFINE3(osf_sigaction, int, sig, 58e5d9a90cSIvan Kokshaysky const struct osf_sigaction __user *, act, 59e5d9a90cSIvan Kokshaysky struct osf_sigaction __user *, oact) 601da177e4SLinus Torvalds { 611da177e4SLinus Torvalds struct k_sigaction new_ka, old_ka; 621da177e4SLinus Torvalds int ret; 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds if (act) { 651da177e4SLinus Torvalds old_sigset_t mask; 661da177e4SLinus Torvalds if (!access_ok(VERIFY_READ, act, sizeof(*act)) || 671da177e4SLinus Torvalds __get_user(new_ka.sa.sa_handler, &act->sa_handler) || 6818e6bfa9SAl Viro __get_user(new_ka.sa.sa_flags, &act->sa_flags) || 6918e6bfa9SAl Viro __get_user(mask, &act->sa_mask)) 701da177e4SLinus Torvalds return -EFAULT; 711da177e4SLinus Torvalds siginitset(&new_ka.sa.sa_mask, mask); 721da177e4SLinus Torvalds new_ka.ka_restorer = NULL; 731da177e4SLinus Torvalds } 741da177e4SLinus Torvalds 751da177e4SLinus Torvalds ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds if (!ret && oact) { 781da177e4SLinus Torvalds if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || 791da177e4SLinus Torvalds __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || 8018e6bfa9SAl Viro __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || 8118e6bfa9SAl Viro __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) 821da177e4SLinus Torvalds return -EFAULT; 831da177e4SLinus Torvalds } 841da177e4SLinus Torvalds 851da177e4SLinus Torvalds return ret; 861da177e4SLinus Torvalds } 871da177e4SLinus Torvalds 88e5d9a90cSIvan Kokshaysky SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act, 89e5d9a90cSIvan Kokshaysky struct sigaction __user *, oact, 90e5d9a90cSIvan Kokshaysky size_t, sigsetsize, void __user *, restorer) 911da177e4SLinus Torvalds { 921da177e4SLinus Torvalds struct k_sigaction new_ka, old_ka; 931da177e4SLinus Torvalds int ret; 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds /* XXX: Don't preclude handling different sized sigset_t's. */ 961da177e4SLinus Torvalds if (sigsetsize != sizeof(sigset_t)) 971da177e4SLinus Torvalds return -EINVAL; 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds if (act) { 1001da177e4SLinus Torvalds new_ka.ka_restorer = restorer; 1011da177e4SLinus Torvalds if (copy_from_user(&new_ka.sa, act, sizeof(*act))) 1021da177e4SLinus Torvalds return -EFAULT; 1031da177e4SLinus Torvalds } 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds if (!ret && oact) { 1081da177e4SLinus Torvalds if (copy_to_user(oact, &old_ka.sa, sizeof(*oact))) 1091da177e4SLinus Torvalds return -EFAULT; 1101da177e4SLinus Torvalds } 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds return ret; 1131da177e4SLinus Torvalds } 1141da177e4SLinus Torvalds 1151da177e4SLinus Torvalds /* 1161da177e4SLinus Torvalds * Atomically swap in the new signal mask, and wait for a signal. 1171da177e4SLinus Torvalds */ 118392fb6e3SAl Viro SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask) 1191da177e4SLinus Torvalds { 1202561b069SMatt Fleming sigset_t blocked; 1212561b069SMatt Fleming siginitset(&blocked, mask); 12268f3f16dSAl Viro return sigsuspend(&blocked); 1231da177e4SLinus Torvalds } 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds /* 1261da177e4SLinus Torvalds * Do a signal return; undo the signal stack. 1271da177e4SLinus Torvalds */ 1281da177e4SLinus Torvalds 1291da177e4SLinus Torvalds #if _NSIG_WORDS > 1 1301da177e4SLinus Torvalds # error "Non SA_SIGINFO frame needs rearranging" 1311da177e4SLinus Torvalds #endif 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds struct sigframe 1341da177e4SLinus Torvalds { 1351da177e4SLinus Torvalds struct sigcontext sc; 1361da177e4SLinus Torvalds unsigned int retcode[3]; 1371da177e4SLinus Torvalds }; 1381da177e4SLinus Torvalds 1391da177e4SLinus Torvalds struct rt_sigframe 1401da177e4SLinus Torvalds { 1411da177e4SLinus Torvalds struct siginfo info; 1421da177e4SLinus Torvalds struct ucontext uc; 1431da177e4SLinus Torvalds unsigned int retcode[3]; 1441da177e4SLinus Torvalds }; 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds /* If this changes, userland unwinders that Know Things about our signal 1471da177e4SLinus Torvalds frame will break. Do not undertake lightly. It also implies an ABI 1481da177e4SLinus Torvalds change wrt the size of siginfo_t, which may cause some pain. */ 1491da177e4SLinus Torvalds extern char compile_time_assert 1501da177e4SLinus Torvalds [offsetof(struct rt_sigframe, uc.uc_mcontext) == 176 ? 1 : -1]; 1511da177e4SLinus Torvalds 1521da177e4SLinus Torvalds #define INSN_MOV_R30_R16 0x47fe0410 1531da177e4SLinus Torvalds #define INSN_LDI_R0 0x201f0000 1541da177e4SLinus Torvalds #define INSN_CALLSYS 0x00000083 1551da177e4SLinus Torvalds 1561da177e4SLinus Torvalds static long 157b960f303SAl Viro restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) 1581da177e4SLinus Torvalds { 1591da177e4SLinus Torvalds unsigned long usp; 160b960f303SAl Viro struct switch_stack *sw = (struct switch_stack *)regs - 1; 1611da177e4SLinus Torvalds long i, err = __get_user(regs->pc, &sc->sc_pc); 1621da177e4SLinus Torvalds 1632deba1bdSAl Viro current_thread_info()->restart_block.fn = do_no_restart_syscall; 1642deba1bdSAl Viro 1651da177e4SLinus Torvalds sw->r26 = (unsigned long) ret_from_sys_call; 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds err |= __get_user(regs->r0, sc->sc_regs+0); 1681da177e4SLinus Torvalds err |= __get_user(regs->r1, sc->sc_regs+1); 1691da177e4SLinus Torvalds err |= __get_user(regs->r2, sc->sc_regs+2); 1701da177e4SLinus Torvalds err |= __get_user(regs->r3, sc->sc_regs+3); 1711da177e4SLinus Torvalds err |= __get_user(regs->r4, sc->sc_regs+4); 1721da177e4SLinus Torvalds err |= __get_user(regs->r5, sc->sc_regs+5); 1731da177e4SLinus Torvalds err |= __get_user(regs->r6, sc->sc_regs+6); 1741da177e4SLinus Torvalds err |= __get_user(regs->r7, sc->sc_regs+7); 1751da177e4SLinus Torvalds err |= __get_user(regs->r8, sc->sc_regs+8); 1761da177e4SLinus Torvalds err |= __get_user(sw->r9, sc->sc_regs+9); 1771da177e4SLinus Torvalds err |= __get_user(sw->r10, sc->sc_regs+10); 1781da177e4SLinus Torvalds err |= __get_user(sw->r11, sc->sc_regs+11); 1791da177e4SLinus Torvalds err |= __get_user(sw->r12, sc->sc_regs+12); 1801da177e4SLinus Torvalds err |= __get_user(sw->r13, sc->sc_regs+13); 1811da177e4SLinus Torvalds err |= __get_user(sw->r14, sc->sc_regs+14); 1821da177e4SLinus Torvalds err |= __get_user(sw->r15, sc->sc_regs+15); 1831da177e4SLinus Torvalds err |= __get_user(regs->r16, sc->sc_regs+16); 1841da177e4SLinus Torvalds err |= __get_user(regs->r17, sc->sc_regs+17); 1851da177e4SLinus Torvalds err |= __get_user(regs->r18, sc->sc_regs+18); 1861da177e4SLinus Torvalds err |= __get_user(regs->r19, sc->sc_regs+19); 1871da177e4SLinus Torvalds err |= __get_user(regs->r20, sc->sc_regs+20); 1881da177e4SLinus Torvalds err |= __get_user(regs->r21, sc->sc_regs+21); 1891da177e4SLinus Torvalds err |= __get_user(regs->r22, sc->sc_regs+22); 1901da177e4SLinus Torvalds err |= __get_user(regs->r23, sc->sc_regs+23); 1911da177e4SLinus Torvalds err |= __get_user(regs->r24, sc->sc_regs+24); 1921da177e4SLinus Torvalds err |= __get_user(regs->r25, sc->sc_regs+25); 1931da177e4SLinus Torvalds err |= __get_user(regs->r26, sc->sc_regs+26); 1941da177e4SLinus Torvalds err |= __get_user(regs->r27, sc->sc_regs+27); 1951da177e4SLinus Torvalds err |= __get_user(regs->r28, sc->sc_regs+28); 1961da177e4SLinus Torvalds err |= __get_user(regs->gp, sc->sc_regs+29); 1971da177e4SLinus Torvalds err |= __get_user(usp, sc->sc_regs+30); 1981da177e4SLinus Torvalds wrusp(usp); 1991da177e4SLinus Torvalds 2001da177e4SLinus Torvalds for (i = 0; i < 31; i++) 2011da177e4SLinus Torvalds err |= __get_user(sw->fp[i], sc->sc_fpregs+i); 2021da177e4SLinus Torvalds err |= __get_user(sw->fp[31], &sc->sc_fpcr); 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds return err; 2051da177e4SLinus Torvalds } 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvalds /* Note that this syscall is also used by setcontext(3) to install 2081da177e4SLinus Torvalds a given sigcontext. This because it's impossible to set *all* 2091da177e4SLinus Torvalds registers and transfer control from userland. */ 2101da177e4SLinus Torvalds 2111da177e4SLinus Torvalds asmlinkage void 212b960f303SAl Viro do_sigreturn(struct sigcontext __user *sc) 2131da177e4SLinus Torvalds { 214b960f303SAl Viro struct pt_regs *regs = current_pt_regs(); 2151da177e4SLinus Torvalds sigset_t set; 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds /* Verify that it's a good sigcontext before using it */ 2181da177e4SLinus Torvalds if (!access_ok(VERIFY_READ, sc, sizeof(*sc))) 2191da177e4SLinus Torvalds goto give_sigsegv; 2201da177e4SLinus Torvalds if (__get_user(set.sig[0], &sc->sc_mask)) 2211da177e4SLinus Torvalds goto give_sigsegv; 2221da177e4SLinus Torvalds 2232561b069SMatt Fleming set_current_blocked(&set); 2241da177e4SLinus Torvalds 225b960f303SAl Viro if (restore_sigcontext(sc, regs)) 2261da177e4SLinus Torvalds goto give_sigsegv; 2271da177e4SLinus Torvalds 2281da177e4SLinus Torvalds /* Send SIGTRAP if we're single-stepping: */ 2291da177e4SLinus Torvalds if (ptrace_cancel_bpt (current)) { 2301da177e4SLinus Torvalds siginfo_t info; 2311da177e4SLinus Torvalds 2321da177e4SLinus Torvalds info.si_signo = SIGTRAP; 2331da177e4SLinus Torvalds info.si_errno = 0; 2341da177e4SLinus Torvalds info.si_code = TRAP_BRKPT; 2351da177e4SLinus Torvalds info.si_addr = (void __user *) regs->pc; 2361da177e4SLinus Torvalds info.si_trapno = 0; 2371da177e4SLinus Torvalds send_sig_info(SIGTRAP, &info, current); 2381da177e4SLinus Torvalds } 2391da177e4SLinus Torvalds return; 2401da177e4SLinus Torvalds 2411da177e4SLinus Torvalds give_sigsegv: 2421da177e4SLinus Torvalds force_sig(SIGSEGV, current); 2431da177e4SLinus Torvalds } 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds asmlinkage void 246b960f303SAl Viro do_rt_sigreturn(struct rt_sigframe __user *frame) 2471da177e4SLinus Torvalds { 248b960f303SAl Viro struct pt_regs *regs = current_pt_regs(); 2491da177e4SLinus Torvalds sigset_t set; 2501da177e4SLinus Torvalds 2511da177e4SLinus Torvalds /* Verify that it's a good ucontext_t before using it */ 2521da177e4SLinus Torvalds if (!access_ok(VERIFY_READ, &frame->uc, sizeof(frame->uc))) 2531da177e4SLinus Torvalds goto give_sigsegv; 2541da177e4SLinus Torvalds if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 2551da177e4SLinus Torvalds goto give_sigsegv; 2561da177e4SLinus Torvalds 2572561b069SMatt Fleming set_current_blocked(&set); 2581da177e4SLinus Torvalds 259b960f303SAl Viro if (restore_sigcontext(&frame->uc.uc_mcontext, regs)) 2601da177e4SLinus Torvalds goto give_sigsegv; 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds /* Send SIGTRAP if we're single-stepping: */ 2631da177e4SLinus Torvalds if (ptrace_cancel_bpt (current)) { 2641da177e4SLinus Torvalds siginfo_t info; 2651da177e4SLinus Torvalds 2661da177e4SLinus Torvalds info.si_signo = SIGTRAP; 2671da177e4SLinus Torvalds info.si_errno = 0; 2681da177e4SLinus Torvalds info.si_code = TRAP_BRKPT; 2691da177e4SLinus Torvalds info.si_addr = (void __user *) regs->pc; 2701da177e4SLinus Torvalds info.si_trapno = 0; 2711da177e4SLinus Torvalds send_sig_info(SIGTRAP, &info, current); 2721da177e4SLinus Torvalds } 2731da177e4SLinus Torvalds return; 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds give_sigsegv: 2761da177e4SLinus Torvalds force_sig(SIGSEGV, current); 2771da177e4SLinus Torvalds } 2781da177e4SLinus Torvalds 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds /* 2811da177e4SLinus Torvalds * Set up a signal frame. 2821da177e4SLinus Torvalds */ 2831da177e4SLinus Torvalds 2841da177e4SLinus Torvalds static inline void __user * 2851da177e4SLinus Torvalds get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) 2861da177e4SLinus Torvalds { 287d09042daSLaurent MEYER if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) 2881da177e4SLinus Torvalds sp = current->sas_ss_sp + current->sas_ss_size; 2891da177e4SLinus Torvalds 2901da177e4SLinus Torvalds return (void __user *)((sp - frame_size) & -32ul); 2911da177e4SLinus Torvalds } 2921da177e4SLinus Torvalds 2931da177e4SLinus Torvalds static long 2941da177e4SLinus Torvalds setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, 295d9d0738aSAl Viro unsigned long mask, unsigned long sp) 2961da177e4SLinus Torvalds { 297d9d0738aSAl Viro struct switch_stack *sw = (struct switch_stack *)regs - 1; 2981da177e4SLinus Torvalds long i, err = 0; 2991da177e4SLinus Torvalds 3001da177e4SLinus Torvalds err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack); 3011da177e4SLinus Torvalds err |= __put_user(mask, &sc->sc_mask); 3021da177e4SLinus Torvalds err |= __put_user(regs->pc, &sc->sc_pc); 3031da177e4SLinus Torvalds err |= __put_user(8, &sc->sc_ps); 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds err |= __put_user(regs->r0 , sc->sc_regs+0); 3061da177e4SLinus Torvalds err |= __put_user(regs->r1 , sc->sc_regs+1); 3071da177e4SLinus Torvalds err |= __put_user(regs->r2 , sc->sc_regs+2); 3081da177e4SLinus Torvalds err |= __put_user(regs->r3 , sc->sc_regs+3); 3091da177e4SLinus Torvalds err |= __put_user(regs->r4 , sc->sc_regs+4); 3101da177e4SLinus Torvalds err |= __put_user(regs->r5 , sc->sc_regs+5); 3111da177e4SLinus Torvalds err |= __put_user(regs->r6 , sc->sc_regs+6); 3121da177e4SLinus Torvalds err |= __put_user(regs->r7 , sc->sc_regs+7); 3131da177e4SLinus Torvalds err |= __put_user(regs->r8 , sc->sc_regs+8); 3141da177e4SLinus Torvalds err |= __put_user(sw->r9 , sc->sc_regs+9); 3151da177e4SLinus Torvalds err |= __put_user(sw->r10 , sc->sc_regs+10); 3161da177e4SLinus Torvalds err |= __put_user(sw->r11 , sc->sc_regs+11); 3171da177e4SLinus Torvalds err |= __put_user(sw->r12 , sc->sc_regs+12); 3181da177e4SLinus Torvalds err |= __put_user(sw->r13 , sc->sc_regs+13); 3191da177e4SLinus Torvalds err |= __put_user(sw->r14 , sc->sc_regs+14); 3201da177e4SLinus Torvalds err |= __put_user(sw->r15 , sc->sc_regs+15); 3211da177e4SLinus Torvalds err |= __put_user(regs->r16, sc->sc_regs+16); 3221da177e4SLinus Torvalds err |= __put_user(regs->r17, sc->sc_regs+17); 3231da177e4SLinus Torvalds err |= __put_user(regs->r18, sc->sc_regs+18); 3241da177e4SLinus Torvalds err |= __put_user(regs->r19, sc->sc_regs+19); 3251da177e4SLinus Torvalds err |= __put_user(regs->r20, sc->sc_regs+20); 3261da177e4SLinus Torvalds err |= __put_user(regs->r21, sc->sc_regs+21); 3271da177e4SLinus Torvalds err |= __put_user(regs->r22, sc->sc_regs+22); 3281da177e4SLinus Torvalds err |= __put_user(regs->r23, sc->sc_regs+23); 3291da177e4SLinus Torvalds err |= __put_user(regs->r24, sc->sc_regs+24); 3301da177e4SLinus Torvalds err |= __put_user(regs->r25, sc->sc_regs+25); 3311da177e4SLinus Torvalds err |= __put_user(regs->r26, sc->sc_regs+26); 3321da177e4SLinus Torvalds err |= __put_user(regs->r27, sc->sc_regs+27); 3331da177e4SLinus Torvalds err |= __put_user(regs->r28, sc->sc_regs+28); 3341da177e4SLinus Torvalds err |= __put_user(regs->gp , sc->sc_regs+29); 3351da177e4SLinus Torvalds err |= __put_user(sp, sc->sc_regs+30); 3361da177e4SLinus Torvalds err |= __put_user(0, sc->sc_regs+31); 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvalds for (i = 0; i < 31; i++) 3391da177e4SLinus Torvalds err |= __put_user(sw->fp[i], sc->sc_fpregs+i); 3401da177e4SLinus Torvalds err |= __put_user(0, sc->sc_fpregs+31); 3411da177e4SLinus Torvalds err |= __put_user(sw->fp[31], &sc->sc_fpcr); 3421da177e4SLinus Torvalds 3431da177e4SLinus Torvalds err |= __put_user(regs->trap_a0, &sc->sc_traparg_a0); 3441da177e4SLinus Torvalds err |= __put_user(regs->trap_a1, &sc->sc_traparg_a1); 3451da177e4SLinus Torvalds err |= __put_user(regs->trap_a2, &sc->sc_traparg_a2); 3461da177e4SLinus Torvalds 3471da177e4SLinus Torvalds return err; 3481da177e4SLinus Torvalds } 3491da177e4SLinus Torvalds 350b927b3e2SRichard Henderson static int 3511da177e4SLinus Torvalds setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, 352d9d0738aSAl Viro struct pt_regs *regs) 3531da177e4SLinus Torvalds { 3541da177e4SLinus Torvalds unsigned long oldsp, r26, err = 0; 3551da177e4SLinus Torvalds struct sigframe __user *frame; 3561da177e4SLinus Torvalds 3571da177e4SLinus Torvalds oldsp = rdusp(); 3581da177e4SLinus Torvalds frame = get_sigframe(ka, oldsp, sizeof(*frame)); 3591da177e4SLinus Torvalds if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 360cbdfb9ffSAl Viro return -EFAULT; 3611da177e4SLinus Torvalds 362d9d0738aSAl Viro err |= setup_sigcontext(&frame->sc, regs, set->sig[0], oldsp); 3631da177e4SLinus Torvalds if (err) 364cbdfb9ffSAl Viro return -EFAULT; 3651da177e4SLinus Torvalds 3661da177e4SLinus Torvalds /* Set up to return from userspace. If provided, use a stub 3671da177e4SLinus Torvalds already in userspace. */ 3681da177e4SLinus Torvalds if (ka->ka_restorer) { 3691da177e4SLinus Torvalds r26 = (unsigned long) ka->ka_restorer; 3701da177e4SLinus Torvalds } else { 3711da177e4SLinus Torvalds err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0); 3721da177e4SLinus Torvalds err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1); 3731da177e4SLinus Torvalds err |= __put_user(INSN_CALLSYS, frame->retcode+2); 3741da177e4SLinus Torvalds imb(); 3751da177e4SLinus Torvalds r26 = (unsigned long) frame->retcode; 3761da177e4SLinus Torvalds } 3771da177e4SLinus Torvalds 3781da177e4SLinus Torvalds /* Check that everything was written properly. */ 3791da177e4SLinus Torvalds if (err) 380cbdfb9ffSAl Viro return err; 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds /* "Return" to the handler */ 3831da177e4SLinus Torvalds regs->r26 = r26; 3841da177e4SLinus Torvalds regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler; 3851da177e4SLinus Torvalds regs->r16 = sig; /* a0: signal number */ 3861da177e4SLinus Torvalds regs->r17 = 0; /* a1: exception code */ 3871da177e4SLinus Torvalds regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */ 3881da177e4SLinus Torvalds wrusp((unsigned long) frame); 3891da177e4SLinus Torvalds 3901da177e4SLinus Torvalds #if DEBUG_SIG 3911da177e4SLinus Torvalds printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", 3921da177e4SLinus Torvalds current->comm, current->pid, frame, regs->pc, regs->r26); 3931da177e4SLinus Torvalds #endif 394b927b3e2SRichard Henderson return 0; 3951da177e4SLinus Torvalds } 3961da177e4SLinus Torvalds 397b927b3e2SRichard Henderson static int 3981da177e4SLinus Torvalds setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 399d9d0738aSAl Viro sigset_t *set, struct pt_regs *regs) 4001da177e4SLinus Torvalds { 4011da177e4SLinus Torvalds unsigned long oldsp, r26, err = 0; 4021da177e4SLinus Torvalds struct rt_sigframe __user *frame; 4031da177e4SLinus Torvalds 4041da177e4SLinus Torvalds oldsp = rdusp(); 4051da177e4SLinus Torvalds frame = get_sigframe(ka, oldsp, sizeof(*frame)); 4061da177e4SLinus Torvalds if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 407cbdfb9ffSAl Viro return -EFAULT; 4081da177e4SLinus Torvalds 4091da177e4SLinus Torvalds err |= copy_siginfo_to_user(&frame->info, info); 4101da177e4SLinus Torvalds 4111da177e4SLinus Torvalds /* Create the ucontext. */ 4121da177e4SLinus Torvalds err |= __put_user(0, &frame->uc.uc_flags); 4131da177e4SLinus Torvalds err |= __put_user(0, &frame->uc.uc_link); 4141da177e4SLinus Torvalds err |= __put_user(set->sig[0], &frame->uc.uc_osf_sigmask); 41550ececcfSAl Viro err |= __save_altstack(&frame->uc.uc_stack, oldsp); 416d9d0738aSAl Viro err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, 4171da177e4SLinus Torvalds set->sig[0], oldsp); 4181da177e4SLinus Torvalds err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 4191da177e4SLinus Torvalds if (err) 420cbdfb9ffSAl Viro return -EFAULT; 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvalds /* Set up to return from userspace. If provided, use a stub 4231da177e4SLinus Torvalds already in userspace. */ 4241da177e4SLinus Torvalds if (ka->ka_restorer) { 4251da177e4SLinus Torvalds r26 = (unsigned long) ka->ka_restorer; 4261da177e4SLinus Torvalds } else { 4271da177e4SLinus Torvalds err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0); 4281da177e4SLinus Torvalds err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn, 4291da177e4SLinus Torvalds frame->retcode+1); 4301da177e4SLinus Torvalds err |= __put_user(INSN_CALLSYS, frame->retcode+2); 4311da177e4SLinus Torvalds imb(); 4321da177e4SLinus Torvalds r26 = (unsigned long) frame->retcode; 4331da177e4SLinus Torvalds } 4341da177e4SLinus Torvalds 4351da177e4SLinus Torvalds if (err) 436cbdfb9ffSAl Viro return -EFAULT; 4371da177e4SLinus Torvalds 4381da177e4SLinus Torvalds /* "Return" to the handler */ 4391da177e4SLinus Torvalds regs->r26 = r26; 4401da177e4SLinus Torvalds regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler; 4411da177e4SLinus Torvalds regs->r16 = sig; /* a0: signal number */ 4421da177e4SLinus Torvalds regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */ 4431da177e4SLinus Torvalds regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */ 4441da177e4SLinus Torvalds wrusp((unsigned long) frame); 4451da177e4SLinus Torvalds 4461da177e4SLinus Torvalds #if DEBUG_SIG 4471da177e4SLinus Torvalds printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", 4481da177e4SLinus Torvalds current->comm, current->pid, frame, regs->pc, regs->r26); 4491da177e4SLinus Torvalds #endif 4501da177e4SLinus Torvalds 451b927b3e2SRichard Henderson return 0; 4521da177e4SLinus Torvalds } 4531da177e4SLinus Torvalds 4541da177e4SLinus Torvalds 4551da177e4SLinus Torvalds /* 4561da177e4SLinus Torvalds * OK, we're invoking a handler. 4571da177e4SLinus Torvalds */ 458cbdfb9ffSAl Viro static inline void 4591da177e4SLinus Torvalds handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, 460d9d0738aSAl Viro struct pt_regs * regs) 4611da177e4SLinus Torvalds { 462b7f9a11aSAl Viro sigset_t *oldset = sigmask_to_save(); 463b927b3e2SRichard Henderson int ret; 464b927b3e2SRichard Henderson 4651da177e4SLinus Torvalds if (ka->sa.sa_flags & SA_SIGINFO) 466d9d0738aSAl Viro ret = setup_rt_frame(sig, ka, info, oldset, regs); 4671da177e4SLinus Torvalds else 468d9d0738aSAl Viro ret = setup_frame(sig, ka, oldset, regs); 4691da177e4SLinus Torvalds 470cbdfb9ffSAl Viro if (ret) { 471cbdfb9ffSAl Viro force_sigsegv(sig, current); 472cbdfb9ffSAl Viro return; 473cbdfb9ffSAl Viro } 474efee984cSAl Viro signal_delivered(sig, info, ka, regs, 0); 475b927b3e2SRichard Henderson } 476b927b3e2SRichard Henderson 4771da177e4SLinus Torvalds static inline void 4781da177e4SLinus Torvalds syscall_restart(unsigned long r0, unsigned long r19, 4791da177e4SLinus Torvalds struct pt_regs *regs, struct k_sigaction *ka) 4801da177e4SLinus Torvalds { 4811da177e4SLinus Torvalds switch (regs->r0) { 4821da177e4SLinus Torvalds case ERESTARTSYS: 4831da177e4SLinus Torvalds if (!(ka->sa.sa_flags & SA_RESTART)) { 4841da177e4SLinus Torvalds case ERESTARTNOHAND: 4851da177e4SLinus Torvalds regs->r0 = EINTR; 4861da177e4SLinus Torvalds break; 4871da177e4SLinus Torvalds } 4881da177e4SLinus Torvalds /* fallthrough */ 4891da177e4SLinus Torvalds case ERESTARTNOINTR: 4901da177e4SLinus Torvalds regs->r0 = r0; /* reset v0 and a3 and replay syscall */ 4911da177e4SLinus Torvalds regs->r19 = r19; 4921da177e4SLinus Torvalds regs->pc -= 4; 4931da177e4SLinus Torvalds break; 4941da177e4SLinus Torvalds case ERESTART_RESTARTBLOCK: 4951da177e4SLinus Torvalds regs->r0 = EINTR; 4961da177e4SLinus Torvalds break; 4971da177e4SLinus Torvalds } 4981da177e4SLinus Torvalds } 4991da177e4SLinus Torvalds 5001da177e4SLinus Torvalds 5011da177e4SLinus Torvalds /* 5021da177e4SLinus Torvalds * Note that 'init' is a special process: it doesn't get signals it doesn't 5031da177e4SLinus Torvalds * want to handle. Thus you cannot kill init even with a SIGKILL even by 5041da177e4SLinus Torvalds * mistake. 5051da177e4SLinus Torvalds * 5061da177e4SLinus Torvalds * Note that we go through the signals twice: once to check the signals that 5071da177e4SLinus Torvalds * the kernel can handle, and then we build all the user-level signal handling 5081da177e4SLinus Torvalds * stack-frames in one go after that. 5091da177e4SLinus Torvalds * 5101da177e4SLinus Torvalds * "r0" and "r19" are the registers we need to restore for system call 5111da177e4SLinus Torvalds * restart. "r0" is also used as an indicator whether we can restart at 5121da177e4SLinus Torvalds * all (if we get here from anything but a syscall return, it will be 0) 5131da177e4SLinus Torvalds */ 514b927b3e2SRichard Henderson static void 515d9d0738aSAl Viro do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19) 5161da177e4SLinus Torvalds { 5171da177e4SLinus Torvalds siginfo_t info; 5181da177e4SLinus Torvalds int signr; 5191da177e4SLinus Torvalds unsigned long single_stepping = ptrace_cancel_bpt(current); 5201da177e4SLinus Torvalds struct k_sigaction ka; 5211da177e4SLinus Torvalds 5221da177e4SLinus Torvalds /* This lets the debugger run, ... */ 5231da177e4SLinus Torvalds signr = get_signal_to_deliver(&info, &ka, regs, NULL); 524b927b3e2SRichard Henderson 5251da177e4SLinus Torvalds /* ... so re-check the single stepping. */ 5261da177e4SLinus Torvalds single_stepping |= ptrace_cancel_bpt(current); 5271da177e4SLinus Torvalds 5281da177e4SLinus Torvalds if (signr > 0) { 5291da177e4SLinus Torvalds /* Whee! Actually deliver the signal. */ 530b927b3e2SRichard Henderson if (r0) 531b927b3e2SRichard Henderson syscall_restart(r0, r19, regs, &ka); 532d9d0738aSAl Viro handle_signal(signr, &ka, &info, regs); 5331da177e4SLinus Torvalds if (single_stepping) 5341da177e4SLinus Torvalds ptrace_set_bpt(current); /* re-set bpt */ 535b927b3e2SRichard Henderson return; 5361da177e4SLinus Torvalds } 5371da177e4SLinus Torvalds 5381da177e4SLinus Torvalds if (r0) { 5391da177e4SLinus Torvalds switch (regs->r0) { 5401da177e4SLinus Torvalds case ERESTARTNOHAND: 5411da177e4SLinus Torvalds case ERESTARTSYS: 5421da177e4SLinus Torvalds case ERESTARTNOINTR: 5431da177e4SLinus Torvalds /* Reset v0 and a3 and replay syscall. */ 5441da177e4SLinus Torvalds regs->r0 = r0; 5451da177e4SLinus Torvalds regs->r19 = r19; 5461da177e4SLinus Torvalds regs->pc -= 4; 5471da177e4SLinus Torvalds break; 5481da177e4SLinus Torvalds case ERESTART_RESTARTBLOCK: 5491da177e4SLinus Torvalds /* Force v0 to the restart syscall and reply. */ 5501da177e4SLinus Torvalds regs->r0 = __NR_restart_syscall; 5511da177e4SLinus Torvalds regs->pc -= 4; 5521da177e4SLinus Torvalds break; 5531da177e4SLinus Torvalds } 5541da177e4SLinus Torvalds } 555b927b3e2SRichard Henderson 556b927b3e2SRichard Henderson /* If there's no signal to deliver, we just restore the saved mask. */ 55751a7b448SAl Viro restore_saved_sigmask(); 5581da177e4SLinus Torvalds if (single_stepping) 5591da177e4SLinus Torvalds ptrace_set_bpt(current); /* re-set breakpoint */ 5601da177e4SLinus Torvalds } 5611da177e4SLinus Torvalds 5621da177e4SLinus Torvalds void 563cb450766SAl Viro do_work_pending(struct pt_regs *regs, unsigned long thread_flags, 564b927b3e2SRichard Henderson unsigned long r0, unsigned long r19) 5651da177e4SLinus Torvalds { 5666972d6f2SAl Viro do { 5676972d6f2SAl Viro if (thread_flags & _TIF_NEED_RESCHED) { 5686972d6f2SAl Viro schedule(); 5696972d6f2SAl Viro } else { 5706972d6f2SAl Viro local_irq_enable(); 5716972d6f2SAl Viro if (thread_flags & _TIF_SIGPENDING) { 572d9d0738aSAl Viro do_signal(regs, r0, r19); 5736972d6f2SAl Viro r0 = 0; 5746972d6f2SAl Viro } else { 575d0420c83SDavid Howells clear_thread_flag(TIF_NOTIFY_RESUME); 576d0420c83SDavid Howells tracehook_notify_resume(regs); 577d0420c83SDavid Howells } 5781da177e4SLinus Torvalds } 5796972d6f2SAl Viro local_irq_disable(); 5806972d6f2SAl Viro thread_flags = current_thread_info()->flags; 5816972d6f2SAl Viro } while (thread_flags & _TIF_WORK_MASK); 5826972d6f2SAl Viro } 583