xref: /linux/arch/parisc/kernel/signal.c (revision ecf02de5a1491592d1b68d8095ff62ea3aaee67e)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  linux/arch/parisc/kernel/signal.c: Architecture-specific signal
31da177e4SLinus Torvalds  *  handling support.
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *  Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
61da177e4SLinus Torvalds  *  Copyright (C) 2000 Linuxcare, Inc.
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  *  Based on the ia64, i386, and alpha versions.
91da177e4SLinus Torvalds  *
101da177e4SLinus Torvalds  *  Like the IA-64, we are a recent enough port (we are *starting*
111da177e4SLinus Torvalds  *  with glibc2.2) that we do not need to support the old non-realtime
121da177e4SLinus Torvalds  *  Linux signals.  Therefore we don't.  HP/UX signals will go in
131da177e4SLinus Torvalds  *  arch/parisc/hpux/signal.c when we figure out how to do them.
141da177e4SLinus Torvalds  */
151da177e4SLinus Torvalds 
161da177e4SLinus Torvalds #include <linux/sched.h>
171da177e4SLinus Torvalds #include <linux/mm.h>
181da177e4SLinus Torvalds #include <linux/smp.h>
191da177e4SLinus Torvalds #include <linux/kernel.h>
201da177e4SLinus Torvalds #include <linux/signal.h>
211da177e4SLinus Torvalds #include <linux/errno.h>
221da177e4SLinus Torvalds #include <linux/wait.h>
231da177e4SLinus Torvalds #include <linux/ptrace.h>
24*ecf02de5SKyle McMartin #include <linux/tracehook.h>
251da177e4SLinus Torvalds #include <linux/unistd.h>
261da177e4SLinus Torvalds #include <linux/stddef.h>
271da177e4SLinus Torvalds #include <linux/compat.h>
281da177e4SLinus Torvalds #include <linux/elf.h>
29733e5e4bSDavid Howells #include <linux/tracehook.h>
301da177e4SLinus Torvalds #include <asm/ucontext.h>
311da177e4SLinus Torvalds #include <asm/rt_sigframe.h>
321da177e4SLinus Torvalds #include <asm/uaccess.h>
331da177e4SLinus Torvalds #include <asm/pgalloc.h>
341da177e4SLinus Torvalds #include <asm/cacheflush.h>
350013a854SSam Ravnborg #include <asm/asm-offsets.h>
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds #ifdef CONFIG_COMPAT
381da177e4SLinus Torvalds #include <linux/compat.h>
391da177e4SLinus Torvalds #include "signal32.h"
401da177e4SLinus Torvalds #endif
411da177e4SLinus Torvalds 
421da177e4SLinus Torvalds #define DEBUG_SIG 0
431da177e4SLinus Torvalds #define DEBUG_SIG_LEVEL 2
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds #if DEBUG_SIG
461da177e4SLinus Torvalds #define DBG(LEVEL, ...) \
471da177e4SLinus Torvalds         ((DEBUG_SIG_LEVEL >= LEVEL) \
481da177e4SLinus Torvalds 	? printk(__VA_ARGS__) : (void) 0)
491da177e4SLinus Torvalds #else
501da177e4SLinus Torvalds #define DBG(LEVEL, ...)
511da177e4SLinus Torvalds #endif
521da177e4SLinus Torvalds 
531da177e4SLinus Torvalds 
541da177e4SLinus Torvalds #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
551da177e4SLinus Torvalds 
561da177e4SLinus Torvalds /* gcc will complain if a pointer is cast to an integer of different
571da177e4SLinus Torvalds  * size.  If you really need to do this (and we do for an ELF32 user
581da177e4SLinus Torvalds  * application in an ELF64 kernel) then you have to do a cast to an
591da177e4SLinus Torvalds  * integer of the same size first.  The A() macro accomplishes
601da177e4SLinus Torvalds  * this. */
611da177e4SLinus Torvalds #define A(__x)	((unsigned long)(__x))
621da177e4SLinus Torvalds 
631da177e4SLinus Torvalds /*
641da177e4SLinus Torvalds  * Atomically swap in the new signal mask, and wait for a signal.
651da177e4SLinus Torvalds  */
66a8f44e38SHelge Deller #ifdef CONFIG_64BIT
671da177e4SLinus Torvalds #include "sys32.h"
681da177e4SLinus Torvalds #endif
691da177e4SLinus Torvalds 
701da177e4SLinus Torvalds /*
711da177e4SLinus Torvalds  * Do a signal return - restore sigcontext.
721da177e4SLinus Torvalds  */
731da177e4SLinus Torvalds 
741da177e4SLinus Torvalds /* Trampoline for calling rt_sigreturn() */
751da177e4SLinus Torvalds #define INSN_LDI_R25_0	 0x34190000 /* ldi  0,%r25 (in_syscall=0) */
761da177e4SLinus Torvalds #define INSN_LDI_R25_1	 0x34190002 /* ldi  1,%r25 (in_syscall=1) */
771da177e4SLinus Torvalds #define INSN_LDI_R20	 0x3414015a /* ldi  __NR_rt_sigreturn,%r20 */
781da177e4SLinus Torvalds #define INSN_BLE_SR2_R0  0xe4008200 /* be,l 0x100(%sr2,%r0),%sr0,%r31 */
791da177e4SLinus Torvalds #define INSN_NOP	 0x08000240 /* nop */
801da177e4SLinus Torvalds /* For debugging */
811da177e4SLinus Torvalds #define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */
821da177e4SLinus Torvalds 
831da177e4SLinus Torvalds static long
841da177e4SLinus Torvalds restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
851da177e4SLinus Torvalds {
861da177e4SLinus Torvalds 	long err = 0;
871da177e4SLinus Torvalds 
881da177e4SLinus Torvalds 	err |= __copy_from_user(regs->gr, sc->sc_gr, sizeof(regs->gr));
891da177e4SLinus Torvalds 	err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
901da177e4SLinus Torvalds 	err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq));
911da177e4SLinus Torvalds 	err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq));
921da177e4SLinus Torvalds 	err |= __get_user(regs->sar, &sc->sc_sar);
931da177e4SLinus Torvalds 	DBG(2,"restore_sigcontext: iaoq is 0x%#lx / 0x%#lx\n",
941da177e4SLinus Torvalds 			regs->iaoq[0],regs->iaoq[1]);
951da177e4SLinus Torvalds 	DBG(2,"restore_sigcontext: r28 is %ld\n", regs->gr[28]);
961da177e4SLinus Torvalds 	return err;
971da177e4SLinus Torvalds }
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds void
1001da177e4SLinus Torvalds sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
1011da177e4SLinus Torvalds {
1021da177e4SLinus Torvalds 	struct rt_sigframe __user *frame;
1031da177e4SLinus Torvalds 	struct siginfo si;
1041da177e4SLinus Torvalds 	sigset_t set;
1051da177e4SLinus Torvalds 	unsigned long usp = (regs->gr[30] & ~(0x01UL));
1061da177e4SLinus Torvalds 	unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
107a8f44e38SHelge Deller #ifdef CONFIG_64BIT
1081da177e4SLinus Torvalds 	compat_sigset_t compat_set;
1091da177e4SLinus Torvalds 	struct compat_rt_sigframe __user * compat_frame;
1101da177e4SLinus Torvalds 
111a3ea84faSKyle McMartin 	if (is_compat_task())
1121da177e4SLinus Torvalds 		sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
1131da177e4SLinus Torvalds #endif
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds 
1161da177e4SLinus Torvalds 	/* Unwind the user stack to get the rt_sigframe structure. */
1171da177e4SLinus Torvalds 	frame = (struct rt_sigframe __user *)
1181da177e4SLinus Torvalds 		(usp - sigframe_size);
1191da177e4SLinus Torvalds 	DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
1201da177e4SLinus Torvalds 
121a8f44e38SHelge Deller #ifdef CONFIG_64BIT
1221da177e4SLinus Torvalds 	compat_frame = (struct compat_rt_sigframe __user *)frame;
1231da177e4SLinus Torvalds 
124a3ea84faSKyle McMartin 	if (is_compat_task()) {
1251da177e4SLinus Torvalds 		DBG(2,"sys_rt_sigreturn: ELF32 process.\n");
1261da177e4SLinus Torvalds 		if (__copy_from_user(&compat_set, &compat_frame->uc.uc_sigmask, sizeof(compat_set)))
1271da177e4SLinus Torvalds 			goto give_sigsegv;
1281da177e4SLinus Torvalds 		sigset_32to64(&set,&compat_set);
1291da177e4SLinus Torvalds 	} else
1301da177e4SLinus Torvalds #endif
1311da177e4SLinus Torvalds 	{
1321da177e4SLinus Torvalds 		if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
1331da177e4SLinus Torvalds 			goto give_sigsegv;
1341da177e4SLinus Torvalds 	}
1351da177e4SLinus Torvalds 
1361da177e4SLinus Torvalds 	sigdelsetmask(&set, ~_BLOCKABLE);
1371da177e4SLinus Torvalds 	spin_lock_irq(&current->sighand->siglock);
1381da177e4SLinus Torvalds 	current->blocked = set;
1391da177e4SLinus Torvalds 	recalc_sigpending();
1401da177e4SLinus Torvalds 	spin_unlock_irq(&current->sighand->siglock);
1411da177e4SLinus Torvalds 
1421da177e4SLinus Torvalds 	/* Good thing we saved the old gr[30], eh? */
143a8f44e38SHelge Deller #ifdef CONFIG_64BIT
144a3ea84faSKyle McMartin 	if (is_compat_task()) {
1451da177e4SLinus Torvalds 		DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n",
1461da177e4SLinus Torvalds 				&compat_frame->uc.uc_mcontext);
1471da177e4SLinus Torvalds // FIXME: Load upper half from register file
1481da177e4SLinus Torvalds 		if (restore_sigcontext32(&compat_frame->uc.uc_mcontext,
1491da177e4SLinus Torvalds 					&compat_frame->regs, regs))
1501da177e4SLinus Torvalds 			goto give_sigsegv;
1511da177e4SLinus Torvalds 		DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
1521da177e4SLinus Torvalds 				usp, &compat_frame->uc.uc_stack);
1531da177e4SLinus Torvalds 		if (do_sigaltstack32(&compat_frame->uc.uc_stack, NULL, usp) == -EFAULT)
1541da177e4SLinus Torvalds 			goto give_sigsegv;
1551da177e4SLinus Torvalds 	} else
1561da177e4SLinus Torvalds #endif
1571da177e4SLinus Torvalds 	{
1581da177e4SLinus Torvalds 		DBG(1,"sys_rt_sigreturn: frame->uc.uc_mcontext 0x%p\n",
1591da177e4SLinus Torvalds 				&frame->uc.uc_mcontext);
1601da177e4SLinus Torvalds 		if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
1611da177e4SLinus Torvalds 			goto give_sigsegv;
1621da177e4SLinus Torvalds 		DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
1631da177e4SLinus Torvalds 				usp, &frame->uc.uc_stack);
1641da177e4SLinus Torvalds 		if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT)
1651da177e4SLinus Torvalds 			goto give_sigsegv;
1661da177e4SLinus Torvalds 	}
1671da177e4SLinus Torvalds 
1681da177e4SLinus Torvalds 
1691da177e4SLinus Torvalds 
1701da177e4SLinus Torvalds 	/* If we are on the syscall path IAOQ will not be restored, and
1711da177e4SLinus Torvalds 	 * if we are on the interrupt path we must not corrupt gr31.
1721da177e4SLinus Torvalds 	 */
1731da177e4SLinus Torvalds 	if (in_syscall)
1741da177e4SLinus Torvalds 		regs->gr[31] = regs->iaoq[0];
1751da177e4SLinus Torvalds #if DEBUG_SIG
1761da177e4SLinus Torvalds 	DBG(1,"sys_rt_sigreturn: returning to %#lx, DUMPING REGS:\n", regs->iaoq[0]);
1771da177e4SLinus Torvalds 	show_regs(regs);
1781da177e4SLinus Torvalds #endif
1791da177e4SLinus Torvalds 	return;
1801da177e4SLinus Torvalds 
1811da177e4SLinus Torvalds give_sigsegv:
1821da177e4SLinus Torvalds 	DBG(1,"sys_rt_sigreturn: Sending SIGSEGV\n");
1831da177e4SLinus Torvalds 	si.si_signo = SIGSEGV;
1841da177e4SLinus Torvalds 	si.si_errno = 0;
1851da177e4SLinus Torvalds 	si.si_code = SI_KERNEL;
186b488893aSPavel Emelyanov 	si.si_pid = task_pid_vnr(current);
18725e15731SDavid Howells 	si.si_uid = current_uid();
1881da177e4SLinus Torvalds 	si.si_addr = &frame->uc;
1891da177e4SLinus Torvalds 	force_sig_info(SIGSEGV, &si, current);
1901da177e4SLinus Torvalds 	return;
1911da177e4SLinus Torvalds }
1921da177e4SLinus Torvalds 
1931da177e4SLinus Torvalds /*
1941da177e4SLinus Torvalds  * Set up a signal frame.
1951da177e4SLinus Torvalds  */
1961da177e4SLinus Torvalds 
1971da177e4SLinus Torvalds static inline void __user *
1981da177e4SLinus Torvalds get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
1991da177e4SLinus Torvalds {
2001da177e4SLinus Torvalds 	/*FIXME: ELF32 vs. ELF64 has different frame_size, but since we
2011da177e4SLinus Torvalds 	  don't use the parameter it doesn't matter */
2021da177e4SLinus Torvalds 
2031da177e4SLinus Torvalds 	DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
2041da177e4SLinus Torvalds 			(unsigned long)ka, sp, frame_size);
2051da177e4SLinus Torvalds 
206d09042daSLaurent MEYER 	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
2071da177e4SLinus Torvalds 		sp = current->sas_ss_sp; /* Stacks grow up! */
2081da177e4SLinus Torvalds 
2091da177e4SLinus Torvalds 	DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
2101da177e4SLinus Torvalds 	return (void __user *) sp; /* Stacks grow up.  Fun. */
2111da177e4SLinus Torvalds }
2121da177e4SLinus Torvalds 
2131da177e4SLinus Torvalds static long
2141da177e4SLinus Torvalds setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_syscall)
2151da177e4SLinus Torvalds 
2161da177e4SLinus Torvalds {
2171da177e4SLinus Torvalds 	unsigned long flags = 0;
2181da177e4SLinus Torvalds 	long err = 0;
2191da177e4SLinus Torvalds 
2201da177e4SLinus Torvalds 	if (on_sig_stack((unsigned long) sc))
2211da177e4SLinus Torvalds 		flags |= PARISC_SC_FLAG_ONSTACK;
2221da177e4SLinus Torvalds 	if (in_syscall) {
2231da177e4SLinus Torvalds 		flags |= PARISC_SC_FLAG_IN_SYSCALL;
2241da177e4SLinus Torvalds 		/* regs->iaoq is undefined in the syscall return path */
2251da177e4SLinus Torvalds 		err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]);
2261da177e4SLinus Torvalds 		err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]);
2271da177e4SLinus Torvalds 		err |= __put_user(regs->sr[3], &sc->sc_iasq[0]);
2281da177e4SLinus Torvalds 		err |= __put_user(regs->sr[3], &sc->sc_iasq[1]);
2291da177e4SLinus Torvalds 		DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (in syscall)\n",
2301da177e4SLinus Torvalds 			regs->gr[31], regs->gr[31]+4);
2311da177e4SLinus Torvalds 	} else {
2321da177e4SLinus Torvalds 		err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq));
2331da177e4SLinus Torvalds 		err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq));
2341da177e4SLinus Torvalds 		DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (not in syscall)\n",
2351da177e4SLinus Torvalds 			regs->iaoq[0], regs->iaoq[1]);
2361da177e4SLinus Torvalds 	}
2371da177e4SLinus Torvalds 
2381da177e4SLinus Torvalds 	err |= __put_user(flags, &sc->sc_flags);
2391da177e4SLinus Torvalds 	err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr));
2401da177e4SLinus Torvalds 	err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
2411da177e4SLinus Torvalds 	err |= __put_user(regs->sar, &sc->sc_sar);
2421da177e4SLinus Torvalds 	DBG(1,"setup_sigcontext: r28 is %ld\n", regs->gr[28]);
2431da177e4SLinus Torvalds 
2441da177e4SLinus Torvalds 	return err;
2451da177e4SLinus Torvalds }
2461da177e4SLinus Torvalds 
2471da177e4SLinus Torvalds static long
2481da177e4SLinus Torvalds setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
2491da177e4SLinus Torvalds 	       sigset_t *set, struct pt_regs *regs, int in_syscall)
2501da177e4SLinus Torvalds {
2511da177e4SLinus Torvalds 	struct rt_sigframe __user *frame;
2521da177e4SLinus Torvalds 	unsigned long rp, usp;
2531da177e4SLinus Torvalds 	unsigned long haddr, sigframe_size;
2541da177e4SLinus Torvalds 	int err = 0;
255a8f44e38SHelge Deller #ifdef CONFIG_64BIT
2561da177e4SLinus Torvalds 	compat_int_t compat_val;
2571da177e4SLinus Torvalds 	struct compat_rt_sigframe __user * compat_frame;
2581da177e4SLinus Torvalds 	compat_sigset_t compat_set;
2591da177e4SLinus Torvalds #endif
2601da177e4SLinus Torvalds 
2611da177e4SLinus Torvalds 	usp = (regs->gr[30] & ~(0x01UL));
2621da177e4SLinus Torvalds 	/*FIXME: frame_size parameter is unused, remove it. */
2631da177e4SLinus Torvalds 	frame = get_sigframe(ka, usp, sizeof(*frame));
2641da177e4SLinus Torvalds 
2651da177e4SLinus Torvalds 	DBG(1,"SETUP_RT_FRAME: START\n");
2661da177e4SLinus Torvalds 	DBG(1,"setup_rt_frame: frame %p info %p\n", frame, info);
2671da177e4SLinus Torvalds 
2681da177e4SLinus Torvalds 
269a8f44e38SHelge Deller #ifdef CONFIG_64BIT
2701da177e4SLinus Torvalds 
2711da177e4SLinus Torvalds 	compat_frame = (struct compat_rt_sigframe __user *)frame;
2721da177e4SLinus Torvalds 
273a3ea84faSKyle McMartin 	if (is_compat_task()) {
2741da177e4SLinus Torvalds 		DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
275f671c45dSKyle McMartin 		err |= copy_siginfo_to_user32(&compat_frame->info, info);
2761da177e4SLinus Torvalds 		DBG(1,"SETUP_RT_FRAME: 1\n");
2771da177e4SLinus Torvalds 		compat_val = (compat_int_t)current->sas_ss_sp;
2781da177e4SLinus Torvalds 		err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_sp);
2791da177e4SLinus Torvalds 		DBG(1,"SETUP_RT_FRAME: 2\n");
2801da177e4SLinus Torvalds 		compat_val = (compat_int_t)current->sas_ss_size;
2811da177e4SLinus Torvalds 		err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_size);
2821da177e4SLinus Torvalds 		DBG(1,"SETUP_RT_FRAME: 3\n");
2831da177e4SLinus Torvalds 		compat_val = sas_ss_flags(regs->gr[30]);
2841da177e4SLinus Torvalds 		err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_flags);
2851da177e4SLinus Torvalds 		DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
2861da177e4SLinus Torvalds 		DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
2871da177e4SLinus Torvalds 		err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext,
2881da177e4SLinus Torvalds 					&compat_frame->regs, regs, in_syscall);
2891da177e4SLinus Torvalds 		sigset_64to32(&compat_set,set);
2901da177e4SLinus Torvalds 		err |= __copy_to_user(&compat_frame->uc.uc_sigmask, &compat_set, sizeof(compat_set));
2911da177e4SLinus Torvalds 	} else
2921da177e4SLinus Torvalds #endif
2931da177e4SLinus Torvalds 	{
2941da177e4SLinus Torvalds 		DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
2951da177e4SLinus Torvalds 		err |= copy_siginfo_to_user(&frame->info, info);
2961da177e4SLinus Torvalds 		err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
2971da177e4SLinus Torvalds 		err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
2981da177e4SLinus Torvalds 		err |= __put_user(sas_ss_flags(regs->gr[30]),
2991da177e4SLinus Torvalds 				  &frame->uc.uc_stack.ss_flags);
3001da177e4SLinus Torvalds 		DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
3011da177e4SLinus Torvalds 		DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
3021da177e4SLinus Torvalds 		err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
3031da177e4SLinus Torvalds 		/* FIXME: Should probably be converted aswell for the compat case */
3041da177e4SLinus Torvalds 		err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
3051da177e4SLinus Torvalds 	}
3061da177e4SLinus Torvalds 
3071da177e4SLinus Torvalds 	if (err)
3081da177e4SLinus Torvalds 		goto give_sigsegv;
3091da177e4SLinus Torvalds 
3101da177e4SLinus Torvalds 	/* Set up to return from userspace.  If provided, use a stub
3111da177e4SLinus Torvalds 	   already in userspace. The first words of tramp are used to
3121da177e4SLinus Torvalds 	   save the previous sigrestartblock trampoline that might be
3131da177e4SLinus Torvalds 	   on the stack. We start the sigreturn trampoline at
3141da177e4SLinus Torvalds 	   SIGRESTARTBLOCK_TRAMP+X. */
3151da177e4SLinus Torvalds 	err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0,
3161da177e4SLinus Torvalds 			&frame->tramp[SIGRESTARTBLOCK_TRAMP+0]);
3171da177e4SLinus Torvalds 	err |= __put_user(INSN_LDI_R20,
3181da177e4SLinus Torvalds 			&frame->tramp[SIGRESTARTBLOCK_TRAMP+1]);
3191da177e4SLinus Torvalds 	err |= __put_user(INSN_BLE_SR2_R0,
3201da177e4SLinus Torvalds 			&frame->tramp[SIGRESTARTBLOCK_TRAMP+2]);
3211da177e4SLinus Torvalds 	err |= __put_user(INSN_NOP, &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]);
3221da177e4SLinus Torvalds 
3231da177e4SLinus Torvalds #if DEBUG_SIG
3241da177e4SLinus Torvalds 	/* Assert that we're flushing in the correct space... */
3251da177e4SLinus Torvalds 	{
3261da177e4SLinus Torvalds 		int sid;
3271da177e4SLinus Torvalds 		asm ("mfsp %%sr3,%0" : "=r" (sid));
3281da177e4SLinus Torvalds 		DBG(1,"setup_rt_frame: Flushing 64 bytes at space %#x offset %p\n",
3291da177e4SLinus Torvalds 		       sid, frame->tramp);
3301da177e4SLinus Torvalds 	}
3311da177e4SLinus Torvalds #endif
3321da177e4SLinus Torvalds 
3331da177e4SLinus Torvalds 	flush_user_dcache_range((unsigned long) &frame->tramp[0],
3341da177e4SLinus Torvalds 			   (unsigned long) &frame->tramp[TRAMP_SIZE]);
3351da177e4SLinus Torvalds 	flush_user_icache_range((unsigned long) &frame->tramp[0],
3361da177e4SLinus Torvalds 			   (unsigned long) &frame->tramp[TRAMP_SIZE]);
3371da177e4SLinus Torvalds 
338efad798bSPaulius Zaleckas 	/* TRAMP Words 0-4, Length 5 = SIGRESTARTBLOCK_TRAMP
3391da177e4SLinus Torvalds 	 * TRAMP Words 5-9, Length 4 = SIGRETURN_TRAMP
3401da177e4SLinus Torvalds 	 * So the SIGRETURN_TRAMP is at the end of SIGRESTARTBLOCK_TRAMP
3411da177e4SLinus Torvalds 	 */
3421da177e4SLinus Torvalds 	rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
3431da177e4SLinus Torvalds 
3441da177e4SLinus Torvalds 	if (err)
3451da177e4SLinus Torvalds 		goto give_sigsegv;
3461da177e4SLinus Torvalds 
3471da177e4SLinus Torvalds 	haddr = A(ka->sa.sa_handler);
3481da177e4SLinus Torvalds 	/* The sa_handler may be a pointer to a function descriptor */
349a8f44e38SHelge Deller #ifdef CONFIG_64BIT
350a3ea84faSKyle McMartin 	if (is_compat_task()) {
3511da177e4SLinus Torvalds #endif
3521da177e4SLinus Torvalds 		if (haddr & PA_PLABEL_FDESC) {
3531da177e4SLinus Torvalds 			Elf32_Fdesc fdesc;
3541da177e4SLinus Torvalds 			Elf32_Fdesc __user *ufdesc = (Elf32_Fdesc __user *)A(haddr & ~3);
3551da177e4SLinus Torvalds 
3561da177e4SLinus Torvalds 			err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
3571da177e4SLinus Torvalds 
3581da177e4SLinus Torvalds 			if (err)
3591da177e4SLinus Torvalds 				goto give_sigsegv;
3601da177e4SLinus Torvalds 
3611da177e4SLinus Torvalds 			haddr = fdesc.addr;
3621da177e4SLinus Torvalds 			regs->gr[19] = fdesc.gp;
3631da177e4SLinus Torvalds 		}
364a8f44e38SHelge Deller #ifdef CONFIG_64BIT
3651da177e4SLinus Torvalds 	} else {
3661da177e4SLinus Torvalds 		Elf64_Fdesc fdesc;
3671da177e4SLinus Torvalds 		Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3);
3681da177e4SLinus Torvalds 
3691da177e4SLinus Torvalds 		err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
3701da177e4SLinus Torvalds 
3711da177e4SLinus Torvalds 		if (err)
3721da177e4SLinus Torvalds 			goto give_sigsegv;
3731da177e4SLinus Torvalds 
3741da177e4SLinus Torvalds 		haddr = fdesc.addr;
3751da177e4SLinus Torvalds 		regs->gr[19] = fdesc.gp;
3761da177e4SLinus Torvalds 		DBG(1,"setup_rt_frame: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
3771da177e4SLinus Torvalds 		     haddr, regs->gr[19], in_syscall);
3781da177e4SLinus Torvalds 	}
3791da177e4SLinus Torvalds #endif
3801da177e4SLinus Torvalds 
3811da177e4SLinus Torvalds 	/* The syscall return path will create IAOQ values from r31.
3821da177e4SLinus Torvalds 	 */
3831da177e4SLinus Torvalds 	sigframe_size = PARISC_RT_SIGFRAME_SIZE;
384a8f44e38SHelge Deller #ifdef CONFIG_64BIT
385a3ea84faSKyle McMartin 	if (is_compat_task())
3861da177e4SLinus Torvalds 		sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
3871da177e4SLinus Torvalds #endif
3881da177e4SLinus Torvalds 	if (in_syscall) {
3891da177e4SLinus Torvalds 		regs->gr[31] = haddr;
390a8f44e38SHelge Deller #ifdef CONFIG_64BIT
391df570b9cSKyle McMartin 		if (!test_thread_flag(TIF_32BIT))
3921da177e4SLinus Torvalds 			sigframe_size |= 1;
3931da177e4SLinus Torvalds #endif
3941da177e4SLinus Torvalds 	} else {
3951da177e4SLinus Torvalds 		unsigned long psw = USER_PSW;
396a8f44e38SHelge Deller #ifdef CONFIG_64BIT
397df570b9cSKyle McMartin 		if (!test_thread_flag(TIF_32BIT))
3981da177e4SLinus Torvalds 			psw |= PSW_W;
3991da177e4SLinus Torvalds #endif
4001da177e4SLinus Torvalds 
4011da177e4SLinus Torvalds 		/* If we are singlestepping, arrange a trap to be delivered
4021da177e4SLinus Torvalds 		   when we return to userspace. Note the semantics -- we
4031da177e4SLinus Torvalds 		   should trap before the first insn in the handler is
4041da177e4SLinus Torvalds 		   executed. Ref:
4051da177e4SLinus Torvalds 			http://sources.redhat.com/ml/gdb/2004-11/msg00245.html
4061da177e4SLinus Torvalds 		 */
4071da177e4SLinus Torvalds 		if (pa_psw(current)->r) {
4081da177e4SLinus Torvalds 			pa_psw(current)->r = 0;
4091da177e4SLinus Torvalds 			psw |= PSW_R;
4101da177e4SLinus Torvalds 			mtctl(-1, 0);
4111da177e4SLinus Torvalds 		}
4121da177e4SLinus Torvalds 
4131da177e4SLinus Torvalds 		regs->gr[0] = psw;
4141da177e4SLinus Torvalds 		regs->iaoq[0] = haddr | 3;
4151da177e4SLinus Torvalds 		regs->iaoq[1] = regs->iaoq[0] + 4;
4161da177e4SLinus Torvalds 	}
4171da177e4SLinus Torvalds 
4181da177e4SLinus Torvalds 	regs->gr[2]  = rp;                /* userland return pointer */
4191da177e4SLinus Torvalds 	regs->gr[26] = sig;               /* signal number */
4201da177e4SLinus Torvalds 
421a8f44e38SHelge Deller #ifdef CONFIG_64BIT
422a3ea84faSKyle McMartin 	if (is_compat_task()) {
4231da177e4SLinus Torvalds 		regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */
4241da177e4SLinus Torvalds 		regs->gr[24] = A(&compat_frame->uc);   /* ucontext pointer */
4251da177e4SLinus Torvalds 	} else
4261da177e4SLinus Torvalds #endif
4271da177e4SLinus Torvalds 	{
4281da177e4SLinus Torvalds 		regs->gr[25] = A(&frame->info); /* siginfo pointer */
4291da177e4SLinus Torvalds 		regs->gr[24] = A(&frame->uc);   /* ucontext pointer */
4301da177e4SLinus Torvalds 	}
4311da177e4SLinus Torvalds 
4321da177e4SLinus Torvalds 	DBG(1,"setup_rt_frame: making sigreturn frame: %#lx + %#lx = %#lx\n",
4331da177e4SLinus Torvalds 	       regs->gr[30], sigframe_size,
4341da177e4SLinus Torvalds 	       regs->gr[30] + sigframe_size);
4351da177e4SLinus Torvalds 	/* Raise the user stack pointer to make a proper call frame. */
4361da177e4SLinus Torvalds 	regs->gr[30] = (A(frame) + sigframe_size);
4371da177e4SLinus Torvalds 
4381da177e4SLinus Torvalds 
4391da177e4SLinus Torvalds 	DBG(1,"setup_rt_frame: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
4401da177e4SLinus Torvalds 	       current->comm, current->pid, frame, regs->gr[30],
4411da177e4SLinus Torvalds 	       regs->iaoq[0], regs->iaoq[1], rp);
4421da177e4SLinus Torvalds 
4431da177e4SLinus Torvalds 	return 1;
4441da177e4SLinus Torvalds 
4451da177e4SLinus Torvalds give_sigsegv:
4461da177e4SLinus Torvalds 	DBG(1,"setup_rt_frame: sending SIGSEGV\n");
44740c72f20SRandolph Chung 	force_sigsegv(sig, current);
4481da177e4SLinus Torvalds 	return 0;
4491da177e4SLinus Torvalds }
4501da177e4SLinus Torvalds 
4511da177e4SLinus Torvalds /*
4521da177e4SLinus Torvalds  * OK, we're invoking a handler.
4531da177e4SLinus Torvalds  */
4541da177e4SLinus Torvalds 
4551da177e4SLinus Torvalds static long
4561da177e4SLinus Torvalds handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
4571da177e4SLinus Torvalds 		sigset_t *oldset, struct pt_regs *regs, int in_syscall)
4581da177e4SLinus Torvalds {
4591da177e4SLinus Torvalds 	DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
4601da177e4SLinus Torvalds 	       sig, ka, info, oldset, regs);
4611da177e4SLinus Torvalds 
4621da177e4SLinus Torvalds 	/* Set up the stack frame */
4631da177e4SLinus Torvalds 	if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
4641da177e4SLinus Torvalds 		return 0;
4651da177e4SLinus Torvalds 
4661da177e4SLinus Torvalds 	spin_lock_irq(&current->sighand->siglock);
4671da177e4SLinus Torvalds 	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
46869be8f18SSteven Rostedt 	if (!(ka->sa.sa_flags & SA_NODEFER))
4691da177e4SLinus Torvalds 		sigaddset(&current->blocked,sig);
4701da177e4SLinus Torvalds 	recalc_sigpending();
4711da177e4SLinus Torvalds 	spin_unlock_irq(&current->sighand->siglock);
472*ecf02de5SKyle McMartin 
473*ecf02de5SKyle McMartin 	tracehook_signal_handler(sig, info, ka, regs, 0);
474*ecf02de5SKyle McMartin 
4751da177e4SLinus Torvalds 	return 1;
4761da177e4SLinus Torvalds }
4771da177e4SLinus Torvalds 
4782b163b71SKyle McMartin static inline void
4792b163b71SKyle McMartin syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
4802b163b71SKyle McMartin {
4812b163b71SKyle McMartin 	/* Check the return code */
4822b163b71SKyle McMartin 	switch (regs->gr[28]) {
4832b163b71SKyle McMartin 	case -ERESTART_RESTARTBLOCK:
4842b163b71SKyle McMartin 		current_thread_info()->restart_block.fn =
4852b163b71SKyle McMartin 			do_no_restart_syscall;
4862b163b71SKyle McMartin 	case -ERESTARTNOHAND:
4872b163b71SKyle McMartin 		DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
4882b163b71SKyle McMartin 		regs->gr[28] = -EINTR;
4892b163b71SKyle McMartin 		break;
4902b163b71SKyle McMartin 
4912b163b71SKyle McMartin 	case -ERESTARTSYS:
4922b163b71SKyle McMartin 		if (!(ka->sa.sa_flags & SA_RESTART)) {
4932b163b71SKyle McMartin 			DBG(1,"ERESTARTSYS: putting -EINTR\n");
4942b163b71SKyle McMartin 			regs->gr[28] = -EINTR;
4952b163b71SKyle McMartin 			break;
4962b163b71SKyle McMartin 		}
4972b163b71SKyle McMartin 		/* fallthrough */
4982b163b71SKyle McMartin 	case -ERESTARTNOINTR:
4992b163b71SKyle McMartin 		/* A syscall is just a branch, so all
5002b163b71SKyle McMartin 		 * we have to do is fiddle the return pointer.
5012b163b71SKyle McMartin 		 */
5022b163b71SKyle McMartin 		regs->gr[31] -= 8; /* delayed branching */
5032b163b71SKyle McMartin 		/* Preserve original r28. */
5042b163b71SKyle McMartin 		regs->gr[28] = regs->orig_r28;
5052b163b71SKyle McMartin 		break;
5062b163b71SKyle McMartin 	}
5072b163b71SKyle McMartin }
5082b163b71SKyle McMartin 
5092b163b71SKyle McMartin static inline void
5102b163b71SKyle McMartin insert_restart_trampoline(struct pt_regs *regs)
5112b163b71SKyle McMartin {
5122b163b71SKyle McMartin 	switch(regs->gr[28]) {
5132b163b71SKyle McMartin 	case -ERESTART_RESTARTBLOCK: {
5142b163b71SKyle McMartin 		/* Restart the system call - no handlers present */
5152b163b71SKyle McMartin 		unsigned int *usp = (unsigned int *)regs->gr[30];
5162b163b71SKyle McMartin 
5172b163b71SKyle McMartin 		/* Setup a trampoline to restart the syscall
5182b163b71SKyle McMartin 		 * with __NR_restart_syscall
5192b163b71SKyle McMartin 		 *
5202b163b71SKyle McMartin 		 *  0: <return address (orig r31)>
5212b163b71SKyle McMartin 		 *  4: <2nd half for 64-bit>
5222b163b71SKyle McMartin 		 *  8: ldw 0(%sp), %r31
5232b163b71SKyle McMartin 		 * 12: be 0x100(%sr2, %r0)
5242b163b71SKyle McMartin 		 * 16: ldi __NR_restart_syscall, %r20
5252b163b71SKyle McMartin 		 */
5262b163b71SKyle McMartin #ifdef CONFIG_64BIT
5272b163b71SKyle McMartin 		put_user(regs->gr[31] >> 32, &usp[0]);
5282b163b71SKyle McMartin 		put_user(regs->gr[31] & 0xffffffff, &usp[1]);
5292b163b71SKyle McMartin 		put_user(0x0fc010df, &usp[2]);
5302b163b71SKyle McMartin #else
5312b163b71SKyle McMartin 		put_user(regs->gr[31], &usp[0]);
5322b163b71SKyle McMartin 		put_user(0x0fc0109f, &usp[2]);
5332b163b71SKyle McMartin #endif
5342b163b71SKyle McMartin 		put_user(0xe0008200, &usp[3]);
5352b163b71SKyle McMartin 		put_user(0x34140000, &usp[4]);
5362b163b71SKyle McMartin 
5372b163b71SKyle McMartin 		/* Stack is 64-byte aligned, and we only need
5382b163b71SKyle McMartin 		 * to flush 1 cache line.
5392b163b71SKyle McMartin 		 * Flushing one cacheline is cheap.
5402b163b71SKyle McMartin 		 * "sync" on bigger (> 4 way) boxes is not.
5412b163b71SKyle McMartin 		 */
542cf39cc3bSKyle McMartin 		flush_user_dcache_range(regs->gr[30], regs->gr[30] + 4);
543cf39cc3bSKyle McMartin 		flush_user_icache_range(regs->gr[30], regs->gr[30] + 4);
5442b163b71SKyle McMartin 
5452b163b71SKyle McMartin 		regs->gr[31] = regs->gr[30] + 8;
5462b163b71SKyle McMartin 		/* Preserve original r28. */
5472b163b71SKyle McMartin 		regs->gr[28] = regs->orig_r28;
5482b163b71SKyle McMartin 
5492b163b71SKyle McMartin 		return;
5502b163b71SKyle McMartin 	}
5512b163b71SKyle McMartin 	case -ERESTARTNOHAND:
5522b163b71SKyle McMartin 	case -ERESTARTSYS:
5532b163b71SKyle McMartin 	case -ERESTARTNOINTR: {
5542b163b71SKyle McMartin 		/* Hooray for delayed branching.  We don't
5552b163b71SKyle McMartin 		 * have to restore %r20 (the system call
5562b163b71SKyle McMartin 		 * number) because it gets loaded in the delay
5572b163b71SKyle McMartin 		 * slot of the branch external instruction.
5582b163b71SKyle McMartin 		 */
5592b163b71SKyle McMartin 		regs->gr[31] -= 8;
5602b163b71SKyle McMartin 		/* Preserve original r28. */
5612b163b71SKyle McMartin 		regs->gr[28] = regs->orig_r28;
5622b163b71SKyle McMartin 
5632b163b71SKyle McMartin 		return;
5642b163b71SKyle McMartin 	}
5652b163b71SKyle McMartin 	default:
5662b163b71SKyle McMartin 		break;
5672b163b71SKyle McMartin 	}
5682b163b71SKyle McMartin }
5692b163b71SKyle McMartin 
5701da177e4SLinus Torvalds /*
5711da177e4SLinus Torvalds  * Note that 'init' is a special process: it doesn't get signals it doesn't
5721da177e4SLinus Torvalds  * want to handle. Thus you cannot kill init even with a SIGKILL even by
5731da177e4SLinus Torvalds  * mistake.
5741da177e4SLinus Torvalds  *
5751da177e4SLinus Torvalds  * We need to be able to restore the syscall arguments (r21-r26) to
5761da177e4SLinus Torvalds  * restart syscalls.  Thus, the syscall path should save them in the
5771da177e4SLinus Torvalds  * pt_regs structure (it's okay to do so since they are caller-save
5781da177e4SLinus Torvalds  * registers).  As noted below, the syscall number gets restored for
5791da177e4SLinus Torvalds  * us due to the magic of delayed branching.
5801da177e4SLinus Torvalds  */
5814650f0a5SKyle McMartin asmlinkage void
5824650f0a5SKyle McMartin do_signal(struct pt_regs *regs, long in_syscall)
5831da177e4SLinus Torvalds {
5841da177e4SLinus Torvalds 	siginfo_t info;
5851da177e4SLinus Torvalds 	struct k_sigaction ka;
5861da177e4SLinus Torvalds 	int signr;
5874650f0a5SKyle McMartin 	sigset_t *oldset;
5881da177e4SLinus Torvalds 
5891da177e4SLinus Torvalds 	DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n",
5901da177e4SLinus Torvalds 	       oldset, regs, regs->sr[7], in_syscall);
5911da177e4SLinus Torvalds 
5921da177e4SLinus Torvalds 	/* Everyone else checks to see if they are in kernel mode at
5931da177e4SLinus Torvalds 	   this point and exits if that's the case.  I'm not sure why
5941da177e4SLinus Torvalds 	   we would be called in that case, but for some reason we
5951da177e4SLinus Torvalds 	   are. */
5961da177e4SLinus Torvalds 
5974650f0a5SKyle McMartin 	if (test_thread_flag(TIF_RESTORE_SIGMASK))
5984650f0a5SKyle McMartin 		oldset = &current->saved_sigmask;
5994650f0a5SKyle McMartin 	else
6001da177e4SLinus Torvalds 		oldset = &current->blocked;
6011da177e4SLinus Torvalds 
6021da177e4SLinus Torvalds 	DBG(1,"do_signal: oldset %08lx / %08lx\n",
6031da177e4SLinus Torvalds 		oldset->sig[0], oldset->sig[1]);
6041da177e4SLinus Torvalds 
6051da177e4SLinus Torvalds 
6061da177e4SLinus Torvalds 	/* May need to force signal if handle_signal failed to deliver */
6071da177e4SLinus Torvalds 	while (1) {
6081da177e4SLinus Torvalds 
6091da177e4SLinus Torvalds 		signr = get_signal_to_deliver(&info, &ka, regs, NULL);
6101da177e4SLinus Torvalds 		DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
6111da177e4SLinus Torvalds 
6121da177e4SLinus Torvalds 		if (signr <= 0)
6131da177e4SLinus Torvalds 		  break;
6141da177e4SLinus Torvalds 
6151da177e4SLinus Torvalds 		/* Restart a system call if necessary. */
6162b163b71SKyle McMartin 		if (in_syscall)
6172b163b71SKyle McMartin 			syscall_restart(regs, &ka);
6181da177e4SLinus Torvalds 
6191da177e4SLinus Torvalds 		/* Whee!  Actually deliver the signal.  If the
6201da177e4SLinus Torvalds 		   delivery failed, we need to continue to iterate in
6211da177e4SLinus Torvalds 		   this loop so we can deliver the SIGSEGV... */
6222b163b71SKyle McMartin 		if (handle_signal(signr, &info, &ka, oldset,
6232b163b71SKyle McMartin 				  regs, in_syscall)) {
6241da177e4SLinus Torvalds 			DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
6251da177e4SLinus Torvalds 				regs->gr[28]);
6264650f0a5SKyle McMartin 			if (test_thread_flag(TIF_RESTORE_SIGMASK))
6274650f0a5SKyle McMartin 				clear_thread_flag(TIF_RESTORE_SIGMASK);
6284650f0a5SKyle McMartin 			return;
6291da177e4SLinus Torvalds 		}
6301da177e4SLinus Torvalds 	}
6311da177e4SLinus Torvalds 	/* end of while(1) looping forever if we can't force a signal */
6321da177e4SLinus Torvalds 
6331da177e4SLinus Torvalds 	/* Did we come from a system call? */
6342b163b71SKyle McMartin 	if (in_syscall)
6352b163b71SKyle McMartin 		insert_restart_trampoline(regs);
6361da177e4SLinus Torvalds 
6371da177e4SLinus Torvalds 	DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n",
6381da177e4SLinus Torvalds 		regs->gr[28]);
6391da177e4SLinus Torvalds 
6404650f0a5SKyle McMartin 	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
6414650f0a5SKyle McMartin 		clear_thread_flag(TIF_RESTORE_SIGMASK);
6424650f0a5SKyle McMartin 		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
6434650f0a5SKyle McMartin 	}
6444650f0a5SKyle McMartin 
6454650f0a5SKyle McMartin 	return;
6464650f0a5SKyle McMartin }
6474650f0a5SKyle McMartin 
6484650f0a5SKyle McMartin void do_notify_resume(struct pt_regs *regs, long in_syscall)
6494650f0a5SKyle McMartin {
6504650f0a5SKyle McMartin 	if (test_thread_flag(TIF_SIGPENDING) ||
6514650f0a5SKyle McMartin 	    test_thread_flag(TIF_RESTORE_SIGMASK))
6524650f0a5SKyle McMartin 		do_signal(regs, in_syscall);
653d0420c83SDavid Howells 
654d0420c83SDavid Howells 	if (test_thread_flag(TIF_NOTIFY_RESUME)) {
655d0420c83SDavid Howells 		clear_thread_flag(TIF_NOTIFY_RESUME);
656d0420c83SDavid Howells 		tracehook_notify_resume(regs);
657ee18d64cSDavid Howells 		if (current->replacement_session_keyring)
658ee18d64cSDavid Howells 			key_replace_session_keyring();
659d0420c83SDavid Howells 	}
6601da177e4SLinus Torvalds }
661