1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/arch/alpha/kernel/signal.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (C) 1995 Linus Torvalds
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * 1997-11-02 Modified for POSIX.1b signals by Richard Henderson
81da177e4SLinus Torvalds */
91da177e4SLinus Torvalds
103f07c014SIngo Molnar #include <linux/sched/signal.h>
1168db0cf1SIngo Molnar #include <linux/sched/task_stack.h>
121da177e4SLinus Torvalds #include <linux/kernel.h>
131da177e4SLinus Torvalds #include <linux/signal.h>
141da177e4SLinus Torvalds #include <linux/errno.h>
151da177e4SLinus Torvalds #include <linux/wait.h>
161da177e4SLinus Torvalds #include <linux/ptrace.h>
171da177e4SLinus Torvalds #include <linux/unistd.h>
181da177e4SLinus Torvalds #include <linux/mm.h>
191da177e4SLinus Torvalds #include <linux/smp.h>
201da177e4SLinus Torvalds #include <linux/stddef.h>
211da177e4SLinus Torvalds #include <linux/tty.h>
221da177e4SLinus Torvalds #include <linux/binfmts.h>
231da177e4SLinus Torvalds #include <linux/bitops.h>
24e5d9a90cSIvan Kokshaysky #include <linux/syscalls.h>
2503248addSEric W. Biederman #include <linux/resume_user_mode.h>
261da177e4SLinus Torvalds
277c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
281da177e4SLinus Torvalds #include <asm/sigcontext.h>
291da177e4SLinus Torvalds #include <asm/ucontext.h>
301da177e4SLinus Torvalds
311da177e4SLinus Torvalds #include "proto.h"
321da177e4SLinus Torvalds
331da177e4SLinus Torvalds
341da177e4SLinus Torvalds #define DEBUG_SIG 0
351da177e4SLinus Torvalds
361da177e4SLinus Torvalds #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
371da177e4SLinus Torvalds
381da177e4SLinus Torvalds asmlinkage void ret_from_sys_call(void);
391da177e4SLinus Torvalds
401da177e4SLinus Torvalds /*
411da177e4SLinus Torvalds * The OSF/1 sigprocmask calling sequence is different from the
421da177e4SLinus Torvalds * C sigprocmask() sequence..
431da177e4SLinus Torvalds */
SYSCALL_DEFINE2(osf_sigprocmask,int,how,unsigned long,newmask)44c52c2ddcSAl Viro SYSCALL_DEFINE2(osf_sigprocmask, int, how, unsigned long, newmask)
451da177e4SLinus Torvalds {
46c52c2ddcSAl Viro sigset_t oldmask;
47c52c2ddcSAl Viro sigset_t mask;
48c52c2ddcSAl Viro unsigned long res;
491da177e4SLinus Torvalds
5087400e54SLinus Torvalds siginitset(&mask, newmask & _BLOCKABLE);
510f44fbd2SLinus Torvalds res = sigprocmask(how, &mask, &oldmask);
52c52c2ddcSAl Viro if (!res) {
53c52c2ddcSAl Viro force_successful_syscall_return();
540f44fbd2SLinus Torvalds res = oldmask.sig[0];
551da177e4SLinus Torvalds }
56c52c2ddcSAl Viro return res;
571da177e4SLinus Torvalds }
581da177e4SLinus Torvalds
SYSCALL_DEFINE3(osf_sigaction,int,sig,const struct osf_sigaction __user *,act,struct osf_sigaction __user *,oact)59e5d9a90cSIvan Kokshaysky SYSCALL_DEFINE3(osf_sigaction, int, sig,
60e5d9a90cSIvan Kokshaysky const struct osf_sigaction __user *, act,
61e5d9a90cSIvan Kokshaysky struct osf_sigaction __user *, oact)
621da177e4SLinus Torvalds {
631da177e4SLinus Torvalds struct k_sigaction new_ka, old_ka;
641da177e4SLinus Torvalds int ret;
651da177e4SLinus Torvalds
661da177e4SLinus Torvalds if (act) {
671da177e4SLinus Torvalds old_sigset_t mask;
6896d4f267SLinus Torvalds if (!access_ok(act, sizeof(*act)) ||
691da177e4SLinus Torvalds __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
7018e6bfa9SAl Viro __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
7118e6bfa9SAl Viro __get_user(mask, &act->sa_mask))
721da177e4SLinus Torvalds return -EFAULT;
731da177e4SLinus Torvalds siginitset(&new_ka.sa.sa_mask, mask);
741da177e4SLinus Torvalds new_ka.ka_restorer = NULL;
751da177e4SLinus Torvalds }
761da177e4SLinus Torvalds
771da177e4SLinus Torvalds ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
781da177e4SLinus Torvalds
791da177e4SLinus Torvalds if (!ret && oact) {
8096d4f267SLinus Torvalds if (!access_ok(oact, sizeof(*oact)) ||
811da177e4SLinus Torvalds __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
8218e6bfa9SAl Viro __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
8318e6bfa9SAl Viro __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
841da177e4SLinus Torvalds return -EFAULT;
851da177e4SLinus Torvalds }
861da177e4SLinus Torvalds
871da177e4SLinus Torvalds return ret;
881da177e4SLinus Torvalds }
891da177e4SLinus Torvalds
SYSCALL_DEFINE5(rt_sigaction,int,sig,const struct sigaction __user *,act,struct sigaction __user *,oact,size_t,sigsetsize,void __user *,restorer)90e5d9a90cSIvan Kokshaysky SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
91e5d9a90cSIvan Kokshaysky struct sigaction __user *, oact,
92e5d9a90cSIvan Kokshaysky size_t, sigsetsize, void __user *, restorer)
931da177e4SLinus Torvalds {
941da177e4SLinus Torvalds struct k_sigaction new_ka, old_ka;
951da177e4SLinus Torvalds int ret;
961da177e4SLinus Torvalds
971da177e4SLinus Torvalds /* XXX: Don't preclude handling different sized sigset_t's. */
981da177e4SLinus Torvalds if (sigsetsize != sizeof(sigset_t))
991da177e4SLinus Torvalds return -EINVAL;
1001da177e4SLinus Torvalds
1011da177e4SLinus Torvalds if (act) {
1021da177e4SLinus Torvalds new_ka.ka_restorer = restorer;
1031da177e4SLinus Torvalds if (copy_from_user(&new_ka.sa, act, sizeof(*act)))
1041da177e4SLinus Torvalds return -EFAULT;
1051da177e4SLinus Torvalds }
1061da177e4SLinus Torvalds
1071da177e4SLinus Torvalds ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
1081da177e4SLinus Torvalds
1091da177e4SLinus Torvalds if (!ret && oact) {
1101da177e4SLinus Torvalds if (copy_to_user(oact, &old_ka.sa, sizeof(*oact)))
1111da177e4SLinus Torvalds return -EFAULT;
1121da177e4SLinus Torvalds }
1131da177e4SLinus Torvalds
1141da177e4SLinus Torvalds return ret;
1151da177e4SLinus Torvalds }
1161da177e4SLinus Torvalds
1171da177e4SLinus Torvalds /*
1181da177e4SLinus Torvalds * Do a signal return; undo the signal stack.
1191da177e4SLinus Torvalds */
1201da177e4SLinus Torvalds
1211da177e4SLinus Torvalds #if _NSIG_WORDS > 1
1221da177e4SLinus Torvalds # error "Non SA_SIGINFO frame needs rearranging"
1231da177e4SLinus Torvalds #endif
1241da177e4SLinus Torvalds
1251da177e4SLinus Torvalds struct sigframe
1261da177e4SLinus Torvalds {
1271da177e4SLinus Torvalds struct sigcontext sc;
1281da177e4SLinus Torvalds unsigned int retcode[3];
1291da177e4SLinus Torvalds };
1301da177e4SLinus Torvalds
1311da177e4SLinus Torvalds struct rt_sigframe
1321da177e4SLinus Torvalds {
1331da177e4SLinus Torvalds struct siginfo info;
1341da177e4SLinus Torvalds struct ucontext uc;
1351da177e4SLinus Torvalds unsigned int retcode[3];
1361da177e4SLinus Torvalds };
1371da177e4SLinus Torvalds
1381da177e4SLinus Torvalds /* If this changes, userland unwinders that Know Things about our signal
1391da177e4SLinus Torvalds frame will break. Do not undertake lightly. It also implies an ABI
1401da177e4SLinus Torvalds change wrt the size of siginfo_t, which may cause some pain. */
1411da177e4SLinus Torvalds extern char compile_time_assert
1421da177e4SLinus Torvalds [offsetof(struct rt_sigframe, uc.uc_mcontext) == 176 ? 1 : -1];
1431da177e4SLinus Torvalds
1441da177e4SLinus Torvalds #define INSN_MOV_R30_R16 0x47fe0410
1451da177e4SLinus Torvalds #define INSN_LDI_R0 0x201f0000
1461da177e4SLinus Torvalds #define INSN_CALLSYS 0x00000083
1471da177e4SLinus Torvalds
1481da177e4SLinus Torvalds static long
restore_sigcontext(struct sigcontext __user * sc,struct pt_regs * regs)149b960f303SAl Viro restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
1501da177e4SLinus Torvalds {
1511da177e4SLinus Torvalds unsigned long usp;
152b960f303SAl Viro struct switch_stack *sw = (struct switch_stack *)regs - 1;
153*05096666SAl Viro long err = __get_user(regs->pc, &sc->sc_pc);
1541da177e4SLinus Torvalds
155f56141e3SAndy Lutomirski current->restart_block.fn = do_no_restart_syscall;
156*05096666SAl Viro current_thread_info()->status |= TS_SAVED_FP | TS_RESTORE_FP;
1572deba1bdSAl Viro
1581da177e4SLinus Torvalds sw->r26 = (unsigned long) ret_from_sys_call;
1591da177e4SLinus Torvalds
1601da177e4SLinus Torvalds err |= __get_user(regs->r0, sc->sc_regs+0);
1611da177e4SLinus Torvalds err |= __get_user(regs->r1, sc->sc_regs+1);
1621da177e4SLinus Torvalds err |= __get_user(regs->r2, sc->sc_regs+2);
1631da177e4SLinus Torvalds err |= __get_user(regs->r3, sc->sc_regs+3);
1641da177e4SLinus Torvalds err |= __get_user(regs->r4, sc->sc_regs+4);
1651da177e4SLinus Torvalds err |= __get_user(regs->r5, sc->sc_regs+5);
1661da177e4SLinus Torvalds err |= __get_user(regs->r6, sc->sc_regs+6);
1671da177e4SLinus Torvalds err |= __get_user(regs->r7, sc->sc_regs+7);
1681da177e4SLinus Torvalds err |= __get_user(regs->r8, sc->sc_regs+8);
1691da177e4SLinus Torvalds err |= __get_user(sw->r9, sc->sc_regs+9);
1701da177e4SLinus Torvalds err |= __get_user(sw->r10, sc->sc_regs+10);
1711da177e4SLinus Torvalds err |= __get_user(sw->r11, sc->sc_regs+11);
1721da177e4SLinus Torvalds err |= __get_user(sw->r12, sc->sc_regs+12);
1731da177e4SLinus Torvalds err |= __get_user(sw->r13, sc->sc_regs+13);
1741da177e4SLinus Torvalds err |= __get_user(sw->r14, sc->sc_regs+14);
1751da177e4SLinus Torvalds err |= __get_user(sw->r15, sc->sc_regs+15);
1761da177e4SLinus Torvalds err |= __get_user(regs->r16, sc->sc_regs+16);
1771da177e4SLinus Torvalds err |= __get_user(regs->r17, sc->sc_regs+17);
1781da177e4SLinus Torvalds err |= __get_user(regs->r18, sc->sc_regs+18);
1791da177e4SLinus Torvalds err |= __get_user(regs->r19, sc->sc_regs+19);
1801da177e4SLinus Torvalds err |= __get_user(regs->r20, sc->sc_regs+20);
1811da177e4SLinus Torvalds err |= __get_user(regs->r21, sc->sc_regs+21);
1821da177e4SLinus Torvalds err |= __get_user(regs->r22, sc->sc_regs+22);
1831da177e4SLinus Torvalds err |= __get_user(regs->r23, sc->sc_regs+23);
1841da177e4SLinus Torvalds err |= __get_user(regs->r24, sc->sc_regs+24);
1851da177e4SLinus Torvalds err |= __get_user(regs->r25, sc->sc_regs+25);
1861da177e4SLinus Torvalds err |= __get_user(regs->r26, sc->sc_regs+26);
1871da177e4SLinus Torvalds err |= __get_user(regs->r27, sc->sc_regs+27);
1881da177e4SLinus Torvalds err |= __get_user(regs->r28, sc->sc_regs+28);
1891da177e4SLinus Torvalds err |= __get_user(regs->gp, sc->sc_regs+29);
1901da177e4SLinus Torvalds err |= __get_user(usp, sc->sc_regs+30);
1911da177e4SLinus Torvalds wrusp(usp);
1921da177e4SLinus Torvalds
193*05096666SAl Viro err |= __copy_from_user(current_thread_info()->fp,
194*05096666SAl Viro sc->sc_fpregs, 31 * 8);
195*05096666SAl Viro err |= __get_user(current_thread_info()->fp[31], &sc->sc_fpcr);
1961da177e4SLinus Torvalds
1971da177e4SLinus Torvalds return err;
1981da177e4SLinus Torvalds }
1991da177e4SLinus Torvalds
2001da177e4SLinus Torvalds /* Note that this syscall is also used by setcontext(3) to install
2011da177e4SLinus Torvalds a given sigcontext. This because it's impossible to set *all*
2021da177e4SLinus Torvalds registers and transfer control from userland. */
2031da177e4SLinus Torvalds
2041da177e4SLinus Torvalds asmlinkage void
do_sigreturn(struct sigcontext __user * sc)205b960f303SAl Viro do_sigreturn(struct sigcontext __user *sc)
2061da177e4SLinus Torvalds {
207b960f303SAl Viro struct pt_regs *regs = current_pt_regs();
2081da177e4SLinus Torvalds sigset_t set;
2091da177e4SLinus Torvalds
2101da177e4SLinus Torvalds /* Verify that it's a good sigcontext before using it */
21196d4f267SLinus Torvalds if (!access_ok(sc, sizeof(*sc)))
2121da177e4SLinus Torvalds goto give_sigsegv;
2131da177e4SLinus Torvalds if (__get_user(set.sig[0], &sc->sc_mask))
2141da177e4SLinus Torvalds goto give_sigsegv;
2151da177e4SLinus Torvalds
2162561b069SMatt Fleming set_current_blocked(&set);
2171da177e4SLinus Torvalds
218b960f303SAl Viro if (restore_sigcontext(sc, regs))
2191da177e4SLinus Torvalds goto give_sigsegv;
2201da177e4SLinus Torvalds
2211da177e4SLinus Torvalds /* Send SIGTRAP if we're single-stepping: */
2221da177e4SLinus Torvalds if (ptrace_cancel_bpt (current)) {
2237de5f68dSEric W. Biederman send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *) regs->pc,
2245f50245bSEric W. Biederman current);
2251da177e4SLinus Torvalds }
2261da177e4SLinus Torvalds return;
2271da177e4SLinus Torvalds
2281da177e4SLinus Torvalds give_sigsegv:
2293cf5d076SEric W. Biederman force_sig(SIGSEGV);
2301da177e4SLinus Torvalds }
2311da177e4SLinus Torvalds
2321da177e4SLinus Torvalds asmlinkage void
do_rt_sigreturn(struct rt_sigframe __user * frame)233b960f303SAl Viro do_rt_sigreturn(struct rt_sigframe __user *frame)
2341da177e4SLinus Torvalds {
235b960f303SAl Viro struct pt_regs *regs = current_pt_regs();
2361da177e4SLinus Torvalds sigset_t set;
2371da177e4SLinus Torvalds
2381da177e4SLinus Torvalds /* Verify that it's a good ucontext_t before using it */
23996d4f267SLinus Torvalds if (!access_ok(&frame->uc, sizeof(frame->uc)))
2401da177e4SLinus Torvalds goto give_sigsegv;
2411da177e4SLinus Torvalds if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
2421da177e4SLinus Torvalds goto give_sigsegv;
2431da177e4SLinus Torvalds
2442561b069SMatt Fleming set_current_blocked(&set);
2451da177e4SLinus Torvalds
246b960f303SAl Viro if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
2471da177e4SLinus Torvalds goto give_sigsegv;
2481da177e4SLinus Torvalds
2491da177e4SLinus Torvalds /* Send SIGTRAP if we're single-stepping: */
2501da177e4SLinus Torvalds if (ptrace_cancel_bpt (current)) {
2517de5f68dSEric W. Biederman send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *) regs->pc,
2525f50245bSEric W. Biederman current);
2531da177e4SLinus Torvalds }
2541da177e4SLinus Torvalds return;
2551da177e4SLinus Torvalds
2561da177e4SLinus Torvalds give_sigsegv:
2573cf5d076SEric W. Biederman force_sig(SIGSEGV);
2581da177e4SLinus Torvalds }
2591da177e4SLinus Torvalds
2601da177e4SLinus Torvalds
2611da177e4SLinus Torvalds /*
2621da177e4SLinus Torvalds * Set up a signal frame.
2631da177e4SLinus Torvalds */
2641da177e4SLinus Torvalds
2651da177e4SLinus Torvalds static inline void __user *
get_sigframe(struct ksignal * ksig,unsigned long sp,size_t frame_size)266cfd60c07SAl Viro get_sigframe(struct ksignal *ksig, unsigned long sp, size_t frame_size)
2671da177e4SLinus Torvalds {
268cfd60c07SAl Viro return (void __user *)((sigsp(sp, ksig) - frame_size) & -32ul);
2691da177e4SLinus Torvalds }
2701da177e4SLinus Torvalds
2711da177e4SLinus Torvalds static long
setup_sigcontext(struct sigcontext __user * sc,struct pt_regs * regs,unsigned long mask,unsigned long sp)2721da177e4SLinus Torvalds setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
273d9d0738aSAl Viro unsigned long mask, unsigned long sp)
2741da177e4SLinus Torvalds {
275d9d0738aSAl Viro struct switch_stack *sw = (struct switch_stack *)regs - 1;
276*05096666SAl Viro long err = 0;
2771da177e4SLinus Torvalds
2781da177e4SLinus Torvalds err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack);
2791da177e4SLinus Torvalds err |= __put_user(mask, &sc->sc_mask);
2801da177e4SLinus Torvalds err |= __put_user(regs->pc, &sc->sc_pc);
2811da177e4SLinus Torvalds err |= __put_user(8, &sc->sc_ps);
2821da177e4SLinus Torvalds
2831da177e4SLinus Torvalds err |= __put_user(regs->r0 , sc->sc_regs+0);
2841da177e4SLinus Torvalds err |= __put_user(regs->r1 , sc->sc_regs+1);
2851da177e4SLinus Torvalds err |= __put_user(regs->r2 , sc->sc_regs+2);
2861da177e4SLinus Torvalds err |= __put_user(regs->r3 , sc->sc_regs+3);
2871da177e4SLinus Torvalds err |= __put_user(regs->r4 , sc->sc_regs+4);
2881da177e4SLinus Torvalds err |= __put_user(regs->r5 , sc->sc_regs+5);
2891da177e4SLinus Torvalds err |= __put_user(regs->r6 , sc->sc_regs+6);
2901da177e4SLinus Torvalds err |= __put_user(regs->r7 , sc->sc_regs+7);
2911da177e4SLinus Torvalds err |= __put_user(regs->r8 , sc->sc_regs+8);
2921da177e4SLinus Torvalds err |= __put_user(sw->r9 , sc->sc_regs+9);
2931da177e4SLinus Torvalds err |= __put_user(sw->r10 , sc->sc_regs+10);
2941da177e4SLinus Torvalds err |= __put_user(sw->r11 , sc->sc_regs+11);
2951da177e4SLinus Torvalds err |= __put_user(sw->r12 , sc->sc_regs+12);
2961da177e4SLinus Torvalds err |= __put_user(sw->r13 , sc->sc_regs+13);
2971da177e4SLinus Torvalds err |= __put_user(sw->r14 , sc->sc_regs+14);
2981da177e4SLinus Torvalds err |= __put_user(sw->r15 , sc->sc_regs+15);
2991da177e4SLinus Torvalds err |= __put_user(regs->r16, sc->sc_regs+16);
3001da177e4SLinus Torvalds err |= __put_user(regs->r17, sc->sc_regs+17);
3011da177e4SLinus Torvalds err |= __put_user(regs->r18, sc->sc_regs+18);
3021da177e4SLinus Torvalds err |= __put_user(regs->r19, sc->sc_regs+19);
3031da177e4SLinus Torvalds err |= __put_user(regs->r20, sc->sc_regs+20);
3041da177e4SLinus Torvalds err |= __put_user(regs->r21, sc->sc_regs+21);
3051da177e4SLinus Torvalds err |= __put_user(regs->r22, sc->sc_regs+22);
3061da177e4SLinus Torvalds err |= __put_user(regs->r23, sc->sc_regs+23);
3071da177e4SLinus Torvalds err |= __put_user(regs->r24, sc->sc_regs+24);
3081da177e4SLinus Torvalds err |= __put_user(regs->r25, sc->sc_regs+25);
3091da177e4SLinus Torvalds err |= __put_user(regs->r26, sc->sc_regs+26);
3101da177e4SLinus Torvalds err |= __put_user(regs->r27, sc->sc_regs+27);
3111da177e4SLinus Torvalds err |= __put_user(regs->r28, sc->sc_regs+28);
3121da177e4SLinus Torvalds err |= __put_user(regs->gp , sc->sc_regs+29);
3131da177e4SLinus Torvalds err |= __put_user(sp, sc->sc_regs+30);
3141da177e4SLinus Torvalds err |= __put_user(0, sc->sc_regs+31);
3151da177e4SLinus Torvalds
316*05096666SAl Viro err |= __copy_to_user(sc->sc_fpregs,
317*05096666SAl Viro current_thread_info()->fp, 31 * 8);
3181da177e4SLinus Torvalds err |= __put_user(0, sc->sc_fpregs+31);
319*05096666SAl Viro err |= __put_user(current_thread_info()->fp[31], &sc->sc_fpcr);
3201da177e4SLinus Torvalds
3211da177e4SLinus Torvalds err |= __put_user(regs->trap_a0, &sc->sc_traparg_a0);
3221da177e4SLinus Torvalds err |= __put_user(regs->trap_a1, &sc->sc_traparg_a1);
3231da177e4SLinus Torvalds err |= __put_user(regs->trap_a2, &sc->sc_traparg_a2);
3241da177e4SLinus Torvalds
3251da177e4SLinus Torvalds return err;
3261da177e4SLinus Torvalds }
3271da177e4SLinus Torvalds
328b927b3e2SRichard Henderson static int
setup_frame(struct ksignal * ksig,sigset_t * set,struct pt_regs * regs)329cfd60c07SAl Viro setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
3301da177e4SLinus Torvalds {
3311da177e4SLinus Torvalds unsigned long oldsp, r26, err = 0;
3321da177e4SLinus Torvalds struct sigframe __user *frame;
3331da177e4SLinus Torvalds
3341da177e4SLinus Torvalds oldsp = rdusp();
335cfd60c07SAl Viro frame = get_sigframe(ksig, oldsp, sizeof(*frame));
33696d4f267SLinus Torvalds if (!access_ok(frame, sizeof(*frame)))
337cbdfb9ffSAl Viro return -EFAULT;
3381da177e4SLinus Torvalds
339d9d0738aSAl Viro err |= setup_sigcontext(&frame->sc, regs, set->sig[0], oldsp);
3401da177e4SLinus Torvalds if (err)
341cbdfb9ffSAl Viro return -EFAULT;
3421da177e4SLinus Torvalds
3431da177e4SLinus Torvalds /* Set up to return from userspace. If provided, use a stub
3441da177e4SLinus Torvalds already in userspace. */
345cfd60c07SAl Viro r26 = (unsigned long) ksig->ka.ka_restorer;
346cfd60c07SAl Viro if (!r26) {
3471da177e4SLinus Torvalds err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
3481da177e4SLinus Torvalds err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
3491da177e4SLinus Torvalds err |= __put_user(INSN_CALLSYS, frame->retcode+2);
3501da177e4SLinus Torvalds imb();
3511da177e4SLinus Torvalds r26 = (unsigned long) frame->retcode;
3521da177e4SLinus Torvalds }
3531da177e4SLinus Torvalds
3541da177e4SLinus Torvalds /* Check that everything was written properly. */
3551da177e4SLinus Torvalds if (err)
356cbdfb9ffSAl Viro return err;
3571da177e4SLinus Torvalds
3581da177e4SLinus Torvalds /* "Return" to the handler */
3591da177e4SLinus Torvalds regs->r26 = r26;
360cfd60c07SAl Viro regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
361cfd60c07SAl Viro regs->r16 = ksig->sig; /* a0: signal number */
3621da177e4SLinus Torvalds regs->r17 = 0; /* a1: exception code */
3631da177e4SLinus Torvalds regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */
3641da177e4SLinus Torvalds wrusp((unsigned long) frame);
3651da177e4SLinus Torvalds
3661da177e4SLinus Torvalds #if DEBUG_SIG
3671da177e4SLinus Torvalds printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
3681da177e4SLinus Torvalds current->comm, current->pid, frame, regs->pc, regs->r26);
3691da177e4SLinus Torvalds #endif
370b927b3e2SRichard Henderson return 0;
3711da177e4SLinus Torvalds }
3721da177e4SLinus Torvalds
373b927b3e2SRichard Henderson static int
setup_rt_frame(struct ksignal * ksig,sigset_t * set,struct pt_regs * regs)374cfd60c07SAl Viro setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
3751da177e4SLinus Torvalds {
3761da177e4SLinus Torvalds unsigned long oldsp, r26, err = 0;
3771da177e4SLinus Torvalds struct rt_sigframe __user *frame;
3781da177e4SLinus Torvalds
3791da177e4SLinus Torvalds oldsp = rdusp();
380cfd60c07SAl Viro frame = get_sigframe(ksig, oldsp, sizeof(*frame));
38196d4f267SLinus Torvalds if (!access_ok(frame, sizeof(*frame)))
382cbdfb9ffSAl Viro return -EFAULT;
3831da177e4SLinus Torvalds
384cfd60c07SAl Viro err |= copy_siginfo_to_user(&frame->info, &ksig->info);
3851da177e4SLinus Torvalds
3861da177e4SLinus Torvalds /* Create the ucontext. */
3871da177e4SLinus Torvalds err |= __put_user(0, &frame->uc.uc_flags);
3881da177e4SLinus Torvalds err |= __put_user(0, &frame->uc.uc_link);
3891da177e4SLinus Torvalds err |= __put_user(set->sig[0], &frame->uc.uc_osf_sigmask);
39050ececcfSAl Viro err |= __save_altstack(&frame->uc.uc_stack, oldsp);
391d9d0738aSAl Viro err |= setup_sigcontext(&frame->uc.uc_mcontext, regs,
3921da177e4SLinus Torvalds set->sig[0], oldsp);
3931da177e4SLinus Torvalds err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
3941da177e4SLinus Torvalds if (err)
395cbdfb9ffSAl Viro return -EFAULT;
3961da177e4SLinus Torvalds
3971da177e4SLinus Torvalds /* Set up to return from userspace. If provided, use a stub
3981da177e4SLinus Torvalds already in userspace. */
399cfd60c07SAl Viro r26 = (unsigned long) ksig->ka.ka_restorer;
400cfd60c07SAl Viro if (!r26) {
4011da177e4SLinus Torvalds err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
4021da177e4SLinus Torvalds err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn,
4031da177e4SLinus Torvalds frame->retcode+1);
4041da177e4SLinus Torvalds err |= __put_user(INSN_CALLSYS, frame->retcode+2);
4051da177e4SLinus Torvalds imb();
4061da177e4SLinus Torvalds r26 = (unsigned long) frame->retcode;
4071da177e4SLinus Torvalds }
4081da177e4SLinus Torvalds
4091da177e4SLinus Torvalds if (err)
410cbdfb9ffSAl Viro return -EFAULT;
4111da177e4SLinus Torvalds
4121da177e4SLinus Torvalds /* "Return" to the handler */
4131da177e4SLinus Torvalds regs->r26 = r26;
414cfd60c07SAl Viro regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
415cfd60c07SAl Viro regs->r16 = ksig->sig; /* a0: signal number */
4161da177e4SLinus Torvalds regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */
4171da177e4SLinus Torvalds regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */
4181da177e4SLinus Torvalds wrusp((unsigned long) frame);
4191da177e4SLinus Torvalds
4201da177e4SLinus Torvalds #if DEBUG_SIG
4211da177e4SLinus Torvalds printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
4221da177e4SLinus Torvalds current->comm, current->pid, frame, regs->pc, regs->r26);
4231da177e4SLinus Torvalds #endif
4241da177e4SLinus Torvalds
425b927b3e2SRichard Henderson return 0;
4261da177e4SLinus Torvalds }
4271da177e4SLinus Torvalds
4281da177e4SLinus Torvalds
4291da177e4SLinus Torvalds /*
4301da177e4SLinus Torvalds * OK, we're invoking a handler.
4311da177e4SLinus Torvalds */
432cbdfb9ffSAl Viro static inline void
handle_signal(struct ksignal * ksig,struct pt_regs * regs)433cfd60c07SAl Viro handle_signal(struct ksignal *ksig, struct pt_regs *regs)
4341da177e4SLinus Torvalds {
435b7f9a11aSAl Viro sigset_t *oldset = sigmask_to_save();
436b927b3e2SRichard Henderson int ret;
437b927b3e2SRichard Henderson
438cfd60c07SAl Viro if (ksig->ka.sa.sa_flags & SA_SIGINFO)
439cfd60c07SAl Viro ret = setup_rt_frame(ksig, oldset, regs);
4401da177e4SLinus Torvalds else
441cfd60c07SAl Viro ret = setup_frame(ksig, oldset, regs);
4421da177e4SLinus Torvalds
443cfd60c07SAl Viro signal_setup_done(ret, ksig, 0);
444b927b3e2SRichard Henderson }
445b927b3e2SRichard Henderson
4461da177e4SLinus Torvalds static inline void
syscall_restart(unsigned long r0,unsigned long r19,struct pt_regs * regs,struct k_sigaction * ka)4471da177e4SLinus Torvalds syscall_restart(unsigned long r0, unsigned long r19,
4481da177e4SLinus Torvalds struct pt_regs *regs, struct k_sigaction *ka)
4491da177e4SLinus Torvalds {
4501da177e4SLinus Torvalds switch (regs->r0) {
4511da177e4SLinus Torvalds case ERESTARTSYS:
4521da177e4SLinus Torvalds if (!(ka->sa.sa_flags & SA_RESTART)) {
4531da177e4SLinus Torvalds case ERESTARTNOHAND:
4541da177e4SLinus Torvalds regs->r0 = EINTR;
4551da177e4SLinus Torvalds break;
4561da177e4SLinus Torvalds }
457df561f66SGustavo A. R. Silva fallthrough;
4581da177e4SLinus Torvalds case ERESTARTNOINTR:
4591da177e4SLinus Torvalds regs->r0 = r0; /* reset v0 and a3 and replay syscall */
4601da177e4SLinus Torvalds regs->r19 = r19;
4611da177e4SLinus Torvalds regs->pc -= 4;
4621da177e4SLinus Torvalds break;
4631da177e4SLinus Torvalds case ERESTART_RESTARTBLOCK:
4641da177e4SLinus Torvalds regs->r0 = EINTR;
4651da177e4SLinus Torvalds break;
4661da177e4SLinus Torvalds }
4671da177e4SLinus Torvalds }
4681da177e4SLinus Torvalds
4691da177e4SLinus Torvalds
4701da177e4SLinus Torvalds /*
4711da177e4SLinus Torvalds * Note that 'init' is a special process: it doesn't get signals it doesn't
4721da177e4SLinus Torvalds * want to handle. Thus you cannot kill init even with a SIGKILL even by
4731da177e4SLinus Torvalds * mistake.
4741da177e4SLinus Torvalds *
4751da177e4SLinus Torvalds * Note that we go through the signals twice: once to check the signals that
4761da177e4SLinus Torvalds * the kernel can handle, and then we build all the user-level signal handling
4771da177e4SLinus Torvalds * stack-frames in one go after that.
4781da177e4SLinus Torvalds *
4791da177e4SLinus Torvalds * "r0" and "r19" are the registers we need to restore for system call
4801da177e4SLinus Torvalds * restart. "r0" is also used as an indicator whether we can restart at
4811da177e4SLinus Torvalds * all (if we get here from anything but a syscall return, it will be 0)
4821da177e4SLinus Torvalds */
483b927b3e2SRichard Henderson static void
do_signal(struct pt_regs * regs,unsigned long r0,unsigned long r19)484d9d0738aSAl Viro do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19)
4851da177e4SLinus Torvalds {
4861da177e4SLinus Torvalds unsigned long single_stepping = ptrace_cancel_bpt(current);
487cfd60c07SAl Viro struct ksignal ksig;
4881da177e4SLinus Torvalds
4891da177e4SLinus Torvalds /* This lets the debugger run, ... */
490cfd60c07SAl Viro if (get_signal(&ksig)) {
4911da177e4SLinus Torvalds /* ... so re-check the single stepping. */
4921da177e4SLinus Torvalds single_stepping |= ptrace_cancel_bpt(current);
4931da177e4SLinus Torvalds /* Whee! Actually deliver the signal. */
494b927b3e2SRichard Henderson if (r0)
495cfd60c07SAl Viro syscall_restart(r0, r19, regs, &ksig.ka);
496cfd60c07SAl Viro handle_signal(&ksig, regs);
497cfd60c07SAl Viro } else {
498cfd60c07SAl Viro single_stepping |= ptrace_cancel_bpt(current);
4991da177e4SLinus Torvalds if (r0) {
5001da177e4SLinus Torvalds switch (regs->r0) {
5011da177e4SLinus Torvalds case ERESTARTNOHAND:
5021da177e4SLinus Torvalds case ERESTARTSYS:
5031da177e4SLinus Torvalds case ERESTARTNOINTR:
5041da177e4SLinus Torvalds /* Reset v0 and a3 and replay syscall. */
5051da177e4SLinus Torvalds regs->r0 = r0;
5061da177e4SLinus Torvalds regs->r19 = r19;
5071da177e4SLinus Torvalds regs->pc -= 4;
5081da177e4SLinus Torvalds break;
5091da177e4SLinus Torvalds case ERESTART_RESTARTBLOCK:
510cfd60c07SAl Viro /* Set v0 to the restart_syscall and replay */
5111da177e4SLinus Torvalds regs->r0 = __NR_restart_syscall;
5121da177e4SLinus Torvalds regs->pc -= 4;
5131da177e4SLinus Torvalds break;
5141da177e4SLinus Torvalds }
5151da177e4SLinus Torvalds }
51651a7b448SAl Viro restore_saved_sigmask();
517cfd60c07SAl Viro }
5181da177e4SLinus Torvalds if (single_stepping)
5191da177e4SLinus Torvalds ptrace_set_bpt(current); /* re-set breakpoint */
5201da177e4SLinus Torvalds }
5211da177e4SLinus Torvalds
5221da177e4SLinus Torvalds void
do_work_pending(struct pt_regs * regs,unsigned long thread_flags,unsigned long r0,unsigned long r19)523cb450766SAl Viro do_work_pending(struct pt_regs *regs, unsigned long thread_flags,
524b927b3e2SRichard Henderson unsigned long r0, unsigned long r19)
5251da177e4SLinus Torvalds {
5266972d6f2SAl Viro do {
5276972d6f2SAl Viro if (thread_flags & _TIF_NEED_RESCHED) {
5286972d6f2SAl Viro schedule();
5296972d6f2SAl Viro } else {
5306972d6f2SAl Viro local_irq_enable();
5315a9a8897SJens Axboe if (thread_flags & (_TIF_SIGPENDING|_TIF_NOTIFY_SIGNAL)) {
532*05096666SAl Viro preempt_disable();
533*05096666SAl Viro save_fpu();
534*05096666SAl Viro preempt_enable();
535d9d0738aSAl Viro do_signal(regs, r0, r19);
5366972d6f2SAl Viro r0 = 0;
5376972d6f2SAl Viro } else {
53803248addSEric W. Biederman resume_user_mode_work(regs);
539d0420c83SDavid Howells }
5401da177e4SLinus Torvalds }
5416972d6f2SAl Viro local_irq_disable();
5427fb2b24bSMark Rutland thread_flags = read_thread_flags();
5436972d6f2SAl Viro } while (thread_flags & _TIF_WORK_MASK);
5446972d6f2SAl Viro }
545