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/kernel.h> 161da177e4SLinus Torvalds #include <linux/signal.h> 171da177e4SLinus Torvalds #include <linux/errno.h> 181da177e4SLinus Torvalds #include <linux/wait.h> 191da177e4SLinus Torvalds #include <linux/ptrace.h> 201da177e4SLinus Torvalds #include <linux/unistd.h> 211da177e4SLinus Torvalds #include <linux/compiler.h> 22dbda6ac0SRalf Baechle #include <linux/syscalls.h> 23faea6234SAtsushi Nemoto #include <linux/uaccess.h> 241da177e4SLinus Torvalds 25e50c0a8fSRalf Baechle #include <asm/abi.h> 261da177e4SLinus Torvalds #include <asm/asm.h> 271da177e4SLinus Torvalds #include <linux/bitops.h> 281da177e4SLinus Torvalds #include <asm/cacheflush.h> 291da177e4SLinus Torvalds #include <asm/fpu.h> 301da177e4SLinus Torvalds #include <asm/sim.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 */ 81faea6234SAtsushi Nemoto static int protected_save_fp_context(struct sigcontext __user *sc) 82faea6234SAtsushi Nemoto { 83faea6234SAtsushi Nemoto int err; 84faea6234SAtsushi Nemoto while (1) { 85faea6234SAtsushi Nemoto lock_fpu_owner(); 86faea6234SAtsushi Nemoto own_fpu_inatomic(1); 87faea6234SAtsushi Nemoto err = save_fp_context(sc); /* this might fail */ 88faea6234SAtsushi Nemoto unlock_fpu_owner(); 89faea6234SAtsushi Nemoto if (likely(!err)) 90faea6234SAtsushi Nemoto break; 91faea6234SAtsushi Nemoto /* touch the sigcontext and try again */ 92faea6234SAtsushi Nemoto err = __put_user(0, &sc->sc_fpregs[0]) | 93faea6234SAtsushi Nemoto __put_user(0, &sc->sc_fpregs[31]) | 94faea6234SAtsushi Nemoto __put_user(0, &sc->sc_fpc_csr); 95faea6234SAtsushi Nemoto if (err) 96faea6234SAtsushi Nemoto break; /* really bad sigcontext */ 97faea6234SAtsushi Nemoto } 98faea6234SAtsushi Nemoto return err; 99faea6234SAtsushi Nemoto } 100faea6234SAtsushi Nemoto 101faea6234SAtsushi Nemoto static int protected_restore_fp_context(struct sigcontext __user *sc) 102faea6234SAtsushi Nemoto { 103faea6234SAtsushi Nemoto int err, tmp; 104faea6234SAtsushi Nemoto while (1) { 105faea6234SAtsushi Nemoto lock_fpu_owner(); 106faea6234SAtsushi Nemoto own_fpu_inatomic(0); 107faea6234SAtsushi Nemoto err = restore_fp_context(sc); /* this might fail */ 108faea6234SAtsushi Nemoto unlock_fpu_owner(); 109faea6234SAtsushi Nemoto if (likely(!err)) 110faea6234SAtsushi Nemoto break; 111faea6234SAtsushi Nemoto /* touch the sigcontext and try again */ 112faea6234SAtsushi Nemoto err = __get_user(tmp, &sc->sc_fpregs[0]) | 113faea6234SAtsushi Nemoto __get_user(tmp, &sc->sc_fpregs[31]) | 114faea6234SAtsushi Nemoto __get_user(tmp, &sc->sc_fpc_csr); 115faea6234SAtsushi Nemoto if (err) 116faea6234SAtsushi Nemoto break; /* really bad sigcontext */ 117faea6234SAtsushi Nemoto } 118faea6234SAtsushi Nemoto return err; 119faea6234SAtsushi Nemoto } 120faea6234SAtsushi Nemoto 121c3fc4ab3SFranck Bui-Huu int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) 122c3fc4ab3SFranck Bui-Huu { 123c3fc4ab3SFranck Bui-Huu int err = 0; 124c3fc4ab3SFranck Bui-Huu int i; 12553dc8028SAtsushi Nemoto unsigned int used_math; 126c3fc4ab3SFranck Bui-Huu 127c3fc4ab3SFranck Bui-Huu err |= __put_user(regs->cp0_epc, &sc->sc_pc); 128c3fc4ab3SFranck Bui-Huu 129c3fc4ab3SFranck Bui-Huu err |= __put_user(0, &sc->sc_regs[0]); 130c3fc4ab3SFranck Bui-Huu for (i = 1; i < 32; i++) 131c3fc4ab3SFranck Bui-Huu err |= __put_user(regs->regs[i], &sc->sc_regs[i]); 132c3fc4ab3SFranck Bui-Huu 1339693a853SFranck Bui-Huu #ifdef CONFIG_CPU_HAS_SMARTMIPS 1349693a853SFranck Bui-Huu err |= __put_user(regs->acx, &sc->sc_acx); 1359693a853SFranck Bui-Huu #endif 136c3fc4ab3SFranck Bui-Huu err |= __put_user(regs->hi, &sc->sc_mdhi); 137c3fc4ab3SFranck Bui-Huu err |= __put_user(regs->lo, &sc->sc_mdlo); 138c3fc4ab3SFranck Bui-Huu if (cpu_has_dsp) { 139c3fc4ab3SFranck Bui-Huu err |= __put_user(mfhi1(), &sc->sc_hi1); 140c3fc4ab3SFranck Bui-Huu err |= __put_user(mflo1(), &sc->sc_lo1); 141c3fc4ab3SFranck Bui-Huu err |= __put_user(mfhi2(), &sc->sc_hi2); 142c3fc4ab3SFranck Bui-Huu err |= __put_user(mflo2(), &sc->sc_lo2); 143c3fc4ab3SFranck Bui-Huu err |= __put_user(mfhi3(), &sc->sc_hi3); 144c3fc4ab3SFranck Bui-Huu err |= __put_user(mflo3(), &sc->sc_lo3); 145c3fc4ab3SFranck Bui-Huu err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); 146c3fc4ab3SFranck Bui-Huu } 147c3fc4ab3SFranck Bui-Huu 14853dc8028SAtsushi Nemoto used_math = !!used_math(); 14953dc8028SAtsushi Nemoto err |= __put_user(used_math, &sc->sc_used_math); 150c3fc4ab3SFranck Bui-Huu 15153dc8028SAtsushi Nemoto if (used_math) { 152c3fc4ab3SFranck Bui-Huu /* 153c3fc4ab3SFranck Bui-Huu * Save FPU state to signal context. Signal handler 154c3fc4ab3SFranck Bui-Huu * will "inherit" current FPU state. 155c3fc4ab3SFranck Bui-Huu */ 156faea6234SAtsushi Nemoto err |= protected_save_fp_context(sc); 157c3fc4ab3SFranck Bui-Huu } 158c3fc4ab3SFranck Bui-Huu return err; 159c3fc4ab3SFranck Bui-Huu } 160c3fc4ab3SFranck Bui-Huu 161c6a2f467SAtsushi Nemoto int fpcsr_pending(unsigned int __user *fpcsr) 162c6a2f467SAtsushi Nemoto { 163c6a2f467SAtsushi Nemoto int err, sig = 0; 164c6a2f467SAtsushi Nemoto unsigned int csr, enabled; 165c6a2f467SAtsushi Nemoto 166c6a2f467SAtsushi Nemoto err = __get_user(csr, fpcsr); 167c6a2f467SAtsushi Nemoto enabled = FPU_CSR_UNI_X | ((csr & FPU_CSR_ALL_E) << 5); 168c6a2f467SAtsushi Nemoto /* 169c6a2f467SAtsushi Nemoto * If the signal handler set some FPU exceptions, clear it and 170c6a2f467SAtsushi Nemoto * send SIGFPE. 171c6a2f467SAtsushi Nemoto */ 172c6a2f467SAtsushi Nemoto if (csr & enabled) { 173c6a2f467SAtsushi Nemoto csr &= ~enabled; 174c6a2f467SAtsushi Nemoto err |= __put_user(csr, fpcsr); 175c6a2f467SAtsushi Nemoto sig = SIGFPE; 176c6a2f467SAtsushi Nemoto } 177c6a2f467SAtsushi Nemoto return err ?: sig; 178c6a2f467SAtsushi Nemoto } 179c6a2f467SAtsushi Nemoto 180c6a2f467SAtsushi Nemoto static int 181c6a2f467SAtsushi Nemoto check_and_restore_fp_context(struct sigcontext __user *sc) 182c6a2f467SAtsushi Nemoto { 183c6a2f467SAtsushi Nemoto int err, sig; 184c6a2f467SAtsushi Nemoto 185c6a2f467SAtsushi Nemoto err = sig = fpcsr_pending(&sc->sc_fpc_csr); 186c6a2f467SAtsushi Nemoto if (err > 0) 187c6a2f467SAtsushi Nemoto err = 0; 188faea6234SAtsushi Nemoto err |= protected_restore_fp_context(sc); 189c6a2f467SAtsushi Nemoto return err ?: sig; 190c6a2f467SAtsushi Nemoto } 191c6a2f467SAtsushi Nemoto 192c3fc4ab3SFranck Bui-Huu int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) 193c3fc4ab3SFranck Bui-Huu { 194c3fc4ab3SFranck Bui-Huu unsigned int used_math; 195c3fc4ab3SFranck Bui-Huu unsigned long treg; 196c3fc4ab3SFranck Bui-Huu int err = 0; 197c3fc4ab3SFranck Bui-Huu int i; 198c3fc4ab3SFranck Bui-Huu 199c3fc4ab3SFranck Bui-Huu /* Always make any pending restarted system calls return -EINTR */ 200c3fc4ab3SFranck Bui-Huu current_thread_info()->restart_block.fn = do_no_restart_syscall; 201c3fc4ab3SFranck Bui-Huu 202c3fc4ab3SFranck Bui-Huu err |= __get_user(regs->cp0_epc, &sc->sc_pc); 2039693a853SFranck Bui-Huu 2049693a853SFranck Bui-Huu #ifdef CONFIG_CPU_HAS_SMARTMIPS 2059693a853SFranck Bui-Huu err |= __get_user(regs->acx, &sc->sc_acx); 2069693a853SFranck Bui-Huu #endif 207c3fc4ab3SFranck Bui-Huu err |= __get_user(regs->hi, &sc->sc_mdhi); 208c3fc4ab3SFranck Bui-Huu err |= __get_user(regs->lo, &sc->sc_mdlo); 209c3fc4ab3SFranck Bui-Huu if (cpu_has_dsp) { 210c3fc4ab3SFranck Bui-Huu err |= __get_user(treg, &sc->sc_hi1); mthi1(treg); 211c3fc4ab3SFranck Bui-Huu err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg); 212c3fc4ab3SFranck Bui-Huu err |= __get_user(treg, &sc->sc_hi2); mthi2(treg); 213c3fc4ab3SFranck Bui-Huu err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg); 214c3fc4ab3SFranck Bui-Huu err |= __get_user(treg, &sc->sc_hi3); mthi3(treg); 215c3fc4ab3SFranck Bui-Huu err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg); 216c3fc4ab3SFranck Bui-Huu err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK); 217c3fc4ab3SFranck Bui-Huu } 218c3fc4ab3SFranck Bui-Huu 219c3fc4ab3SFranck Bui-Huu for (i = 1; i < 32; i++) 220c3fc4ab3SFranck Bui-Huu err |= __get_user(regs->regs[i], &sc->sc_regs[i]); 221c3fc4ab3SFranck Bui-Huu 222c3fc4ab3SFranck Bui-Huu err |= __get_user(used_math, &sc->sc_used_math); 223c3fc4ab3SFranck Bui-Huu conditional_used_math(used_math); 224c3fc4ab3SFranck Bui-Huu 22553dc8028SAtsushi Nemoto if (used_math) { 226c3fc4ab3SFranck Bui-Huu /* restore fpu context if we have used it before */ 227c6a2f467SAtsushi Nemoto if (!err) 228c6a2f467SAtsushi Nemoto err = check_and_restore_fp_context(sc); 229c3fc4ab3SFranck Bui-Huu } else { 230c3fc4ab3SFranck Bui-Huu /* signal handler may have used FPU. Give it up. */ 23153dc8028SAtsushi Nemoto lose_fpu(0); 232c3fc4ab3SFranck Bui-Huu } 233c3fc4ab3SFranck Bui-Huu 234c3fc4ab3SFranck Bui-Huu return err; 235c3fc4ab3SFranck Bui-Huu } 236c3fc4ab3SFranck Bui-Huu 237c3fc4ab3SFranck Bui-Huu void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, 238c3fc4ab3SFranck Bui-Huu size_t frame_size) 239c3fc4ab3SFranck Bui-Huu { 240c3fc4ab3SFranck Bui-Huu unsigned long sp; 241c3fc4ab3SFranck Bui-Huu 242c3fc4ab3SFranck Bui-Huu /* Default to using normal stack */ 243c3fc4ab3SFranck Bui-Huu sp = regs->regs[29]; 244c3fc4ab3SFranck Bui-Huu 245c3fc4ab3SFranck Bui-Huu /* 246c3fc4ab3SFranck Bui-Huu * FPU emulator may have it's own trampoline active just 247c3fc4ab3SFranck Bui-Huu * above the user stack, 16-bytes before the next lowest 248c3fc4ab3SFranck Bui-Huu * 16 byte boundary. Try to avoid trashing it. 249c3fc4ab3SFranck Bui-Huu */ 250c3fc4ab3SFranck Bui-Huu sp -= 32; 251c3fc4ab3SFranck Bui-Huu 252c3fc4ab3SFranck Bui-Huu /* This is the X/Open sanctioned signal stack switching. */ 253c3fc4ab3SFranck Bui-Huu if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) 254c3fc4ab3SFranck Bui-Huu sp = current->sas_ss_sp + current->sas_ss_size; 255c3fc4ab3SFranck Bui-Huu 256c3fc4ab3SFranck Bui-Huu return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK)); 257c3fc4ab3SFranck Bui-Huu } 258c3fc4ab3SFranck Bui-Huu 259c3fc4ab3SFranck Bui-Huu int install_sigtramp(unsigned int __user *tramp, unsigned int syscall) 260c3fc4ab3SFranck Bui-Huu { 261c3fc4ab3SFranck Bui-Huu int err; 262c3fc4ab3SFranck Bui-Huu 263c3fc4ab3SFranck Bui-Huu /* 264c3fc4ab3SFranck Bui-Huu * Set up the return code ... 265c3fc4ab3SFranck Bui-Huu * 266c3fc4ab3SFranck Bui-Huu * li v0, __NR__foo_sigreturn 267c3fc4ab3SFranck Bui-Huu * syscall 268c3fc4ab3SFranck Bui-Huu */ 269c3fc4ab3SFranck Bui-Huu 270c3fc4ab3SFranck Bui-Huu err = __put_user(0x24020000 + syscall, tramp + 0); 271c3fc4ab3SFranck Bui-Huu err |= __put_user(0x0000000c , tramp + 1); 272c3fc4ab3SFranck Bui-Huu if (ICACHE_REFILLS_WORKAROUND_WAR) { 273c3fc4ab3SFranck Bui-Huu err |= __put_user(0, tramp + 2); 274c3fc4ab3SFranck Bui-Huu err |= __put_user(0, tramp + 3); 275c3fc4ab3SFranck Bui-Huu err |= __put_user(0, tramp + 4); 276c3fc4ab3SFranck Bui-Huu err |= __put_user(0, tramp + 5); 277c3fc4ab3SFranck Bui-Huu err |= __put_user(0, tramp + 6); 278c3fc4ab3SFranck Bui-Huu err |= __put_user(0, tramp + 7); 279c3fc4ab3SFranck Bui-Huu } 280c3fc4ab3SFranck Bui-Huu flush_cache_sigtramp((unsigned long) tramp); 281c3fc4ab3SFranck Bui-Huu 282c3fc4ab3SFranck Bui-Huu return err; 283c3fc4ab3SFranck Bui-Huu } 284c3fc4ab3SFranck Bui-Huu 285c3fc4ab3SFranck Bui-Huu /* 2861da177e4SLinus Torvalds * Atomically swap in the new signal mask, and wait for a signal. 2871da177e4SLinus Torvalds */ 2881da177e4SLinus Torvalds 2891da177e4SLinus Torvalds #ifdef CONFIG_TRAD_SIGNALS 290f90080a0SFranck Bui-Huu asmlinkage int sys_sigsuspend(nabi_no_regargs struct pt_regs regs) 2911da177e4SLinus Torvalds { 2927b3e2fc8SRalf Baechle sigset_t newset; 293fe00f943SRalf Baechle sigset_t __user *uset; 2941da177e4SLinus Torvalds 295fe00f943SRalf Baechle uset = (sigset_t __user *) regs.regs[4]; 2961da177e4SLinus Torvalds if (copy_from_user(&newset, uset, sizeof(sigset_t))) 2971da177e4SLinus Torvalds return -EFAULT; 2981da177e4SLinus Torvalds sigdelsetmask(&newset, ~_BLOCKABLE); 2991da177e4SLinus Torvalds 3001da177e4SLinus Torvalds spin_lock_irq(¤t->sighand->siglock); 3017b3e2fc8SRalf Baechle current->saved_sigmask = current->blocked; 3021da177e4SLinus Torvalds current->blocked = newset; 3031da177e4SLinus Torvalds recalc_sigpending(); 3041da177e4SLinus Torvalds spin_unlock_irq(¤t->sighand->siglock); 3051da177e4SLinus Torvalds 3061da177e4SLinus Torvalds current->state = TASK_INTERRUPTIBLE; 3071da177e4SLinus Torvalds schedule(); 3087b3e2fc8SRalf Baechle set_thread_flag(TIF_RESTORE_SIGMASK); 3097b3e2fc8SRalf Baechle return -ERESTARTNOHAND; 3101da177e4SLinus Torvalds } 3111da177e4SLinus Torvalds #endif 3121da177e4SLinus Torvalds 313f90080a0SFranck Bui-Huu asmlinkage int sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) 3141da177e4SLinus Torvalds { 3157b3e2fc8SRalf Baechle sigset_t newset; 316fe00f943SRalf Baechle sigset_t __user *unewset; 3171da177e4SLinus Torvalds size_t sigsetsize; 3181da177e4SLinus Torvalds 3191da177e4SLinus Torvalds /* XXX Don't preclude handling different sized sigset_t's. */ 3201da177e4SLinus Torvalds sigsetsize = regs.regs[5]; 3211da177e4SLinus Torvalds if (sigsetsize != sizeof(sigset_t)) 3221da177e4SLinus Torvalds return -EINVAL; 3231da177e4SLinus Torvalds 324fe00f943SRalf Baechle unewset = (sigset_t __user *) regs.regs[4]; 3251da177e4SLinus Torvalds if (copy_from_user(&newset, unewset, sizeof(newset))) 3261da177e4SLinus Torvalds return -EFAULT; 3271da177e4SLinus Torvalds sigdelsetmask(&newset, ~_BLOCKABLE); 3281da177e4SLinus Torvalds 3291da177e4SLinus Torvalds spin_lock_irq(¤t->sighand->siglock); 3307b3e2fc8SRalf Baechle current->saved_sigmask = current->blocked; 3311da177e4SLinus Torvalds current->blocked = newset; 3321da177e4SLinus Torvalds recalc_sigpending(); 3331da177e4SLinus Torvalds spin_unlock_irq(¤t->sighand->siglock); 3341da177e4SLinus Torvalds 3351da177e4SLinus Torvalds current->state = TASK_INTERRUPTIBLE; 3361da177e4SLinus Torvalds schedule(); 3377b3e2fc8SRalf Baechle set_thread_flag(TIF_RESTORE_SIGMASK); 3387b3e2fc8SRalf Baechle return -ERESTARTNOHAND; 3391da177e4SLinus Torvalds } 3401da177e4SLinus Torvalds 3411da177e4SLinus Torvalds #ifdef CONFIG_TRAD_SIGNALS 342dbda6ac0SRalf Baechle SYSCALL_DEFINE3(sigaction, int, sig, const struct sigaction __user *, act, 343dbda6ac0SRalf Baechle struct sigaction __user *, oact) 3441da177e4SLinus Torvalds { 3451da177e4SLinus Torvalds struct k_sigaction new_ka, old_ka; 3461da177e4SLinus Torvalds int ret; 3471da177e4SLinus Torvalds int err = 0; 3481da177e4SLinus Torvalds 3491da177e4SLinus Torvalds if (act) { 3501da177e4SLinus Torvalds old_sigset_t mask; 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds if (!access_ok(VERIFY_READ, act, sizeof(*act))) 3531da177e4SLinus Torvalds return -EFAULT; 3541da177e4SLinus Torvalds err |= __get_user(new_ka.sa.sa_handler, &act->sa_handler); 3551da177e4SLinus Torvalds err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); 3561da177e4SLinus Torvalds err |= __get_user(mask, &act->sa_mask.sig[0]); 3571da177e4SLinus Torvalds if (err) 3581da177e4SLinus Torvalds return -EFAULT; 3591da177e4SLinus Torvalds 3601da177e4SLinus Torvalds siginitset(&new_ka.sa.sa_mask, mask); 3611da177e4SLinus Torvalds } 3621da177e4SLinus Torvalds 3631da177e4SLinus Torvalds ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); 3641da177e4SLinus Torvalds 3651da177e4SLinus Torvalds if (!ret && oact) { 3661da177e4SLinus Torvalds if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact))) 3671da177e4SLinus Torvalds return -EFAULT; 3681da177e4SLinus Torvalds err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); 3691da177e4SLinus Torvalds err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler); 3701da177e4SLinus Torvalds err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig); 3711da177e4SLinus Torvalds err |= __put_user(0, &oact->sa_mask.sig[1]); 3721da177e4SLinus Torvalds err |= __put_user(0, &oact->sa_mask.sig[2]); 3731da177e4SLinus Torvalds err |= __put_user(0, &oact->sa_mask.sig[3]); 3741da177e4SLinus Torvalds if (err) 3751da177e4SLinus Torvalds return -EFAULT; 3761da177e4SLinus Torvalds } 3771da177e4SLinus Torvalds 3781da177e4SLinus Torvalds return ret; 3791da177e4SLinus Torvalds } 3801da177e4SLinus Torvalds #endif 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds asmlinkage int sys_sigaltstack(nabi_no_regargs struct pt_regs regs) 3831da177e4SLinus Torvalds { 384fe00f943SRalf Baechle const stack_t __user *uss = (const stack_t __user *) regs.regs[4]; 385fe00f943SRalf Baechle stack_t __user *uoss = (stack_t __user *) regs.regs[5]; 3861da177e4SLinus Torvalds unsigned long usp = regs.regs[29]; 3871da177e4SLinus Torvalds 3881da177e4SLinus Torvalds return do_sigaltstack(uss, uoss, usp); 3891da177e4SLinus Torvalds } 3901da177e4SLinus Torvalds 3911da177e4SLinus Torvalds #ifdef CONFIG_TRAD_SIGNALS 392f90080a0SFranck Bui-Huu asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs) 3931da177e4SLinus Torvalds { 3949bbf28a3SAtsushi Nemoto struct sigframe __user *frame; 3951da177e4SLinus Torvalds sigset_t blocked; 396c6a2f467SAtsushi Nemoto int sig; 3971da177e4SLinus Torvalds 3989bbf28a3SAtsushi Nemoto frame = (struct sigframe __user *) regs.regs[29]; 3991da177e4SLinus Torvalds if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 4001da177e4SLinus Torvalds goto badframe; 4011da177e4SLinus Torvalds if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked))) 4021da177e4SLinus Torvalds goto badframe; 4031da177e4SLinus Torvalds 4041da177e4SLinus Torvalds sigdelsetmask(&blocked, ~_BLOCKABLE); 4051da177e4SLinus Torvalds spin_lock_irq(¤t->sighand->siglock); 4061da177e4SLinus Torvalds current->blocked = blocked; 4071da177e4SLinus Torvalds recalc_sigpending(); 4081da177e4SLinus Torvalds spin_unlock_irq(¤t->sighand->siglock); 4091da177e4SLinus Torvalds 410c6a2f467SAtsushi Nemoto sig = restore_sigcontext(®s, &frame->sf_sc); 411c6a2f467SAtsushi Nemoto if (sig < 0) 4121da177e4SLinus Torvalds goto badframe; 413c6a2f467SAtsushi Nemoto else if (sig) 414c6a2f467SAtsushi Nemoto force_sig(sig, current); 4151da177e4SLinus Torvalds 4161da177e4SLinus Torvalds /* 4171da177e4SLinus Torvalds * Don't let your children do this ... 4181da177e4SLinus Torvalds */ 4191da177e4SLinus Torvalds __asm__ __volatile__( 4201da177e4SLinus Torvalds "move\t$29, %0\n\t" 4211da177e4SLinus Torvalds "j\tsyscall_exit" 4221da177e4SLinus Torvalds :/* no outputs */ 4231da177e4SLinus Torvalds :"r" (®s)); 4241da177e4SLinus Torvalds /* Unreached */ 4251da177e4SLinus Torvalds 4261da177e4SLinus Torvalds badframe: 4271da177e4SLinus Torvalds force_sig(SIGSEGV, current); 4281da177e4SLinus Torvalds } 429e50c0a8fSRalf Baechle #endif /* CONFIG_TRAD_SIGNALS */ 4301da177e4SLinus Torvalds 431f90080a0SFranck Bui-Huu asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) 4321da177e4SLinus Torvalds { 4339bbf28a3SAtsushi Nemoto struct rt_sigframe __user *frame; 4341da177e4SLinus Torvalds sigset_t set; 4351da177e4SLinus Torvalds stack_t st; 436c6a2f467SAtsushi Nemoto int sig; 4371da177e4SLinus Torvalds 4389bbf28a3SAtsushi Nemoto frame = (struct rt_sigframe __user *) regs.regs[29]; 4391da177e4SLinus Torvalds if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 4401da177e4SLinus Torvalds goto badframe; 4411da177e4SLinus Torvalds if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) 4421da177e4SLinus Torvalds goto badframe; 4431da177e4SLinus Torvalds 4441da177e4SLinus Torvalds sigdelsetmask(&set, ~_BLOCKABLE); 4451da177e4SLinus Torvalds spin_lock_irq(¤t->sighand->siglock); 4461da177e4SLinus Torvalds current->blocked = set; 4471da177e4SLinus Torvalds recalc_sigpending(); 4481da177e4SLinus Torvalds spin_unlock_irq(¤t->sighand->siglock); 4491da177e4SLinus Torvalds 450c6a2f467SAtsushi Nemoto sig = restore_sigcontext(®s, &frame->rs_uc.uc_mcontext); 451c6a2f467SAtsushi Nemoto if (sig < 0) 4521da177e4SLinus Torvalds goto badframe; 453c6a2f467SAtsushi Nemoto else if (sig) 454c6a2f467SAtsushi Nemoto force_sig(sig, current); 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvalds if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st))) 4571da177e4SLinus Torvalds goto badframe; 4581da177e4SLinus Torvalds /* It is more difficult to avoid calling this function than to 4591da177e4SLinus Torvalds call it and ignore errors. */ 4609bbf28a3SAtsushi Nemoto do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]); 4611da177e4SLinus Torvalds 4621da177e4SLinus Torvalds /* 4631da177e4SLinus Torvalds * Don't let your children do this ... 4641da177e4SLinus Torvalds */ 4651da177e4SLinus Torvalds __asm__ __volatile__( 4661da177e4SLinus Torvalds "move\t$29, %0\n\t" 4671da177e4SLinus Torvalds "j\tsyscall_exit" 4681da177e4SLinus Torvalds :/* no outputs */ 4691da177e4SLinus Torvalds :"r" (®s)); 4701da177e4SLinus Torvalds /* Unreached */ 4711da177e4SLinus Torvalds 4721da177e4SLinus Torvalds badframe: 4731da177e4SLinus Torvalds force_sig(SIGSEGV, current); 4741da177e4SLinus Torvalds } 4751da177e4SLinus Torvalds 4761da177e4SLinus Torvalds #ifdef CONFIG_TRAD_SIGNALS 477151fd6acSRalf Baechle static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, 4781da177e4SLinus Torvalds int signr, sigset_t *set) 4791da177e4SLinus Torvalds { 4809bbf28a3SAtsushi Nemoto struct sigframe __user *frame; 4811da177e4SLinus Torvalds int err = 0; 4821da177e4SLinus Torvalds 4831da177e4SLinus Torvalds frame = get_sigframe(ka, regs, sizeof(*frame)); 4841da177e4SLinus Torvalds if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 4851da177e4SLinus Torvalds goto give_sigsegv; 4861da177e4SLinus Torvalds 487601dde45SFranck Bui-Huu err |= install_sigtramp(frame->sf_code, __NR_sigreturn); 4881da177e4SLinus Torvalds 4891da177e4SLinus Torvalds err |= setup_sigcontext(regs, &frame->sf_sc); 4901da177e4SLinus Torvalds err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); 4911da177e4SLinus Torvalds if (err) 4921da177e4SLinus Torvalds goto give_sigsegv; 4931da177e4SLinus Torvalds 4941da177e4SLinus Torvalds /* 4951da177e4SLinus Torvalds * Arguments to signal handler: 4961da177e4SLinus Torvalds * 4971da177e4SLinus Torvalds * a0 = signal number 4981da177e4SLinus Torvalds * a1 = 0 (should be cause) 4991da177e4SLinus Torvalds * a2 = pointer to struct sigcontext 5001da177e4SLinus Torvalds * 5011da177e4SLinus Torvalds * $25 and c0_epc point to the signal handler, $29 points to the 5021da177e4SLinus Torvalds * struct sigframe. 5031da177e4SLinus Torvalds */ 5041da177e4SLinus Torvalds regs->regs[ 4] = signr; 5051da177e4SLinus Torvalds regs->regs[ 5] = 0; 5061da177e4SLinus Torvalds regs->regs[ 6] = (unsigned long) &frame->sf_sc; 5071da177e4SLinus Torvalds regs->regs[29] = (unsigned long) frame; 5081da177e4SLinus Torvalds regs->regs[31] = (unsigned long) frame->sf_code; 5091da177e4SLinus Torvalds regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; 5101da177e4SLinus Torvalds 511722bb63dSFranck Bui-Huu DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", 5121da177e4SLinus Torvalds current->comm, current->pid, 513722bb63dSFranck Bui-Huu frame, regs->cp0_epc, regs->regs[31]); 5147b3e2fc8SRalf Baechle return 0; 5151da177e4SLinus Torvalds 5161da177e4SLinus Torvalds give_sigsegv: 5171da177e4SLinus Torvalds force_sigsegv(signr, current); 5187b3e2fc8SRalf Baechle return -EFAULT; 5191da177e4SLinus Torvalds } 5201da177e4SLinus Torvalds #endif 5211da177e4SLinus Torvalds 522151fd6acSRalf Baechle static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, 5231da177e4SLinus Torvalds int signr, sigset_t *set, siginfo_t *info) 5241da177e4SLinus Torvalds { 5259bbf28a3SAtsushi Nemoto struct rt_sigframe __user *frame; 5261da177e4SLinus Torvalds int err = 0; 5271da177e4SLinus Torvalds 5281da177e4SLinus Torvalds frame = get_sigframe(ka, regs, sizeof(*frame)); 5291da177e4SLinus Torvalds if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 5301da177e4SLinus Torvalds goto give_sigsegv; 5311da177e4SLinus Torvalds 532601dde45SFranck Bui-Huu err |= install_sigtramp(frame->rs_code, __NR_rt_sigreturn); 5331da177e4SLinus Torvalds 5341da177e4SLinus Torvalds /* Create siginfo. */ 5351da177e4SLinus Torvalds err |= copy_siginfo_to_user(&frame->rs_info, info); 5361da177e4SLinus Torvalds 5371da177e4SLinus Torvalds /* Create the ucontext. */ 5381da177e4SLinus Torvalds err |= __put_user(0, &frame->rs_uc.uc_flags); 5395665a0acSAtsushi Nemoto err |= __put_user(NULL, &frame->rs_uc.uc_link); 5409c6031ccSAtsushi Nemoto err |= __put_user((void __user *)current->sas_ss_sp, 5411da177e4SLinus Torvalds &frame->rs_uc.uc_stack.ss_sp); 5421da177e4SLinus Torvalds err |= __put_user(sas_ss_flags(regs->regs[29]), 5431da177e4SLinus Torvalds &frame->rs_uc.uc_stack.ss_flags); 5441da177e4SLinus Torvalds err |= __put_user(current->sas_ss_size, 5451da177e4SLinus Torvalds &frame->rs_uc.uc_stack.ss_size); 5461da177e4SLinus Torvalds err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext); 5471da177e4SLinus Torvalds err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set)); 5481da177e4SLinus Torvalds 5491da177e4SLinus Torvalds if (err) 5501da177e4SLinus Torvalds goto give_sigsegv; 5511da177e4SLinus Torvalds 5521da177e4SLinus Torvalds /* 5531da177e4SLinus Torvalds * Arguments to signal handler: 5541da177e4SLinus Torvalds * 5551da177e4SLinus Torvalds * a0 = signal number 5561da177e4SLinus Torvalds * a1 = 0 (should be cause) 5571da177e4SLinus Torvalds * a2 = pointer to ucontext 5581da177e4SLinus Torvalds * 5591da177e4SLinus Torvalds * $25 and c0_epc point to the signal handler, $29 points to 5601da177e4SLinus Torvalds * the struct rt_sigframe. 5611da177e4SLinus Torvalds */ 5621da177e4SLinus Torvalds regs->regs[ 4] = signr; 5631da177e4SLinus Torvalds regs->regs[ 5] = (unsigned long) &frame->rs_info; 5641da177e4SLinus Torvalds regs->regs[ 6] = (unsigned long) &frame->rs_uc; 5651da177e4SLinus Torvalds regs->regs[29] = (unsigned long) frame; 5661da177e4SLinus Torvalds regs->regs[31] = (unsigned long) frame->rs_code; 5671da177e4SLinus Torvalds regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; 5681da177e4SLinus Torvalds 569722bb63dSFranck Bui-Huu DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", 5701da177e4SLinus Torvalds current->comm, current->pid, 5711da177e4SLinus Torvalds frame, regs->cp0_epc, regs->regs[31]); 572722bb63dSFranck Bui-Huu 5737b3e2fc8SRalf Baechle return 0; 5741da177e4SLinus Torvalds 5751da177e4SLinus Torvalds give_sigsegv: 5761da177e4SLinus Torvalds force_sigsegv(signr, current); 5777b3e2fc8SRalf Baechle return -EFAULT; 5781da177e4SLinus Torvalds } 5791da177e4SLinus Torvalds 580151fd6acSRalf Baechle struct mips_abi mips_abi = { 581151fd6acSRalf Baechle #ifdef CONFIG_TRAD_SIGNALS 582151fd6acSRalf Baechle .setup_frame = setup_frame, 583151fd6acSRalf Baechle #endif 584151fd6acSRalf Baechle .setup_rt_frame = setup_rt_frame, 585151fd6acSRalf Baechle .restart = __NR_restart_syscall 586151fd6acSRalf Baechle }; 587151fd6acSRalf Baechle 588e692eb30SFranck Bui-Huu static int handle_signal(unsigned long sig, siginfo_t *info, 5891da177e4SLinus Torvalds struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) 5901da177e4SLinus Torvalds { 591129bc8f7SRalf Baechle int ret; 592129bc8f7SRalf Baechle 5931da177e4SLinus Torvalds switch(regs->regs[0]) { 5941da177e4SLinus Torvalds case ERESTART_RESTARTBLOCK: 5951da177e4SLinus Torvalds case ERESTARTNOHAND: 5961da177e4SLinus Torvalds regs->regs[2] = EINTR; 5971da177e4SLinus Torvalds break; 5981da177e4SLinus Torvalds case ERESTARTSYS: 5991da177e4SLinus Torvalds if (!(ka->sa.sa_flags & SA_RESTART)) { 6001da177e4SLinus Torvalds regs->regs[2] = EINTR; 6011da177e4SLinus Torvalds break; 6021da177e4SLinus Torvalds } 6031da177e4SLinus Torvalds /* fallthrough */ 6041da177e4SLinus Torvalds case ERESTARTNOINTR: /* Userland will reload $v0. */ 6051da177e4SLinus Torvalds regs->regs[7] = regs->regs[26]; 6061da177e4SLinus Torvalds regs->cp0_epc -= 8; 6071da177e4SLinus Torvalds } 6081da177e4SLinus Torvalds 6091da177e4SLinus Torvalds regs->regs[0] = 0; /* Don't deal with this again. */ 6101da177e4SLinus Torvalds 611e50c0a8fSRalf Baechle if (sig_uses_siginfo(ka)) 612129bc8f7SRalf Baechle ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info); 6131da177e4SLinus Torvalds else 614129bc8f7SRalf Baechle ret = current->thread.abi->setup_frame(ka, regs, sig, oldset); 6151da177e4SLinus Torvalds 6161da177e4SLinus Torvalds spin_lock_irq(¤t->sighand->siglock); 6171da177e4SLinus Torvalds sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); 61869be8f18SSteven Rostedt if (!(ka->sa.sa_flags & SA_NODEFER)) 6191da177e4SLinus Torvalds sigaddset(¤t->blocked, sig); 6201da177e4SLinus Torvalds recalc_sigpending(); 6211da177e4SLinus Torvalds spin_unlock_irq(¤t->sighand->siglock); 622129bc8f7SRalf Baechle 623129bc8f7SRalf Baechle return ret; 6241da177e4SLinus Torvalds } 6251da177e4SLinus Torvalds 626151fd6acSRalf Baechle static void do_signal(struct pt_regs *regs) 6271da177e4SLinus Torvalds { 6281da177e4SLinus Torvalds struct k_sigaction ka; 6297b3e2fc8SRalf Baechle sigset_t *oldset; 6301da177e4SLinus Torvalds siginfo_t info; 6311da177e4SLinus Torvalds int signr; 6321da177e4SLinus Torvalds 6331da177e4SLinus Torvalds /* 6341da177e4SLinus Torvalds * We want the common case to go fast, which is why we may in certain 6351da177e4SLinus Torvalds * cases get here from kernel mode. Just return without doing anything 6361da177e4SLinus Torvalds * if so. 6371da177e4SLinus Torvalds */ 6381da177e4SLinus Torvalds if (!user_mode(regs)) 63940ac5d47SRalf Baechle return; 6401da177e4SLinus Torvalds 6417b3e2fc8SRalf Baechle if (test_thread_flag(TIF_RESTORE_SIGMASK)) 6427b3e2fc8SRalf Baechle oldset = ¤t->saved_sigmask; 6437b3e2fc8SRalf Baechle else 6441da177e4SLinus Torvalds oldset = ¤t->blocked; 6451da177e4SLinus Torvalds 6461da177e4SLinus Torvalds signr = get_signal_to_deliver(&info, &ka, regs, NULL); 6477b3e2fc8SRalf Baechle if (signr > 0) { 6487b3e2fc8SRalf Baechle /* Whee! Actually deliver the signal. */ 6497b3e2fc8SRalf Baechle if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { 6507b3e2fc8SRalf Baechle /* 6517b3e2fc8SRalf Baechle * A signal was successfully delivered; the saved 6527b3e2fc8SRalf Baechle * sigmask will have been stored in the signal frame, 6537b3e2fc8SRalf Baechle * and will be restored by sigreturn, so we can simply 6547b3e2fc8SRalf Baechle * clear the TIF_RESTORE_SIGMASK flag. 6557b3e2fc8SRalf Baechle */ 6567b3e2fc8SRalf Baechle if (test_thread_flag(TIF_RESTORE_SIGMASK)) 6577b3e2fc8SRalf Baechle clear_thread_flag(TIF_RESTORE_SIGMASK); 6587b3e2fc8SRalf Baechle } 65945887e12SRalf Baechle 66045887e12SRalf Baechle return; 6617b3e2fc8SRalf Baechle } 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds /* 6641da177e4SLinus Torvalds * Who's code doesn't conform to the restartable syscall convention 6651da177e4SLinus Torvalds * dies here!!! The li instruction, a single machine instruction, 6661da177e4SLinus Torvalds * must directly be followed by the syscall instruction. 6671da177e4SLinus Torvalds */ 6681da177e4SLinus Torvalds if (regs->regs[0]) { 6691da177e4SLinus Torvalds if (regs->regs[2] == ERESTARTNOHAND || 6701da177e4SLinus Torvalds regs->regs[2] == ERESTARTSYS || 6711da177e4SLinus Torvalds regs->regs[2] == ERESTARTNOINTR) { 6721da177e4SLinus Torvalds regs->regs[7] = regs->regs[26]; 6731da177e4SLinus Torvalds regs->cp0_epc -= 8; 6741da177e4SLinus Torvalds } 6751da177e4SLinus Torvalds if (regs->regs[2] == ERESTART_RESTARTBLOCK) { 676151fd6acSRalf Baechle regs->regs[2] = current->thread.abi->restart; 6771da177e4SLinus Torvalds regs->regs[7] = regs->regs[26]; 6781da177e4SLinus Torvalds regs->cp0_epc -= 4; 6791da177e4SLinus Torvalds } 68013fdd31aSRalf Baechle regs->regs[0] = 0; /* Don't deal with this again. */ 6811da177e4SLinus Torvalds } 6827b3e2fc8SRalf Baechle 6837b3e2fc8SRalf Baechle /* 6847b3e2fc8SRalf Baechle * If there's no signal to deliver, we just put the saved sigmask 6857b3e2fc8SRalf Baechle * back 6867b3e2fc8SRalf Baechle */ 6877b3e2fc8SRalf Baechle if (test_thread_flag(TIF_RESTORE_SIGMASK)) { 6887b3e2fc8SRalf Baechle clear_thread_flag(TIF_RESTORE_SIGMASK); 6897b3e2fc8SRalf Baechle sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); 6907b3e2fc8SRalf Baechle } 6911da177e4SLinus Torvalds } 6921da177e4SLinus Torvalds 6931da177e4SLinus Torvalds /* 6941da177e4SLinus Torvalds * notification of userspace execution resumption 6957b3e2fc8SRalf Baechle * - triggered by the TIF_WORK_MASK flags 6961da177e4SLinus Torvalds */ 6977b3e2fc8SRalf Baechle asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, 6981da177e4SLinus Torvalds __u32 thread_info_flags) 6991da177e4SLinus Torvalds { 7001da177e4SLinus Torvalds /* deal with pending signal delivery */ 7017b3e2fc8SRalf Baechle if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) 702151fd6acSRalf Baechle do_signal(regs); 703d0420c83SDavid Howells 704d0420c83SDavid Howells if (thread_info_flags & _TIF_NOTIFY_RESUME) { 705d0420c83SDavid Howells clear_thread_flag(TIF_NOTIFY_RESUME); 706d0420c83SDavid Howells tracehook_notify_resume(regs); 707d0420c83SDavid Howells } 7081da177e4SLinus Torvalds } 709