xref: /openbmc/linux/arch/mips/kernel/signal.c (revision 53dc8028)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * This file is subject to the terms and conditions of the GNU General Public
31da177e4SLinus Torvalds  * License.  See the file "COPYING" in the main directory of this archive
41da177e4SLinus Torvalds  * for more details.
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Copyright (C) 1991, 1992  Linus Torvalds
71da177e4SLinus Torvalds  * Copyright (C) 1994 - 2000  Ralf Baechle
81da177e4SLinus Torvalds  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
91da177e4SLinus Torvalds  */
1002416dcfSRalf Baechle #include <linux/cache.h>
111da177e4SLinus Torvalds #include <linux/sched.h>
121da177e4SLinus Torvalds #include <linux/mm.h>
131da177e4SLinus Torvalds #include <linux/personality.h>
141da177e4SLinus Torvalds #include <linux/smp.h>
151da177e4SLinus Torvalds #include <linux/smp_lock.h>
161da177e4SLinus Torvalds #include <linux/kernel.h>
171da177e4SLinus Torvalds #include <linux/signal.h>
181da177e4SLinus Torvalds #include <linux/errno.h>
191da177e4SLinus Torvalds #include <linux/wait.h>
201da177e4SLinus Torvalds #include <linux/ptrace.h>
211da177e4SLinus Torvalds #include <linux/unistd.h>
221da177e4SLinus Torvalds #include <linux/compiler.h>
231da177e4SLinus Torvalds 
24e50c0a8fSRalf Baechle #include <asm/abi.h>
251da177e4SLinus Torvalds #include <asm/asm.h>
261da177e4SLinus Torvalds #include <linux/bitops.h>
271da177e4SLinus Torvalds #include <asm/cacheflush.h>
281da177e4SLinus Torvalds #include <asm/fpu.h>
291da177e4SLinus Torvalds #include <asm/sim.h>
301da177e4SLinus Torvalds #include <asm/uaccess.h>
311da177e4SLinus Torvalds #include <asm/ucontext.h>
321da177e4SLinus Torvalds #include <asm/cpu-features.h>
3302416dcfSRalf Baechle #include <asm/war.h>
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds #include "signal-common.h"
361da177e4SLinus Torvalds 
3766680583SRalf Baechle /*
3866680583SRalf Baechle  * Horribly complicated - with the bloody RM9000 workarounds enabled
3966680583SRalf Baechle  * the signal trampolines is moving to the end of the structure so we can
4066680583SRalf Baechle  * increase the alignment without breaking software compatibility.
4166680583SRalf Baechle  */
42c0b9bae9SFranck Bui-Huu #if ICACHE_REFILLS_WORKAROUND_WAR == 0
43c0b9bae9SFranck Bui-Huu 
4466680583SRalf Baechle struct sigframe {
4566680583SRalf Baechle 	u32 sf_ass[4];		/* argument save space for o32 */
4666680583SRalf Baechle 	u32 sf_code[2];		/* signal trampoline */
4766680583SRalf Baechle 	struct sigcontext sf_sc;
4866680583SRalf Baechle 	sigset_t sf_mask;
4966680583SRalf Baechle };
5066680583SRalf Baechle 
51c0b9bae9SFranck Bui-Huu struct rt_sigframe {
52c0b9bae9SFranck Bui-Huu 	u32 rs_ass[4];		/* argument save space for o32 */
53c0b9bae9SFranck Bui-Huu 	u32 rs_code[2];		/* signal trampoline */
54c0b9bae9SFranck Bui-Huu 	struct siginfo rs_info;
55c0b9bae9SFranck Bui-Huu 	struct ucontext rs_uc;
56c0b9bae9SFranck Bui-Huu };
57c0b9bae9SFranck Bui-Huu 
58c0b9bae9SFranck Bui-Huu #else
59c0b9bae9SFranck Bui-Huu 
6066680583SRalf Baechle struct sigframe {
6166680583SRalf Baechle 	u32 sf_ass[4];			/* argument save space for o32 */
6266680583SRalf Baechle 	u32 sf_pad[2];
6366680583SRalf Baechle 	struct sigcontext sf_sc;	/* hw context */
6466680583SRalf Baechle 	sigset_t sf_mask;
6566680583SRalf Baechle 	u32 sf_code[8] ____cacheline_aligned;	/* signal trampoline */
6666680583SRalf Baechle };
6766680583SRalf Baechle 
68c0b9bae9SFranck Bui-Huu struct rt_sigframe {
69c0b9bae9SFranck Bui-Huu 	u32 rs_ass[4];			/* argument save space for o32 */
70c0b9bae9SFranck Bui-Huu 	u32 rs_pad[2];
71c0b9bae9SFranck Bui-Huu 	struct siginfo rs_info;
72c0b9bae9SFranck Bui-Huu 	struct ucontext rs_uc;
73c0b9bae9SFranck Bui-Huu 	u32 rs_code[8] ____cacheline_aligned;	/* signal trampoline */
74c0b9bae9SFranck Bui-Huu };
75c0b9bae9SFranck Bui-Huu 
76c0b9bae9SFranck Bui-Huu #endif
77c0b9bae9SFranck Bui-Huu 
781da177e4SLinus Torvalds /*
79c3fc4ab3SFranck Bui-Huu  * Helper routines
80c3fc4ab3SFranck Bui-Huu  */
81c3fc4ab3SFranck Bui-Huu int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
82c3fc4ab3SFranck Bui-Huu {
83c3fc4ab3SFranck Bui-Huu 	int err = 0;
84c3fc4ab3SFranck Bui-Huu 	int i;
8553dc8028SAtsushi Nemoto 	unsigned int used_math;
86c3fc4ab3SFranck Bui-Huu 
87c3fc4ab3SFranck Bui-Huu 	err |= __put_user(regs->cp0_epc, &sc->sc_pc);
88c3fc4ab3SFranck Bui-Huu 
89c3fc4ab3SFranck Bui-Huu 	err |= __put_user(0, &sc->sc_regs[0]);
90c3fc4ab3SFranck Bui-Huu 	for (i = 1; i < 32; i++)
91c3fc4ab3SFranck Bui-Huu 		err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
92c3fc4ab3SFranck Bui-Huu 
939693a853SFranck Bui-Huu #ifdef CONFIG_CPU_HAS_SMARTMIPS
949693a853SFranck Bui-Huu 	err |= __put_user(regs->acx, &sc->sc_acx);
959693a853SFranck Bui-Huu #endif
96c3fc4ab3SFranck Bui-Huu 	err |= __put_user(regs->hi, &sc->sc_mdhi);
97c3fc4ab3SFranck Bui-Huu 	err |= __put_user(regs->lo, &sc->sc_mdlo);
98c3fc4ab3SFranck Bui-Huu 	if (cpu_has_dsp) {
99c3fc4ab3SFranck Bui-Huu 		err |= __put_user(mfhi1(), &sc->sc_hi1);
100c3fc4ab3SFranck Bui-Huu 		err |= __put_user(mflo1(), &sc->sc_lo1);
101c3fc4ab3SFranck Bui-Huu 		err |= __put_user(mfhi2(), &sc->sc_hi2);
102c3fc4ab3SFranck Bui-Huu 		err |= __put_user(mflo2(), &sc->sc_lo2);
103c3fc4ab3SFranck Bui-Huu 		err |= __put_user(mfhi3(), &sc->sc_hi3);
104c3fc4ab3SFranck Bui-Huu 		err |= __put_user(mflo3(), &sc->sc_lo3);
105c3fc4ab3SFranck Bui-Huu 		err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
106c3fc4ab3SFranck Bui-Huu 	}
107c3fc4ab3SFranck Bui-Huu 
10853dc8028SAtsushi Nemoto 	used_math = !!used_math();
10953dc8028SAtsushi Nemoto 	err |= __put_user(used_math, &sc->sc_used_math);
110c3fc4ab3SFranck Bui-Huu 
11153dc8028SAtsushi Nemoto 	if (used_math) {
112c3fc4ab3SFranck Bui-Huu 		/*
113c3fc4ab3SFranck Bui-Huu 		 * Save FPU state to signal context. Signal handler
114c3fc4ab3SFranck Bui-Huu 		 * will "inherit" current FPU state.
115c3fc4ab3SFranck Bui-Huu 		 */
11653dc8028SAtsushi Nemoto 		own_fpu(1);
11753dc8028SAtsushi Nemoto 		enable_fp_in_kernel();
118c3fc4ab3SFranck Bui-Huu 		err |= save_fp_context(sc);
11953dc8028SAtsushi Nemoto 		disable_fp_in_kernel();
120c3fc4ab3SFranck Bui-Huu 	}
121c3fc4ab3SFranck Bui-Huu 	return err;
122c3fc4ab3SFranck Bui-Huu }
123c3fc4ab3SFranck Bui-Huu 
124c6a2f467SAtsushi Nemoto int fpcsr_pending(unsigned int __user *fpcsr)
125c6a2f467SAtsushi Nemoto {
126c6a2f467SAtsushi Nemoto 	int err, sig = 0;
127c6a2f467SAtsushi Nemoto 	unsigned int csr, enabled;
128c6a2f467SAtsushi Nemoto 
129c6a2f467SAtsushi Nemoto 	err = __get_user(csr, fpcsr);
130c6a2f467SAtsushi Nemoto 	enabled = FPU_CSR_UNI_X | ((csr & FPU_CSR_ALL_E) << 5);
131c6a2f467SAtsushi Nemoto 	/*
132c6a2f467SAtsushi Nemoto 	 * If the signal handler set some FPU exceptions, clear it and
133c6a2f467SAtsushi Nemoto 	 * send SIGFPE.
134c6a2f467SAtsushi Nemoto 	 */
135c6a2f467SAtsushi Nemoto 	if (csr & enabled) {
136c6a2f467SAtsushi Nemoto 		csr &= ~enabled;
137c6a2f467SAtsushi Nemoto 		err |= __put_user(csr, fpcsr);
138c6a2f467SAtsushi Nemoto 		sig = SIGFPE;
139c6a2f467SAtsushi Nemoto 	}
140c6a2f467SAtsushi Nemoto 	return err ?: sig;
141c6a2f467SAtsushi Nemoto }
142c6a2f467SAtsushi Nemoto 
143c6a2f467SAtsushi Nemoto static int
144c6a2f467SAtsushi Nemoto check_and_restore_fp_context(struct sigcontext __user *sc)
145c6a2f467SAtsushi Nemoto {
146c6a2f467SAtsushi Nemoto 	int err, sig;
147c6a2f467SAtsushi Nemoto 
148c6a2f467SAtsushi Nemoto 	err = sig = fpcsr_pending(&sc->sc_fpc_csr);
149c6a2f467SAtsushi Nemoto 	if (err > 0)
150c6a2f467SAtsushi Nemoto 		err = 0;
151c6a2f467SAtsushi Nemoto 	err |= restore_fp_context(sc);
152c6a2f467SAtsushi Nemoto 	return err ?: sig;
153c6a2f467SAtsushi Nemoto }
154c6a2f467SAtsushi Nemoto 
155c3fc4ab3SFranck Bui-Huu int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
156c3fc4ab3SFranck Bui-Huu {
157c3fc4ab3SFranck Bui-Huu 	unsigned int used_math;
158c3fc4ab3SFranck Bui-Huu 	unsigned long treg;
159c3fc4ab3SFranck Bui-Huu 	int err = 0;
160c3fc4ab3SFranck Bui-Huu 	int i;
161c3fc4ab3SFranck Bui-Huu 
162c3fc4ab3SFranck Bui-Huu 	/* Always make any pending restarted system calls return -EINTR */
163c3fc4ab3SFranck Bui-Huu 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
164c3fc4ab3SFranck Bui-Huu 
165c3fc4ab3SFranck Bui-Huu 	err |= __get_user(regs->cp0_epc, &sc->sc_pc);
1669693a853SFranck Bui-Huu 
1679693a853SFranck Bui-Huu #ifdef CONFIG_CPU_HAS_SMARTMIPS
1689693a853SFranck Bui-Huu 	err |= __get_user(regs->acx, &sc->sc_acx);
1699693a853SFranck Bui-Huu #endif
170c3fc4ab3SFranck Bui-Huu 	err |= __get_user(regs->hi, &sc->sc_mdhi);
171c3fc4ab3SFranck Bui-Huu 	err |= __get_user(regs->lo, &sc->sc_mdlo);
172c3fc4ab3SFranck Bui-Huu 	if (cpu_has_dsp) {
173c3fc4ab3SFranck Bui-Huu 		err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
174c3fc4ab3SFranck Bui-Huu 		err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
175c3fc4ab3SFranck Bui-Huu 		err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
176c3fc4ab3SFranck Bui-Huu 		err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
177c3fc4ab3SFranck Bui-Huu 		err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
178c3fc4ab3SFranck Bui-Huu 		err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
179c3fc4ab3SFranck Bui-Huu 		err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
180c3fc4ab3SFranck Bui-Huu 	}
181c3fc4ab3SFranck Bui-Huu 
182c3fc4ab3SFranck Bui-Huu 	for (i = 1; i < 32; i++)
183c3fc4ab3SFranck Bui-Huu 		err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
184c3fc4ab3SFranck Bui-Huu 
185c3fc4ab3SFranck Bui-Huu 	err |= __get_user(used_math, &sc->sc_used_math);
186c3fc4ab3SFranck Bui-Huu 	conditional_used_math(used_math);
187c3fc4ab3SFranck Bui-Huu 
18853dc8028SAtsushi Nemoto 	if (used_math) {
189c3fc4ab3SFranck Bui-Huu 		/* restore fpu context if we have used it before */
19053dc8028SAtsushi Nemoto 		own_fpu(0);
19153dc8028SAtsushi Nemoto 		enable_fp_in_kernel();
192c6a2f467SAtsushi Nemoto 		if (!err)
193c6a2f467SAtsushi Nemoto 			err = check_and_restore_fp_context(sc);
19453dc8028SAtsushi Nemoto 		disable_fp_in_kernel();
195c3fc4ab3SFranck Bui-Huu 	} else {
196c3fc4ab3SFranck Bui-Huu 		/* signal handler may have used FPU.  Give it up. */
19753dc8028SAtsushi Nemoto 		lose_fpu(0);
198c3fc4ab3SFranck Bui-Huu 	}
199c3fc4ab3SFranck Bui-Huu 
200c3fc4ab3SFranck Bui-Huu 	return err;
201c3fc4ab3SFranck Bui-Huu }
202c3fc4ab3SFranck Bui-Huu 
203c3fc4ab3SFranck Bui-Huu void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
204c3fc4ab3SFranck Bui-Huu 			  size_t frame_size)
205c3fc4ab3SFranck Bui-Huu {
206c3fc4ab3SFranck Bui-Huu 	unsigned long sp;
207c3fc4ab3SFranck Bui-Huu 
208c3fc4ab3SFranck Bui-Huu 	/* Default to using normal stack */
209c3fc4ab3SFranck Bui-Huu 	sp = regs->regs[29];
210c3fc4ab3SFranck Bui-Huu 
211c3fc4ab3SFranck Bui-Huu 	/*
212c3fc4ab3SFranck Bui-Huu 	 * FPU emulator may have it's own trampoline active just
213c3fc4ab3SFranck Bui-Huu 	 * above the user stack, 16-bytes before the next lowest
214c3fc4ab3SFranck Bui-Huu 	 * 16 byte boundary.  Try to avoid trashing it.
215c3fc4ab3SFranck Bui-Huu 	 */
216c3fc4ab3SFranck Bui-Huu 	sp -= 32;
217c3fc4ab3SFranck Bui-Huu 
218c3fc4ab3SFranck Bui-Huu 	/* This is the X/Open sanctioned signal stack switching.  */
219c3fc4ab3SFranck Bui-Huu 	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
220c3fc4ab3SFranck Bui-Huu 		sp = current->sas_ss_sp + current->sas_ss_size;
221c3fc4ab3SFranck Bui-Huu 
222c3fc4ab3SFranck Bui-Huu 	return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
223c3fc4ab3SFranck Bui-Huu }
224c3fc4ab3SFranck Bui-Huu 
225c3fc4ab3SFranck Bui-Huu int install_sigtramp(unsigned int __user *tramp, unsigned int syscall)
226c3fc4ab3SFranck Bui-Huu {
227c3fc4ab3SFranck Bui-Huu 	int err;
228c3fc4ab3SFranck Bui-Huu 
229c3fc4ab3SFranck Bui-Huu 	/*
230c3fc4ab3SFranck Bui-Huu 	 * Set up the return code ...
231c3fc4ab3SFranck Bui-Huu 	 *
232c3fc4ab3SFranck Bui-Huu 	 *         li      v0, __NR__foo_sigreturn
233c3fc4ab3SFranck Bui-Huu 	 *         syscall
234c3fc4ab3SFranck Bui-Huu 	 */
235c3fc4ab3SFranck Bui-Huu 
236c3fc4ab3SFranck Bui-Huu 	err = __put_user(0x24020000 + syscall, tramp + 0);
237c3fc4ab3SFranck Bui-Huu 	err |= __put_user(0x0000000c         , tramp + 1);
238c3fc4ab3SFranck Bui-Huu 	if (ICACHE_REFILLS_WORKAROUND_WAR) {
239c3fc4ab3SFranck Bui-Huu 		err |= __put_user(0, tramp + 2);
240c3fc4ab3SFranck Bui-Huu 		err |= __put_user(0, tramp + 3);
241c3fc4ab3SFranck Bui-Huu 		err |= __put_user(0, tramp + 4);
242c3fc4ab3SFranck Bui-Huu 		err |= __put_user(0, tramp + 5);
243c3fc4ab3SFranck Bui-Huu 		err |= __put_user(0, tramp + 6);
244c3fc4ab3SFranck Bui-Huu 		err |= __put_user(0, tramp + 7);
245c3fc4ab3SFranck Bui-Huu 	}
246c3fc4ab3SFranck Bui-Huu 	flush_cache_sigtramp((unsigned long) tramp);
247c3fc4ab3SFranck Bui-Huu 
248c3fc4ab3SFranck Bui-Huu 	return err;
249c3fc4ab3SFranck Bui-Huu }
250c3fc4ab3SFranck Bui-Huu 
251c3fc4ab3SFranck Bui-Huu /*
2521da177e4SLinus Torvalds  * Atomically swap in the new signal mask, and wait for a signal.
2531da177e4SLinus Torvalds  */
2541da177e4SLinus Torvalds 
2551da177e4SLinus Torvalds #ifdef CONFIG_TRAD_SIGNALS
256f90080a0SFranck Bui-Huu asmlinkage int sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
2571da177e4SLinus Torvalds {
2587b3e2fc8SRalf Baechle 	sigset_t newset;
259fe00f943SRalf Baechle 	sigset_t __user *uset;
2601da177e4SLinus Torvalds 
261fe00f943SRalf Baechle 	uset = (sigset_t __user *) regs.regs[4];
2621da177e4SLinus Torvalds 	if (copy_from_user(&newset, uset, sizeof(sigset_t)))
2631da177e4SLinus Torvalds 		return -EFAULT;
2641da177e4SLinus Torvalds 	sigdelsetmask(&newset, ~_BLOCKABLE);
2651da177e4SLinus Torvalds 
2661da177e4SLinus Torvalds 	spin_lock_irq(&current->sighand->siglock);
2677b3e2fc8SRalf Baechle 	current->saved_sigmask = current->blocked;
2681da177e4SLinus Torvalds 	current->blocked = newset;
2691da177e4SLinus Torvalds 	recalc_sigpending();
2701da177e4SLinus Torvalds 	spin_unlock_irq(&current->sighand->siglock);
2711da177e4SLinus Torvalds 
2721da177e4SLinus Torvalds 	current->state = TASK_INTERRUPTIBLE;
2731da177e4SLinus Torvalds 	schedule();
2747b3e2fc8SRalf Baechle 	set_thread_flag(TIF_RESTORE_SIGMASK);
2757b3e2fc8SRalf Baechle 	return -ERESTARTNOHAND;
2761da177e4SLinus Torvalds }
2771da177e4SLinus Torvalds #endif
2781da177e4SLinus Torvalds 
279f90080a0SFranck Bui-Huu asmlinkage int sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
2801da177e4SLinus Torvalds {
2817b3e2fc8SRalf Baechle 	sigset_t newset;
282fe00f943SRalf Baechle 	sigset_t __user *unewset;
2831da177e4SLinus Torvalds 	size_t sigsetsize;
2841da177e4SLinus Torvalds 
2851da177e4SLinus Torvalds 	/* XXX Don't preclude handling different sized sigset_t's.  */
2861da177e4SLinus Torvalds 	sigsetsize = regs.regs[5];
2871da177e4SLinus Torvalds 	if (sigsetsize != sizeof(sigset_t))
2881da177e4SLinus Torvalds 		return -EINVAL;
2891da177e4SLinus Torvalds 
290fe00f943SRalf Baechle 	unewset = (sigset_t __user *) regs.regs[4];
2911da177e4SLinus Torvalds 	if (copy_from_user(&newset, unewset, sizeof(newset)))
2921da177e4SLinus Torvalds 		return -EFAULT;
2931da177e4SLinus Torvalds 	sigdelsetmask(&newset, ~_BLOCKABLE);
2941da177e4SLinus Torvalds 
2951da177e4SLinus Torvalds 	spin_lock_irq(&current->sighand->siglock);
2967b3e2fc8SRalf Baechle 	current->saved_sigmask = current->blocked;
2971da177e4SLinus Torvalds 	current->blocked = newset;
2981da177e4SLinus Torvalds 	recalc_sigpending();
2991da177e4SLinus Torvalds 	spin_unlock_irq(&current->sighand->siglock);
3001da177e4SLinus Torvalds 
3011da177e4SLinus Torvalds 	current->state = TASK_INTERRUPTIBLE;
3021da177e4SLinus Torvalds 	schedule();
3037b3e2fc8SRalf Baechle 	set_thread_flag(TIF_RESTORE_SIGMASK);
3047b3e2fc8SRalf Baechle 	return -ERESTARTNOHAND;
3051da177e4SLinus Torvalds }
3061da177e4SLinus Torvalds 
3071da177e4SLinus Torvalds #ifdef CONFIG_TRAD_SIGNALS
3089c6031ccSAtsushi Nemoto asmlinkage int sys_sigaction(int sig, const struct sigaction __user *act,
3099c6031ccSAtsushi Nemoto 	struct sigaction __user *oact)
3101da177e4SLinus Torvalds {
3111da177e4SLinus Torvalds 	struct k_sigaction new_ka, old_ka;
3121da177e4SLinus Torvalds 	int ret;
3131da177e4SLinus Torvalds 	int err = 0;
3141da177e4SLinus Torvalds 
3151da177e4SLinus Torvalds 	if (act) {
3161da177e4SLinus Torvalds 		old_sigset_t mask;
3171da177e4SLinus Torvalds 
3181da177e4SLinus Torvalds 		if (!access_ok(VERIFY_READ, act, sizeof(*act)))
3191da177e4SLinus Torvalds 			return -EFAULT;
3201da177e4SLinus Torvalds 		err |= __get_user(new_ka.sa.sa_handler, &act->sa_handler);
3211da177e4SLinus Torvalds 		err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
3221da177e4SLinus Torvalds 		err |= __get_user(mask, &act->sa_mask.sig[0]);
3231da177e4SLinus Torvalds 		if (err)
3241da177e4SLinus Torvalds 			return -EFAULT;
3251da177e4SLinus Torvalds 
3261da177e4SLinus Torvalds 		siginitset(&new_ka.sa.sa_mask, mask);
3271da177e4SLinus Torvalds 	}
3281da177e4SLinus Torvalds 
3291da177e4SLinus Torvalds 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
3301da177e4SLinus Torvalds 
3311da177e4SLinus Torvalds 	if (!ret && oact) {
3321da177e4SLinus Torvalds 		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
3331da177e4SLinus Torvalds 			return -EFAULT;
3341da177e4SLinus Torvalds 		err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
3351da177e4SLinus Torvalds 		err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler);
3361da177e4SLinus Torvalds 		err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
3371da177e4SLinus Torvalds 		err |= __put_user(0, &oact->sa_mask.sig[1]);
3381da177e4SLinus Torvalds 		err |= __put_user(0, &oact->sa_mask.sig[2]);
3391da177e4SLinus Torvalds 		err |= __put_user(0, &oact->sa_mask.sig[3]);
3401da177e4SLinus Torvalds 		if (err)
3411da177e4SLinus Torvalds 			return -EFAULT;
3421da177e4SLinus Torvalds 	}
3431da177e4SLinus Torvalds 
3441da177e4SLinus Torvalds 	return ret;
3451da177e4SLinus Torvalds }
3461da177e4SLinus Torvalds #endif
3471da177e4SLinus Torvalds 
3481da177e4SLinus Torvalds asmlinkage int sys_sigaltstack(nabi_no_regargs struct pt_regs regs)
3491da177e4SLinus Torvalds {
350fe00f943SRalf Baechle 	const stack_t __user *uss = (const stack_t __user *) regs.regs[4];
351fe00f943SRalf Baechle 	stack_t __user *uoss = (stack_t __user *) regs.regs[5];
3521da177e4SLinus Torvalds 	unsigned long usp = regs.regs[29];
3531da177e4SLinus Torvalds 
3541da177e4SLinus Torvalds 	return do_sigaltstack(uss, uoss, usp);
3551da177e4SLinus Torvalds }
3561da177e4SLinus Torvalds 
3571da177e4SLinus Torvalds #ifdef CONFIG_TRAD_SIGNALS
358f90080a0SFranck Bui-Huu asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs)
3591da177e4SLinus Torvalds {
3609bbf28a3SAtsushi Nemoto 	struct sigframe __user *frame;
3611da177e4SLinus Torvalds 	sigset_t blocked;
362c6a2f467SAtsushi Nemoto 	int sig;
3631da177e4SLinus Torvalds 
3649bbf28a3SAtsushi Nemoto 	frame = (struct sigframe __user *) regs.regs[29];
3651da177e4SLinus Torvalds 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
3661da177e4SLinus Torvalds 		goto badframe;
3671da177e4SLinus Torvalds 	if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
3681da177e4SLinus Torvalds 		goto badframe;
3691da177e4SLinus Torvalds 
3701da177e4SLinus Torvalds 	sigdelsetmask(&blocked, ~_BLOCKABLE);
3711da177e4SLinus Torvalds 	spin_lock_irq(&current->sighand->siglock);
3721da177e4SLinus Torvalds 	current->blocked = blocked;
3731da177e4SLinus Torvalds 	recalc_sigpending();
3741da177e4SLinus Torvalds 	spin_unlock_irq(&current->sighand->siglock);
3751da177e4SLinus Torvalds 
376c6a2f467SAtsushi Nemoto 	sig = restore_sigcontext(&regs, &frame->sf_sc);
377c6a2f467SAtsushi Nemoto 	if (sig < 0)
3781da177e4SLinus Torvalds 		goto badframe;
379c6a2f467SAtsushi Nemoto 	else if (sig)
380c6a2f467SAtsushi Nemoto 		force_sig(sig, current);
3811da177e4SLinus Torvalds 
3821da177e4SLinus Torvalds 	/*
3831da177e4SLinus Torvalds 	 * Don't let your children do this ...
3841da177e4SLinus Torvalds 	 */
3851da177e4SLinus Torvalds 	__asm__ __volatile__(
3861da177e4SLinus Torvalds 		"move\t$29, %0\n\t"
3871da177e4SLinus Torvalds 		"j\tsyscall_exit"
3881da177e4SLinus Torvalds 		:/* no outputs */
3891da177e4SLinus Torvalds 		:"r" (&regs));
3901da177e4SLinus Torvalds 	/* Unreached */
3911da177e4SLinus Torvalds 
3921da177e4SLinus Torvalds badframe:
3931da177e4SLinus Torvalds 	force_sig(SIGSEGV, current);
3941da177e4SLinus Torvalds }
395e50c0a8fSRalf Baechle #endif /* CONFIG_TRAD_SIGNALS */
3961da177e4SLinus Torvalds 
397f90080a0SFranck Bui-Huu asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
3981da177e4SLinus Torvalds {
3999bbf28a3SAtsushi Nemoto 	struct rt_sigframe __user *frame;
4001da177e4SLinus Torvalds 	sigset_t set;
4011da177e4SLinus Torvalds 	stack_t st;
402c6a2f467SAtsushi Nemoto 	int sig;
4031da177e4SLinus Torvalds 
4049bbf28a3SAtsushi Nemoto 	frame = (struct rt_sigframe __user *) regs.regs[29];
4051da177e4SLinus Torvalds 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
4061da177e4SLinus Torvalds 		goto badframe;
4071da177e4SLinus Torvalds 	if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
4081da177e4SLinus Torvalds 		goto badframe;
4091da177e4SLinus Torvalds 
4101da177e4SLinus Torvalds 	sigdelsetmask(&set, ~_BLOCKABLE);
4111da177e4SLinus Torvalds 	spin_lock_irq(&current->sighand->siglock);
4121da177e4SLinus Torvalds 	current->blocked = set;
4131da177e4SLinus Torvalds 	recalc_sigpending();
4141da177e4SLinus Torvalds 	spin_unlock_irq(&current->sighand->siglock);
4151da177e4SLinus Torvalds 
416c6a2f467SAtsushi Nemoto 	sig = restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext);
417c6a2f467SAtsushi Nemoto 	if (sig < 0)
4181da177e4SLinus Torvalds 		goto badframe;
419c6a2f467SAtsushi Nemoto 	else if (sig)
420c6a2f467SAtsushi Nemoto 		force_sig(sig, current);
4211da177e4SLinus Torvalds 
4221da177e4SLinus Torvalds 	if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st)))
4231da177e4SLinus Torvalds 		goto badframe;
4241da177e4SLinus Torvalds 	/* It is more difficult to avoid calling this function than to
4251da177e4SLinus Torvalds 	   call it and ignore errors.  */
4269bbf28a3SAtsushi Nemoto 	do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
4271da177e4SLinus Torvalds 
4281da177e4SLinus Torvalds 	/*
4291da177e4SLinus Torvalds 	 * Don't let your children do this ...
4301da177e4SLinus Torvalds 	 */
4311da177e4SLinus Torvalds 	__asm__ __volatile__(
4321da177e4SLinus Torvalds 		"move\t$29, %0\n\t"
4331da177e4SLinus Torvalds 		"j\tsyscall_exit"
4341da177e4SLinus Torvalds 		:/* no outputs */
4351da177e4SLinus Torvalds 		:"r" (&regs));
4361da177e4SLinus Torvalds 	/* Unreached */
4371da177e4SLinus Torvalds 
4381da177e4SLinus Torvalds badframe:
4391da177e4SLinus Torvalds 	force_sig(SIGSEGV, current);
4401da177e4SLinus Torvalds }
4411da177e4SLinus Torvalds 
4421da177e4SLinus Torvalds #ifdef CONFIG_TRAD_SIGNALS
443151fd6acSRalf Baechle static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
4441da177e4SLinus Torvalds 	int signr, sigset_t *set)
4451da177e4SLinus Torvalds {
4469bbf28a3SAtsushi Nemoto 	struct sigframe __user *frame;
4471da177e4SLinus Torvalds 	int err = 0;
4481da177e4SLinus Torvalds 
4491da177e4SLinus Torvalds 	frame = get_sigframe(ka, regs, sizeof(*frame));
4501da177e4SLinus Torvalds 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
4511da177e4SLinus Torvalds 		goto give_sigsegv;
4521da177e4SLinus Torvalds 
453601dde45SFranck Bui-Huu 	err |= install_sigtramp(frame->sf_code, __NR_sigreturn);
4541da177e4SLinus Torvalds 
4551da177e4SLinus Torvalds 	err |= setup_sigcontext(regs, &frame->sf_sc);
4561da177e4SLinus Torvalds 	err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
4571da177e4SLinus Torvalds 	if (err)
4581da177e4SLinus Torvalds 		goto give_sigsegv;
4591da177e4SLinus Torvalds 
4601da177e4SLinus Torvalds 	/*
4611da177e4SLinus Torvalds 	 * Arguments to signal handler:
4621da177e4SLinus Torvalds 	 *
4631da177e4SLinus Torvalds 	 *   a0 = signal number
4641da177e4SLinus Torvalds 	 *   a1 = 0 (should be cause)
4651da177e4SLinus Torvalds 	 *   a2 = pointer to struct sigcontext
4661da177e4SLinus Torvalds 	 *
4671da177e4SLinus Torvalds 	 * $25 and c0_epc point to the signal handler, $29 points to the
4681da177e4SLinus Torvalds 	 * struct sigframe.
4691da177e4SLinus Torvalds 	 */
4701da177e4SLinus Torvalds 	regs->regs[ 4] = signr;
4711da177e4SLinus Torvalds 	regs->regs[ 5] = 0;
4721da177e4SLinus Torvalds 	regs->regs[ 6] = (unsigned long) &frame->sf_sc;
4731da177e4SLinus Torvalds 	regs->regs[29] = (unsigned long) frame;
4741da177e4SLinus Torvalds 	regs->regs[31] = (unsigned long) frame->sf_code;
4751da177e4SLinus Torvalds 	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
4761da177e4SLinus Torvalds 
477722bb63dSFranck Bui-Huu 	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
4781da177e4SLinus Torvalds 	       current->comm, current->pid,
479722bb63dSFranck Bui-Huu 	       frame, regs->cp0_epc, regs->regs[31]);
4807b3e2fc8SRalf Baechle 	return 0;
4811da177e4SLinus Torvalds 
4821da177e4SLinus Torvalds give_sigsegv:
4831da177e4SLinus Torvalds 	force_sigsegv(signr, current);
4847b3e2fc8SRalf Baechle 	return -EFAULT;
4851da177e4SLinus Torvalds }
4861da177e4SLinus Torvalds #endif
4871da177e4SLinus Torvalds 
488151fd6acSRalf Baechle static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
4891da177e4SLinus Torvalds 	int signr, sigset_t *set, siginfo_t *info)
4901da177e4SLinus Torvalds {
4919bbf28a3SAtsushi Nemoto 	struct rt_sigframe __user *frame;
4921da177e4SLinus Torvalds 	int err = 0;
4931da177e4SLinus Torvalds 
4941da177e4SLinus Torvalds 	frame = get_sigframe(ka, regs, sizeof(*frame));
4951da177e4SLinus Torvalds 	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
4961da177e4SLinus Torvalds 		goto give_sigsegv;
4971da177e4SLinus Torvalds 
498601dde45SFranck Bui-Huu 	err |= install_sigtramp(frame->rs_code, __NR_rt_sigreturn);
4991da177e4SLinus Torvalds 
5001da177e4SLinus Torvalds 	/* Create siginfo.  */
5011da177e4SLinus Torvalds 	err |= copy_siginfo_to_user(&frame->rs_info, info);
5021da177e4SLinus Torvalds 
5031da177e4SLinus Torvalds 	/* Create the ucontext.  */
5041da177e4SLinus Torvalds 	err |= __put_user(0, &frame->rs_uc.uc_flags);
5055665a0acSAtsushi Nemoto 	err |= __put_user(NULL, &frame->rs_uc.uc_link);
5069c6031ccSAtsushi Nemoto 	err |= __put_user((void __user *)current->sas_ss_sp,
5071da177e4SLinus Torvalds 	                  &frame->rs_uc.uc_stack.ss_sp);
5081da177e4SLinus Torvalds 	err |= __put_user(sas_ss_flags(regs->regs[29]),
5091da177e4SLinus Torvalds 	                  &frame->rs_uc.uc_stack.ss_flags);
5101da177e4SLinus Torvalds 	err |= __put_user(current->sas_ss_size,
5111da177e4SLinus Torvalds 	                  &frame->rs_uc.uc_stack.ss_size);
5121da177e4SLinus Torvalds 	err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
5131da177e4SLinus Torvalds 	err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
5141da177e4SLinus Torvalds 
5151da177e4SLinus Torvalds 	if (err)
5161da177e4SLinus Torvalds 		goto give_sigsegv;
5171da177e4SLinus Torvalds 
5181da177e4SLinus Torvalds 	/*
5191da177e4SLinus Torvalds 	 * Arguments to signal handler:
5201da177e4SLinus Torvalds 	 *
5211da177e4SLinus Torvalds 	 *   a0 = signal number
5221da177e4SLinus Torvalds 	 *   a1 = 0 (should be cause)
5231da177e4SLinus Torvalds 	 *   a2 = pointer to ucontext
5241da177e4SLinus Torvalds 	 *
5251da177e4SLinus Torvalds 	 * $25 and c0_epc point to the signal handler, $29 points to
5261da177e4SLinus Torvalds 	 * the struct rt_sigframe.
5271da177e4SLinus Torvalds 	 */
5281da177e4SLinus Torvalds 	regs->regs[ 4] = signr;
5291da177e4SLinus Torvalds 	regs->regs[ 5] = (unsigned long) &frame->rs_info;
5301da177e4SLinus Torvalds 	regs->regs[ 6] = (unsigned long) &frame->rs_uc;
5311da177e4SLinus Torvalds 	regs->regs[29] = (unsigned long) frame;
5321da177e4SLinus Torvalds 	regs->regs[31] = (unsigned long) frame->rs_code;
5331da177e4SLinus Torvalds 	regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
5341da177e4SLinus Torvalds 
535722bb63dSFranck Bui-Huu 	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
5361da177e4SLinus Torvalds 	       current->comm, current->pid,
5371da177e4SLinus Torvalds 	       frame, regs->cp0_epc, regs->regs[31]);
538722bb63dSFranck Bui-Huu 
5397b3e2fc8SRalf Baechle 	return 0;
5401da177e4SLinus Torvalds 
5411da177e4SLinus Torvalds give_sigsegv:
5421da177e4SLinus Torvalds 	force_sigsegv(signr, current);
5437b3e2fc8SRalf Baechle 	return -EFAULT;
5441da177e4SLinus Torvalds }
5451da177e4SLinus Torvalds 
546151fd6acSRalf Baechle struct mips_abi mips_abi = {
547151fd6acSRalf Baechle #ifdef CONFIG_TRAD_SIGNALS
548151fd6acSRalf Baechle 	.setup_frame	= setup_frame,
549151fd6acSRalf Baechle #endif
550151fd6acSRalf Baechle 	.setup_rt_frame	= setup_rt_frame,
551151fd6acSRalf Baechle 	.restart	= __NR_restart_syscall
552151fd6acSRalf Baechle };
553151fd6acSRalf Baechle 
554e692eb30SFranck Bui-Huu static int handle_signal(unsigned long sig, siginfo_t *info,
5551da177e4SLinus Torvalds 	struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
5561da177e4SLinus Torvalds {
557129bc8f7SRalf Baechle 	int ret;
558129bc8f7SRalf Baechle 
5591da177e4SLinus Torvalds 	switch(regs->regs[0]) {
5601da177e4SLinus Torvalds 	case ERESTART_RESTARTBLOCK:
5611da177e4SLinus Torvalds 	case ERESTARTNOHAND:
5621da177e4SLinus Torvalds 		regs->regs[2] = EINTR;
5631da177e4SLinus Torvalds 		break;
5641da177e4SLinus Torvalds 	case ERESTARTSYS:
5651da177e4SLinus Torvalds 		if (!(ka->sa.sa_flags & SA_RESTART)) {
5661da177e4SLinus Torvalds 			regs->regs[2] = EINTR;
5671da177e4SLinus Torvalds 			break;
5681da177e4SLinus Torvalds 		}
5691da177e4SLinus Torvalds 	/* fallthrough */
5701da177e4SLinus Torvalds 	case ERESTARTNOINTR:		/* Userland will reload $v0.  */
5711da177e4SLinus Torvalds 		regs->regs[7] = regs->regs[26];
5721da177e4SLinus Torvalds 		regs->cp0_epc -= 8;
5731da177e4SLinus Torvalds 	}
5741da177e4SLinus Torvalds 
5751da177e4SLinus Torvalds 	regs->regs[0] = 0;		/* Don't deal with this again.  */
5761da177e4SLinus Torvalds 
577e50c0a8fSRalf Baechle 	if (sig_uses_siginfo(ka))
578129bc8f7SRalf Baechle 		ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
5791da177e4SLinus Torvalds 	else
580129bc8f7SRalf Baechle 		ret = current->thread.abi->setup_frame(ka, regs, sig, oldset);
5811da177e4SLinus Torvalds 
5821da177e4SLinus Torvalds 	spin_lock_irq(&current->sighand->siglock);
5831da177e4SLinus Torvalds 	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
58469be8f18SSteven Rostedt 	if (!(ka->sa.sa_flags & SA_NODEFER))
5851da177e4SLinus Torvalds 		sigaddset(&current->blocked,sig);
5861da177e4SLinus Torvalds 	recalc_sigpending();
5871da177e4SLinus Torvalds 	spin_unlock_irq(&current->sighand->siglock);
588129bc8f7SRalf Baechle 
589129bc8f7SRalf Baechle 	return ret;
5901da177e4SLinus Torvalds }
5911da177e4SLinus Torvalds 
592151fd6acSRalf Baechle static void do_signal(struct pt_regs *regs)
5931da177e4SLinus Torvalds {
5941da177e4SLinus Torvalds 	struct k_sigaction ka;
5957b3e2fc8SRalf Baechle 	sigset_t *oldset;
5961da177e4SLinus Torvalds 	siginfo_t info;
5971da177e4SLinus Torvalds 	int signr;
5981da177e4SLinus Torvalds 
5991da177e4SLinus Torvalds 	/*
6001da177e4SLinus Torvalds 	 * We want the common case to go fast, which is why we may in certain
6011da177e4SLinus Torvalds 	 * cases get here from kernel mode. Just return without doing anything
6021da177e4SLinus Torvalds 	 * if so.
6031da177e4SLinus Torvalds 	 */
6041da177e4SLinus Torvalds 	if (!user_mode(regs))
60540ac5d47SRalf Baechle 		return;
6061da177e4SLinus Torvalds 
6077b3e2fc8SRalf Baechle 	if (test_thread_flag(TIF_RESTORE_SIGMASK))
6087b3e2fc8SRalf Baechle 		oldset = &current->saved_sigmask;
6097b3e2fc8SRalf Baechle 	else
6101da177e4SLinus Torvalds 		oldset = &current->blocked;
6111da177e4SLinus Torvalds 
6121da177e4SLinus Torvalds 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
6137b3e2fc8SRalf Baechle 	if (signr > 0) {
6147b3e2fc8SRalf Baechle 		/* Whee!  Actually deliver the signal.  */
6157b3e2fc8SRalf Baechle 		if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
6167b3e2fc8SRalf Baechle 			/*
6177b3e2fc8SRalf Baechle 			 * A signal was successfully delivered; the saved
6187b3e2fc8SRalf Baechle 			 * sigmask will have been stored in the signal frame,
6197b3e2fc8SRalf Baechle 			 * and will be restored by sigreturn, so we can simply
6207b3e2fc8SRalf Baechle 			 * clear the TIF_RESTORE_SIGMASK flag.
6217b3e2fc8SRalf Baechle 			 */
6227b3e2fc8SRalf Baechle 			if (test_thread_flag(TIF_RESTORE_SIGMASK))
6237b3e2fc8SRalf Baechle 				clear_thread_flag(TIF_RESTORE_SIGMASK);
6247b3e2fc8SRalf Baechle 		}
62545887e12SRalf Baechle 
62645887e12SRalf Baechle 		return;
6277b3e2fc8SRalf Baechle 	}
6281da177e4SLinus Torvalds 
6291da177e4SLinus Torvalds 	/*
6301da177e4SLinus Torvalds 	 * Who's code doesn't conform to the restartable syscall convention
6311da177e4SLinus Torvalds 	 * dies here!!!  The li instruction, a single machine instruction,
6321da177e4SLinus Torvalds 	 * must directly be followed by the syscall instruction.
6331da177e4SLinus Torvalds 	 */
6341da177e4SLinus Torvalds 	if (regs->regs[0]) {
6351da177e4SLinus Torvalds 		if (regs->regs[2] == ERESTARTNOHAND ||
6361da177e4SLinus Torvalds 		    regs->regs[2] == ERESTARTSYS ||
6371da177e4SLinus Torvalds 		    regs->regs[2] == ERESTARTNOINTR) {
6381da177e4SLinus Torvalds 			regs->regs[7] = regs->regs[26];
6391da177e4SLinus Torvalds 			regs->cp0_epc -= 8;
6401da177e4SLinus Torvalds 		}
6411da177e4SLinus Torvalds 		if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
642151fd6acSRalf Baechle 			regs->regs[2] = current->thread.abi->restart;
6431da177e4SLinus Torvalds 			regs->regs[7] = regs->regs[26];
6441da177e4SLinus Torvalds 			regs->cp0_epc -= 4;
6451da177e4SLinus Torvalds 		}
64613fdd31aSRalf Baechle 		regs->regs[0] = 0;	/* Don't deal with this again.  */
6471da177e4SLinus Torvalds 	}
6487b3e2fc8SRalf Baechle 
6497b3e2fc8SRalf Baechle 	/*
6507b3e2fc8SRalf Baechle 	 * If there's no signal to deliver, we just put the saved sigmask
6517b3e2fc8SRalf Baechle 	 * back
6527b3e2fc8SRalf Baechle 	 */
6537b3e2fc8SRalf Baechle 	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
6547b3e2fc8SRalf Baechle 		clear_thread_flag(TIF_RESTORE_SIGMASK);
6557b3e2fc8SRalf Baechle 		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
6567b3e2fc8SRalf Baechle 	}
6571da177e4SLinus Torvalds }
6581da177e4SLinus Torvalds 
6591da177e4SLinus Torvalds /*
6601da177e4SLinus Torvalds  * notification of userspace execution resumption
6617b3e2fc8SRalf Baechle  * - triggered by the TIF_WORK_MASK flags
6621da177e4SLinus Torvalds  */
6637b3e2fc8SRalf Baechle asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
6641da177e4SLinus Torvalds 	__u32 thread_info_flags)
6651da177e4SLinus Torvalds {
6661da177e4SLinus Torvalds 	/* deal with pending signal delivery */
6677b3e2fc8SRalf Baechle 	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
668151fd6acSRalf Baechle 		do_signal(regs);
6691da177e4SLinus Torvalds }
670