blob: 35f2ef44de12629cfa166cef50f23b5e72b365cb [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/arch/alpha/kernel/signal.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 *
6 * 1997-11-02 Modified for POSIX.1b signals by Richard Henderson
7 */
8
9#include <linux/sched.h>
10#include <linux/kernel.h>
11#include <linux/signal.h>
12#include <linux/errno.h>
13#include <linux/wait.h>
14#include <linux/ptrace.h>
15#include <linux/unistd.h>
16#include <linux/mm.h>
17#include <linux/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include <linux/stddef.h>
19#include <linux/tty.h>
20#include <linux/binfmts.h>
21#include <linux/bitops.h>
Ivan Kokshayskye5d9a902009-01-29 14:25:18 -080022#include <linux/syscalls.h>
David Howells733e5e42009-09-09 08:30:21 +010023#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
25#include <asm/uaccess.h>
26#include <asm/sigcontext.h>
27#include <asm/ucontext.h>
28
29#include "proto.h"
30
31
32#define DEBUG_SIG 0
33
34#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
35
36asmlinkage void ret_from_sys_call(void);
Richard Hendersonb927b3e2007-05-29 16:03:28 -070037static void do_signal(struct pt_regs *, struct switch_stack *,
38 unsigned long, unsigned long);
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
40
41/*
42 * The OSF/1 sigprocmask calling sequence is different from the
43 * C sigprocmask() sequence..
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 */
Al Viroc52c2dd2010-09-26 19:28:12 +010045SYSCALL_DEFINE2(osf_sigprocmask, int, how, unsigned long, newmask)
Linus Torvalds1da177e2005-04-16 15:20:36 -070046{
Al Viroc52c2dd2010-09-26 19:28:12 +010047 sigset_t oldmask;
48 sigset_t mask;
49 unsigned long res;
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
Linus Torvalds87400e52010-09-30 08:37:38 -070051 siginitset(&mask, newmask & _BLOCKABLE);
Linus Torvalds0f44fbd2010-09-28 13:26:57 -070052 res = sigprocmask(how, &mask, &oldmask);
Al Viroc52c2dd2010-09-26 19:28:12 +010053 if (!res) {
54 force_successful_syscall_return();
Linus Torvalds0f44fbd2010-09-28 13:26:57 -070055 res = oldmask.sig[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 }
Al Viroc52c2dd2010-09-26 19:28:12 +010057 return res;
Linus Torvalds1da177e2005-04-16 15:20:36 -070058}
59
Ivan Kokshayskye5d9a902009-01-29 14:25:18 -080060SYSCALL_DEFINE3(osf_sigaction, int, sig,
61 const struct osf_sigaction __user *, act,
62 struct osf_sigaction __user *, oact)
Linus Torvalds1da177e2005-04-16 15:20:36 -070063{
64 struct k_sigaction new_ka, old_ka;
65 int ret;
66
67 if (act) {
68 old_sigset_t mask;
69 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
70 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
Al Viro18e6bfa2010-09-26 19:28:22 +010071 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
72 __get_user(mask, &act->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -070073 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 siginitset(&new_ka.sa.sa_mask, mask);
75 new_ka.ka_restorer = NULL;
76 }
77
78 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
79
80 if (!ret && oact) {
81 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
82 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
Al Viro18e6bfa2010-09-26 19:28:22 +010083 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
84 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 }
87
88 return ret;
89}
90
Ivan Kokshayskye5d9a902009-01-29 14:25:18 -080091SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
92 struct sigaction __user *, oact,
93 size_t, sigsetsize, void __user *, restorer)
Linus Torvalds1da177e2005-04-16 15:20:36 -070094{
95 struct k_sigaction new_ka, old_ka;
96 int ret;
97
98 /* XXX: Don't preclude handling different sized sigset_t's. */
99 if (sigsetsize != sizeof(sigset_t))
100 return -EINVAL;
101
102 if (act) {
103 new_ka.ka_restorer = restorer;
104 if (copy_from_user(&new_ka.sa, act, sizeof(*act)))
105 return -EFAULT;
106 }
107
108 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
109
110 if (!ret && oact) {
111 if (copy_to_user(oact, &old_ka.sa, sizeof(*oact)))
112 return -EFAULT;
113 }
114
115 return ret;
116}
117
118/*
119 * Atomically swap in the new signal mask, and wait for a signal.
120 */
Al Viro392fb6e2010-09-18 08:40:07 -0400121SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122{
Matt Fleming2561b062012-04-05 14:25:12 -0700123 sigset_t blocked;
124
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700125 current->saved_sigmask = current->blocked;
Matt Fleming2561b062012-04-05 14:25:12 -0700126
127 mask &= _BLOCKABLE;
128 siginitset(&blocked, mask);
129 set_current_blocked(&blocked);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700131 current->state = TASK_INTERRUPTIBLE;
132 schedule();
133 set_thread_flag(TIF_RESTORE_SIGMASK);
134 return -ERESTARTNOHAND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135}
136
137asmlinkage int
138sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
139{
140 return do_sigaltstack(uss, uoss, rdusp());
141}
142
143/*
144 * Do a signal return; undo the signal stack.
145 */
146
147#if _NSIG_WORDS > 1
148# error "Non SA_SIGINFO frame needs rearranging"
149#endif
150
151struct sigframe
152{
153 struct sigcontext sc;
154 unsigned int retcode[3];
155};
156
157struct rt_sigframe
158{
159 struct siginfo info;
160 struct ucontext uc;
161 unsigned int retcode[3];
162};
163
164/* If this changes, userland unwinders that Know Things about our signal
165 frame will break. Do not undertake lightly. It also implies an ABI
166 change wrt the size of siginfo_t, which may cause some pain. */
167extern char compile_time_assert
168 [offsetof(struct rt_sigframe, uc.uc_mcontext) == 176 ? 1 : -1];
169
170#define INSN_MOV_R30_R16 0x47fe0410
171#define INSN_LDI_R0 0x201f0000
172#define INSN_CALLSYS 0x00000083
173
174static long
175restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
176 struct switch_stack *sw)
177{
178 unsigned long usp;
179 long i, err = __get_user(regs->pc, &sc->sc_pc);
180
Al Viro2deba1b2010-09-18 08:38:47 -0400181 current_thread_info()->restart_block.fn = do_no_restart_syscall;
182
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 sw->r26 = (unsigned long) ret_from_sys_call;
184
185 err |= __get_user(regs->r0, sc->sc_regs+0);
186 err |= __get_user(regs->r1, sc->sc_regs+1);
187 err |= __get_user(regs->r2, sc->sc_regs+2);
188 err |= __get_user(regs->r3, sc->sc_regs+3);
189 err |= __get_user(regs->r4, sc->sc_regs+4);
190 err |= __get_user(regs->r5, sc->sc_regs+5);
191 err |= __get_user(regs->r6, sc->sc_regs+6);
192 err |= __get_user(regs->r7, sc->sc_regs+7);
193 err |= __get_user(regs->r8, sc->sc_regs+8);
194 err |= __get_user(sw->r9, sc->sc_regs+9);
195 err |= __get_user(sw->r10, sc->sc_regs+10);
196 err |= __get_user(sw->r11, sc->sc_regs+11);
197 err |= __get_user(sw->r12, sc->sc_regs+12);
198 err |= __get_user(sw->r13, sc->sc_regs+13);
199 err |= __get_user(sw->r14, sc->sc_regs+14);
200 err |= __get_user(sw->r15, sc->sc_regs+15);
201 err |= __get_user(regs->r16, sc->sc_regs+16);
202 err |= __get_user(regs->r17, sc->sc_regs+17);
203 err |= __get_user(regs->r18, sc->sc_regs+18);
204 err |= __get_user(regs->r19, sc->sc_regs+19);
205 err |= __get_user(regs->r20, sc->sc_regs+20);
206 err |= __get_user(regs->r21, sc->sc_regs+21);
207 err |= __get_user(regs->r22, sc->sc_regs+22);
208 err |= __get_user(regs->r23, sc->sc_regs+23);
209 err |= __get_user(regs->r24, sc->sc_regs+24);
210 err |= __get_user(regs->r25, sc->sc_regs+25);
211 err |= __get_user(regs->r26, sc->sc_regs+26);
212 err |= __get_user(regs->r27, sc->sc_regs+27);
213 err |= __get_user(regs->r28, sc->sc_regs+28);
214 err |= __get_user(regs->gp, sc->sc_regs+29);
215 err |= __get_user(usp, sc->sc_regs+30);
216 wrusp(usp);
217
218 for (i = 0; i < 31; i++)
219 err |= __get_user(sw->fp[i], sc->sc_fpregs+i);
220 err |= __get_user(sw->fp[31], &sc->sc_fpcr);
221
222 return err;
223}
224
225/* Note that this syscall is also used by setcontext(3) to install
226 a given sigcontext. This because it's impossible to set *all*
227 registers and transfer control from userland. */
228
229asmlinkage void
230do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
231 struct switch_stack *sw)
232{
233 sigset_t set;
234
235 /* Verify that it's a good sigcontext before using it */
236 if (!access_ok(VERIFY_READ, sc, sizeof(*sc)))
237 goto give_sigsegv;
238 if (__get_user(set.sig[0], &sc->sc_mask))
239 goto give_sigsegv;
240
241 sigdelsetmask(&set, ~_BLOCKABLE);
Matt Fleming2561b062012-04-05 14:25:12 -0700242 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243
244 if (restore_sigcontext(sc, regs, sw))
245 goto give_sigsegv;
246
247 /* Send SIGTRAP if we're single-stepping: */
248 if (ptrace_cancel_bpt (current)) {
249 siginfo_t info;
250
251 info.si_signo = SIGTRAP;
252 info.si_errno = 0;
253 info.si_code = TRAP_BRKPT;
254 info.si_addr = (void __user *) regs->pc;
255 info.si_trapno = 0;
256 send_sig_info(SIGTRAP, &info, current);
257 }
258 return;
259
260give_sigsegv:
261 force_sig(SIGSEGV, current);
262}
263
264asmlinkage void
265do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
266 struct switch_stack *sw)
267{
268 sigset_t set;
269
270 /* Verify that it's a good ucontext_t before using it */
271 if (!access_ok(VERIFY_READ, &frame->uc, sizeof(frame->uc)))
272 goto give_sigsegv;
273 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
274 goto give_sigsegv;
275
276 sigdelsetmask(&set, ~_BLOCKABLE);
Matt Fleming2561b062012-04-05 14:25:12 -0700277 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
279 if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
280 goto give_sigsegv;
281
282 /* Send SIGTRAP if we're single-stepping: */
283 if (ptrace_cancel_bpt (current)) {
284 siginfo_t info;
285
286 info.si_signo = SIGTRAP;
287 info.si_errno = 0;
288 info.si_code = TRAP_BRKPT;
289 info.si_addr = (void __user *) regs->pc;
290 info.si_trapno = 0;
291 send_sig_info(SIGTRAP, &info, current);
292 }
293 return;
294
295give_sigsegv:
296 force_sig(SIGSEGV, current);
297}
298
299
300/*
301 * Set up a signal frame.
302 */
303
304static inline void __user *
305get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
306{
Laurent MEYERd09042d2006-06-23 02:05:36 -0700307 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 sp = current->sas_ss_sp + current->sas_ss_size;
309
310 return (void __user *)((sp - frame_size) & -32ul);
311}
312
313static long
314setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
315 struct switch_stack *sw, unsigned long mask, unsigned long sp)
316{
317 long i, err = 0;
318
319 err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack);
320 err |= __put_user(mask, &sc->sc_mask);
321 err |= __put_user(regs->pc, &sc->sc_pc);
322 err |= __put_user(8, &sc->sc_ps);
323
324 err |= __put_user(regs->r0 , sc->sc_regs+0);
325 err |= __put_user(regs->r1 , sc->sc_regs+1);
326 err |= __put_user(regs->r2 , sc->sc_regs+2);
327 err |= __put_user(regs->r3 , sc->sc_regs+3);
328 err |= __put_user(regs->r4 , sc->sc_regs+4);
329 err |= __put_user(regs->r5 , sc->sc_regs+5);
330 err |= __put_user(regs->r6 , sc->sc_regs+6);
331 err |= __put_user(regs->r7 , sc->sc_regs+7);
332 err |= __put_user(regs->r8 , sc->sc_regs+8);
333 err |= __put_user(sw->r9 , sc->sc_regs+9);
334 err |= __put_user(sw->r10 , sc->sc_regs+10);
335 err |= __put_user(sw->r11 , sc->sc_regs+11);
336 err |= __put_user(sw->r12 , sc->sc_regs+12);
337 err |= __put_user(sw->r13 , sc->sc_regs+13);
338 err |= __put_user(sw->r14 , sc->sc_regs+14);
339 err |= __put_user(sw->r15 , sc->sc_regs+15);
340 err |= __put_user(regs->r16, sc->sc_regs+16);
341 err |= __put_user(regs->r17, sc->sc_regs+17);
342 err |= __put_user(regs->r18, sc->sc_regs+18);
343 err |= __put_user(regs->r19, sc->sc_regs+19);
344 err |= __put_user(regs->r20, sc->sc_regs+20);
345 err |= __put_user(regs->r21, sc->sc_regs+21);
346 err |= __put_user(regs->r22, sc->sc_regs+22);
347 err |= __put_user(regs->r23, sc->sc_regs+23);
348 err |= __put_user(regs->r24, sc->sc_regs+24);
349 err |= __put_user(regs->r25, sc->sc_regs+25);
350 err |= __put_user(regs->r26, sc->sc_regs+26);
351 err |= __put_user(regs->r27, sc->sc_regs+27);
352 err |= __put_user(regs->r28, sc->sc_regs+28);
353 err |= __put_user(regs->gp , sc->sc_regs+29);
354 err |= __put_user(sp, sc->sc_regs+30);
355 err |= __put_user(0, sc->sc_regs+31);
356
357 for (i = 0; i < 31; i++)
358 err |= __put_user(sw->fp[i], sc->sc_fpregs+i);
359 err |= __put_user(0, sc->sc_fpregs+31);
360 err |= __put_user(sw->fp[31], &sc->sc_fpcr);
361
362 err |= __put_user(regs->trap_a0, &sc->sc_traparg_a0);
363 err |= __put_user(regs->trap_a1, &sc->sc_traparg_a1);
364 err |= __put_user(regs->trap_a2, &sc->sc_traparg_a2);
365
366 return err;
367}
368
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700369static int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
371 struct pt_regs *regs, struct switch_stack * sw)
372{
373 unsigned long oldsp, r26, err = 0;
374 struct sigframe __user *frame;
375
376 oldsp = rdusp();
377 frame = get_sigframe(ka, oldsp, sizeof(*frame));
378 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
379 goto give_sigsegv;
380
381 err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
382 if (err)
383 goto give_sigsegv;
384
385 /* Set up to return from userspace. If provided, use a stub
386 already in userspace. */
387 if (ka->ka_restorer) {
388 r26 = (unsigned long) ka->ka_restorer;
389 } else {
390 err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
391 err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
392 err |= __put_user(INSN_CALLSYS, frame->retcode+2);
393 imb();
394 r26 = (unsigned long) frame->retcode;
395 }
396
397 /* Check that everything was written properly. */
398 if (err)
399 goto give_sigsegv;
400
401 /* "Return" to the handler */
402 regs->r26 = r26;
403 regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
404 regs->r16 = sig; /* a0: signal number */
405 regs->r17 = 0; /* a1: exception code */
406 regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */
407 wrusp((unsigned long) frame);
408
409#if DEBUG_SIG
410 printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
411 current->comm, current->pid, frame, regs->pc, regs->r26);
412#endif
413
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700414 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
416give_sigsegv:
417 force_sigsegv(sig, current);
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700418 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419}
420
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700421static int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
423 sigset_t *set, struct pt_regs *regs, struct switch_stack * sw)
424{
425 unsigned long oldsp, r26, err = 0;
426 struct rt_sigframe __user *frame;
427
428 oldsp = rdusp();
429 frame = get_sigframe(ka, oldsp, sizeof(*frame));
430 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
431 goto give_sigsegv;
432
433 err |= copy_siginfo_to_user(&frame->info, info);
434
435 /* Create the ucontext. */
436 err |= __put_user(0, &frame->uc.uc_flags);
437 err |= __put_user(0, &frame->uc.uc_link);
438 err |= __put_user(set->sig[0], &frame->uc.uc_osf_sigmask);
439 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
440 err |= __put_user(sas_ss_flags(oldsp), &frame->uc.uc_stack.ss_flags);
441 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
442 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, sw,
443 set->sig[0], oldsp);
444 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
445 if (err)
446 goto give_sigsegv;
447
448 /* Set up to return from userspace. If provided, use a stub
449 already in userspace. */
450 if (ka->ka_restorer) {
451 r26 = (unsigned long) ka->ka_restorer;
452 } else {
453 err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
454 err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn,
455 frame->retcode+1);
456 err |= __put_user(INSN_CALLSYS, frame->retcode+2);
457 imb();
458 r26 = (unsigned long) frame->retcode;
459 }
460
461 if (err)
462 goto give_sigsegv;
463
464 /* "Return" to the handler */
465 regs->r26 = r26;
466 regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
467 regs->r16 = sig; /* a0: signal number */
468 regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */
469 regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */
470 wrusp((unsigned long) frame);
471
472#if DEBUG_SIG
473 printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
474 current->comm, current->pid, frame, regs->pc, regs->r26);
475#endif
476
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700477 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
479give_sigsegv:
480 force_sigsegv(sig, current);
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700481 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482}
483
484
485/*
486 * OK, we're invoking a handler.
487 */
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700488static inline int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
490 sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw)
491{
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700492 int ret;
493
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 if (ka->sa.sa_flags & SA_SIGINFO)
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700495 ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 else
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700497 ret = setup_frame(sig, ka, oldset, regs, sw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498
Matt Fleming2561b062012-04-05 14:25:12 -0700499 if (ret == 0)
500 block_sigmask(ka, sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700502 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503}
504
505static inline void
506syscall_restart(unsigned long r0, unsigned long r19,
507 struct pt_regs *regs, struct k_sigaction *ka)
508{
509 switch (regs->r0) {
510 case ERESTARTSYS:
511 if (!(ka->sa.sa_flags & SA_RESTART)) {
512 case ERESTARTNOHAND:
513 regs->r0 = EINTR;
514 break;
515 }
516 /* fallthrough */
517 case ERESTARTNOINTR:
518 regs->r0 = r0; /* reset v0 and a3 and replay syscall */
519 regs->r19 = r19;
520 regs->pc -= 4;
521 break;
522 case ERESTART_RESTARTBLOCK:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 regs->r0 = EINTR;
524 break;
525 }
526}
527
528
529/*
530 * Note that 'init' is a special process: it doesn't get signals it doesn't
531 * want to handle. Thus you cannot kill init even with a SIGKILL even by
532 * mistake.
533 *
534 * Note that we go through the signals twice: once to check the signals that
535 * the kernel can handle, and then we build all the user-level signal handling
536 * stack-frames in one go after that.
537 *
538 * "r0" and "r19" are the registers we need to restore for system call
539 * restart. "r0" is also used as an indicator whether we can restart at
540 * all (if we get here from anything but a syscall return, it will be 0)
541 */
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700542static void
543do_signal(struct pt_regs * regs, struct switch_stack * sw,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 unsigned long r0, unsigned long r19)
545{
546 siginfo_t info;
547 int signr;
548 unsigned long single_stepping = ptrace_cancel_bpt(current);
549 struct k_sigaction ka;
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700550 sigset_t *oldset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700552 if (test_thread_flag(TIF_RESTORE_SIGMASK))
553 oldset = &current->saved_sigmask;
554 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 oldset = &current->blocked;
556
557 /* This lets the debugger run, ... */
558 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700559
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 /* ... so re-check the single stepping. */
561 single_stepping |= ptrace_cancel_bpt(current);
562
563 if (signr > 0) {
564 /* Whee! Actually deliver the signal. */
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700565 if (r0)
566 syscall_restart(r0, r19, regs, &ka);
567 if (handle_signal(signr, &ka, &info, oldset, regs, sw) == 0) {
568 /* A signal was successfully delivered, and the
569 saved sigmask was stored on the signal frame,
570 and will be restored by sigreturn. So we can
571 simply clear the restore sigmask flag. */
572 if (test_thread_flag(TIF_RESTORE_SIGMASK))
573 clear_thread_flag(TIF_RESTORE_SIGMASK);
574 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 if (single_stepping)
576 ptrace_set_bpt(current); /* re-set bpt */
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700577 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 }
579
580 if (r0) {
581 switch (regs->r0) {
582 case ERESTARTNOHAND:
583 case ERESTARTSYS:
584 case ERESTARTNOINTR:
585 /* Reset v0 and a3 and replay syscall. */
586 regs->r0 = r0;
587 regs->r19 = r19;
588 regs->pc -= 4;
589 break;
590 case ERESTART_RESTARTBLOCK:
591 /* Force v0 to the restart syscall and reply. */
592 regs->r0 = __NR_restart_syscall;
593 regs->pc -= 4;
594 break;
595 }
596 }
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700597
598 /* If there's no signal to deliver, we just restore the saved mask. */
599 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
600 clear_thread_flag(TIF_RESTORE_SIGMASK);
601 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
602 }
603
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 if (single_stepping)
605 ptrace_set_bpt(current); /* re-set breakpoint */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606}
607
608void
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700609do_notify_resume(struct pt_regs *regs, struct switch_stack *sw,
610 unsigned long thread_info_flags,
611 unsigned long r0, unsigned long r19)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612{
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700613 if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
614 do_signal(regs, sw, r0, r19);
David Howellsd0420c82009-09-02 09:14:16 +0100615
616 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
617 clear_thread_flag(TIF_NOTIFY_RESUME);
618 tracehook_notify_resume(regs);
David Howellsee18d642009-09-02 09:14:21 +0100619 if (current->replacement_session_keyring)
620 key_replace_session_keyring();
David Howellsd0420c82009-09-02 09:14:16 +0100621 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622}