blob: 1d62dfef77f1df57d4c2b555e0a7d64a16052f8d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Paul Mundta23ba432007-11-28 20:19:38 +09002 * arch/sh/kernel/signal_64.c
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * Copyright (C) 2000, 2001 Paolo Alberelli
5 * Copyright (C) 2003 Paul Mundt
6 * Copyright (C) 2004 Richard Curnow
7 *
Paul Mundta23ba432007-11-28 20:19:38 +09008 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 */
12#include <linux/rwsem.h>
13#include <linux/sched.h>
14#include <linux/mm.h>
15#include <linux/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include <linux/kernel.h>
17#include <linux/signal.h>
18#include <linux/errno.h>
19#include <linux/wait.h>
20#include <linux/personality.h>
Nigel Cunningham7dfb7102006-12-06 20:34:23 -080021#include <linux/freezer.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/ptrace.h>
23#include <linux/unistd.h>
24#include <linux/stddef.h>
Paul Mundtab99c732008-07-30 19:55:30 +090025#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <asm/ucontext.h>
27#include <asm/uaccess.h>
28#include <asm/pgtable.h>
Paul Mundtf7a7b152007-11-10 20:07:57 +090029#include <asm/cacheflush.h>
Adrian Bunk50387b32008-04-13 21:15:38 +030030#include <asm/fpu.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
32#define REG_RET 9
33#define REG_ARG1 2
34#define REG_ARG2 3
35#define REG_ARG3 4
36#define REG_SP 15
37#define REG_PR 18
38#define REF_REG_RET regs->regs[REG_RET]
39#define REF_REG_SP regs->regs[REG_SP]
40#define DEREF_REG_PR regs->regs[REG_PR]
41
42#define DEBUG_SIG 0
43
44#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
45
Paul Mundtab99c732008-07-30 19:55:30 +090046/*
47 * Note that 'init' is a special process: it doesn't get signals it doesn't
48 * want to handle. Thus you cannot kill init even with a SIGKILL even by
49 * mistake.
50 *
51 * Note that we go through the signals twice: once to check the signals that
52 * the kernel can handle, and then we build all the user-level signal handling
53 * stack-frames in one go after that.
54 */
55static int do_signal(struct pt_regs *regs, sigset_t *oldset)
56{
57 siginfo_t info;
58 int signr;
59 struct k_sigaction ka;
60
61 /*
62 * We want the common case to go fast, which
63 * is why we may in certain cases get here from
64 * kernel mode. Just return without doing anything
65 * if so.
66 */
67 if (!user_mode(regs))
68 return 1;
69
70 if (try_to_freeze())
71 goto no_signal;
72
73 if (test_thread_flag(TIF_RESTORE_SIGMASK))
74 oldset = &current->saved_sigmask;
75 else if (!oldset)
76 oldset = &current->blocked;
77
78 signr = get_signal_to_deliver(&info, &ka, regs, 0);
79
80 if (signr > 0) {
81 /* Whee! Actually deliver the signal. */
82 handle_signal(signr, &info, &ka, oldset, regs);
83
84 /*
85 * If a signal was successfully delivered, the saved sigmask
86 * is in its frame, and we can clear the TIF_RESTORE_SIGMASK
87 * flag.
88 */
89 if (test_thread_flag(TIF_RESTORE_SIGMASK))
90 clear_thread_flag(TIF_RESTORE_SIGMASK);
91
92 tracehook_signal_handler(signr, &info, &ka, regs, 0);
93 return 1;
94 }
95
96no_signal:
97 /* Did we come from a system call? */
98 if (regs->syscall_nr >= 0) {
99 /* Restart the system call - no handlers present */
100 switch (regs->regs[REG_RET]) {
101 case -ERESTARTNOHAND:
102 case -ERESTARTSYS:
103 case -ERESTARTNOINTR:
104 /* Decode Syscall # */
105 regs->regs[REG_RET] = regs->syscall_nr;
106 regs->pc -= 4;
107 break;
108
109 case -ERESTART_RESTARTBLOCK:
110 regs->regs[REG_RET] = __NR_restart_syscall;
111 regs->pc -= 4;
112 break;
113 }
114 }
115
116 /* No signal to deliver -- put the saved sigmask back */
117 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
118 clear_thread_flag(TIF_RESTORE_SIGMASK);
119 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
120 }
121
122 return 0;
123}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124
125/*
126 * Atomically swap in the new signal mask, and wait for a signal.
127 */
128
129asmlinkage int
130sys_sigsuspend(old_sigset_t mask,
131 unsigned long r3, unsigned long r4, unsigned long r5,
132 unsigned long r6, unsigned long r7,
133 struct pt_regs * regs)
134{
135 sigset_t saveset;
136
137 mask &= _BLOCKABLE;
138 spin_lock_irq(&current->sighand->siglock);
139 saveset = current->blocked;
140 siginitset(&current->blocked, mask);
141 recalc_sigpending();
142 spin_unlock_irq(&current->sighand->siglock);
143
144 REF_REG_RET = -EINTR;
145 while (1) {
146 current->state = TASK_INTERRUPTIBLE;
147 schedule();
148 regs->pc += 4; /* because sys_sigreturn decrements the pc */
149 if (do_signal(regs, &saveset)) {
150 /* pc now points at signal handler. Need to decrement
151 it because entry.S will increment it. */
152 regs->pc -= 4;
153 return -EINTR;
154 }
155 }
156}
157
158asmlinkage int
159sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
160 unsigned long r4, unsigned long r5, unsigned long r6,
161 unsigned long r7,
162 struct pt_regs * regs)
163{
164 sigset_t saveset, newset;
165
166 /* XXX: Don't preclude handling different sized sigset_t's. */
167 if (sigsetsize != sizeof(sigset_t))
168 return -EINVAL;
169
170 if (copy_from_user(&newset, unewset, sizeof(newset)))
171 return -EFAULT;
172 sigdelsetmask(&newset, ~_BLOCKABLE);
173 spin_lock_irq(&current->sighand->siglock);
174 saveset = current->blocked;
175 current->blocked = newset;
176 recalc_sigpending();
177 spin_unlock_irq(&current->sighand->siglock);
178
179 REF_REG_RET = -EINTR;
180 while (1) {
181 current->state = TASK_INTERRUPTIBLE;
182 schedule();
183 regs->pc += 4; /* because sys_sigreturn decrements the pc */
184 if (do_signal(regs, &saveset)) {
185 /* pc now points at signal handler. Need to decrement
186 it because entry.S will increment it. */
187 regs->pc -= 4;
188 return -EINTR;
189 }
190 }
191}
192
193asmlinkage int
194sys_sigaction(int sig, const struct old_sigaction __user *act,
195 struct old_sigaction __user *oact)
196{
197 struct k_sigaction new_ka, old_ka;
198 int ret;
199
200 if (act) {
201 old_sigset_t mask;
202 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
203 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
204 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
205 return -EFAULT;
206 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
207 __get_user(mask, &act->sa_mask);
208 siginitset(&new_ka.sa.sa_mask, mask);
209 }
210
211 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
212
213 if (!ret && oact) {
214 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
215 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
216 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
217 return -EFAULT;
218 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
219 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
220 }
221
222 return ret;
223}
224
225asmlinkage int
226sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
227 unsigned long r4, unsigned long r5, unsigned long r6,
228 unsigned long r7,
229 struct pt_regs * regs)
230{
231 return do_sigaltstack(uss, uoss, REF_REG_SP);
232}
233
234
235/*
236 * Do a signal return; undo the signal stack.
237 */
238
239struct sigframe
240{
241 struct sigcontext sc;
242 unsigned long extramask[_NSIG_WORDS-1];
243 long long retcode[2];
244};
245
246struct rt_sigframe
247{
248 struct siginfo __user *pinfo;
249 void *puc;
250 struct siginfo info;
251 struct ucontext uc;
252 long long retcode[2];
253};
254
255#ifdef CONFIG_SH_FPU
256static inline int
257restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
258{
259 int err = 0;
260 int fpvalid;
261
262 err |= __get_user (fpvalid, &sc->sc_fpvalid);
263 conditional_used_math(fpvalid);
264 if (! fpvalid)
265 return err;
266
267 if (current == last_task_used_math) {
268 last_task_used_math = NULL;
269 regs->sr |= SR_FD;
270 }
271
272 err |= __copy_from_user(&current->thread.fpu.hard, &sc->sc_fpregs[0],
273 (sizeof(long long) * 32) + (sizeof(int) * 1));
274
275 return err;
276}
277
278static inline int
279setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
280{
281 int err = 0;
282 int fpvalid;
283
284 fpvalid = !!used_math();
285 err |= __put_user(fpvalid, &sc->sc_fpvalid);
286 if (! fpvalid)
287 return err;
288
289 if (current == last_task_used_math) {
Paul Mundt600ee242007-11-19 19:13:38 +0900290 enable_fpu();
Paul Mundt332fd572007-11-22 17:30:50 +0900291 save_fpu(current, regs);
Paul Mundt600ee242007-11-19 19:13:38 +0900292 disable_fpu();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 last_task_used_math = NULL;
294 regs->sr |= SR_FD;
295 }
296
297 err |= __copy_to_user(&sc->sc_fpregs[0], &current->thread.fpu.hard,
298 (sizeof(long long) * 32) + (sizeof(int) * 1));
299 clear_used_math();
300
301 return err;
302}
303#else
304static inline int
305restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900306{
307 return 0;
308}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309static inline int
310setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900311{
312 return 0;
313}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314#endif
315
316static int
317restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, long long *r2_p)
318{
319 unsigned int err = 0;
320 unsigned long long current_sr, new_sr;
321#define SR_MASK 0xffff8cfd
322
323#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
324
325 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
326 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
327 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
328 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
329 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
330 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
331 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
332 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
333 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
334 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
335 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
336 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
337 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
338 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
339 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
340 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
341 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
342 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
343
344 /* Prevent the signal handler manipulating SR in a way that can
345 crash the kernel. i.e. only allow S, Q, M, PR, SZ, FR to be
346 modified */
347 current_sr = regs->sr;
348 err |= __get_user(new_sr, &sc->sc_sr);
349 regs->sr &= SR_MASK;
350 regs->sr |= (new_sr & ~SR_MASK);
351
352 COPY(pc);
353
354#undef COPY
355
356 /* Must do this last in case it sets regs->sr.fd (i.e. after rest of sr
357 * has been restored above.) */
358 err |= restore_sigcontext_fpu(regs, sc);
359
360 regs->syscall_nr = -1; /* disable syscall checks */
361 err |= __get_user(*r2_p, &sc->sc_regs[REG_RET]);
362 return err;
363}
364
365asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
366 unsigned long r4, unsigned long r5,
367 unsigned long r6, unsigned long r7,
368 struct pt_regs * regs)
369{
370 struct sigframe __user *frame = (struct sigframe __user *) (long) REF_REG_SP;
371 sigset_t set;
372 long long ret;
373
374 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
375 goto badframe;
376
377 if (__get_user(set.sig[0], &frame->sc.oldmask)
378 || (_NSIG_WORDS > 1
379 && __copy_from_user(&set.sig[1], &frame->extramask,
380 sizeof(frame->extramask))))
381 goto badframe;
382
383 sigdelsetmask(&set, ~_BLOCKABLE);
384
385 spin_lock_irq(&current->sighand->siglock);
386 current->blocked = set;
387 recalc_sigpending();
388 spin_unlock_irq(&current->sighand->siglock);
389
390 if (restore_sigcontext(regs, &frame->sc, &ret))
391 goto badframe;
392 regs->pc -= 4;
393
394 return (int) ret;
395
396badframe:
397 force_sig(SIGSEGV, current);
398 return 0;
399}
400
401asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
402 unsigned long r4, unsigned long r5,
403 unsigned long r6, unsigned long r7,
404 struct pt_regs * regs)
405{
406 struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP;
407 sigset_t set;
408 stack_t __user st;
409 long long ret;
410
411 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
412 goto badframe;
413
414 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
415 goto badframe;
416
417 sigdelsetmask(&set, ~_BLOCKABLE);
418 spin_lock_irq(&current->sighand->siglock);
419 current->blocked = set;
420 recalc_sigpending();
421 spin_unlock_irq(&current->sighand->siglock);
422
423 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret))
424 goto badframe;
425 regs->pc -= 4;
426
427 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
428 goto badframe;
429 /* It is more difficult to avoid calling this function than to
430 call it and ignore errors. */
431 do_sigaltstack(&st, NULL, REF_REG_SP);
432
433 return (int) ret;
434
435badframe:
436 force_sig(SIGSEGV, current);
437 return 0;
438}
439
440/*
441 * Set up a signal frame.
442 */
443
444static int
445setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
446 unsigned long mask)
447{
448 int err = 0;
449
450 /* Do this first, otherwise is this sets sr->fd, that value isn't preserved. */
451 err |= setup_sigcontext_fpu(regs, sc);
452
453#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
454
455 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
456 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
457 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
458 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
459 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
460 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
461 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
462 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
463 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
464 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
465 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
466 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
467 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
468 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
469 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
470 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
471 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
472 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
473 COPY(sr); COPY(pc);
474
475#undef COPY
476
477 err |= __put_user(mask, &sc->oldmask);
478
479 return err;
480}
481
482/*
483 * Determine which stack to use..
484 */
485static inline void __user *
486get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
487{
Laurent MEYERd09042d2006-06-23 02:05:36 -0700488 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 sp = current->sas_ss_sp + current->sas_ss_size;
490
491 return (void __user *)((sp - frame_size) & -8ul);
492}
493
494void sa_default_restorer(void); /* See comments below */
495void sa_default_rt_restorer(void); /* See comments below */
496
497static void setup_frame(int sig, struct k_sigaction *ka,
498 sigset_t *set, struct pt_regs *regs)
499{
500 struct sigframe __user *frame;
501 int err = 0;
502 int signal;
503
504 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
505
506 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
507 goto give_sigsegv;
508
509 signal = current_thread_info()->exec_domain
510 && current_thread_info()->exec_domain->signal_invmap
511 && sig < 32
512 ? current_thread_info()->exec_domain->signal_invmap[sig]
513 : sig;
514
515 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
516
517 /* Give up earlier as i386, in case */
518 if (err)
519 goto give_sigsegv;
520
521 if (_NSIG_WORDS > 1) {
522 err |= __copy_to_user(frame->extramask, &set->sig[1],
523 sizeof(frame->extramask)); }
524
525 /* Give up earlier as i386, in case */
526 if (err)
527 goto give_sigsegv;
528
529 /* Set up to return from userspace. If provided, use a stub
530 already in userspace. */
531 if (ka->sa.sa_flags & SA_RESTORER) {
532 DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1;
533
534 /*
535 * On SH5 all edited pointers are subject to NEFF
536 */
537 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
538 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
539 } else {
540 /*
541 * Different approach on SH5.
542 * . Endianness independent asm code gets placed in entry.S .
543 * This is limited to four ASM instructions corresponding
544 * to two long longs in size.
545 * . err checking is done on the else branch only
546 * . flush_icache_range() is called upon __put_user() only
547 * . all edited pointers are subject to NEFF
548 * . being code, linker turns ShMedia bit on, always
549 * dereference index -1.
550 */
551 DEREF_REG_PR = (unsigned long) frame->retcode | 0x01;
552 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
553 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
554
555 if (__copy_to_user(frame->retcode,
556 (unsigned long long)sa_default_restorer & (~1), 16) != 0)
557 goto give_sigsegv;
558
559 /* Cohere the trampoline with the I-cache. */
Paul Mundtb6138812007-11-11 15:53:51 +0900560 flush_cache_sigtramp(DEREF_REG_PR-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 }
562
563 /*
564 * Set up registers for signal handler.
565 * All edited pointers are subject to NEFF.
566 */
567 regs->regs[REG_SP] = (unsigned long) frame;
568 regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ?
569 (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP];
570 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
571
572 /* FIXME:
573 The glibc profiling support for SH-5 needs to be passed a sigcontext
574 so it can retrieve the PC. At some point during 2003 the glibc
575 support was changed to receive the sigcontext through the 2nd
576 argument, but there are still versions of libc.so in use that use
577 the 3rd argument. Until libc.so is stabilised, pass the sigcontext
578 through both 2nd and 3rd arguments.
579 */
580
581 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
582 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
583
584 regs->pc = (unsigned long) ka->sa.sa_handler;
585 regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc;
586
587 set_fs(USER_DS);
588
589#if DEBUG_SIG
590 /* Broken %016Lx */
591 printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
592 signal,
593 current->comm, current->pid, frame,
594 regs->pc >> 32, regs->pc & 0xffffffff,
595 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
596#endif
597
598 return;
599
600give_sigsegv:
601 force_sigsegv(sig, current);
602}
603
604static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
605 sigset_t *set, struct pt_regs *regs)
606{
607 struct rt_sigframe __user *frame;
608 int err = 0;
609 int signal;
610
611 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
612
613 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
614 goto give_sigsegv;
615
616 signal = current_thread_info()->exec_domain
617 && current_thread_info()->exec_domain->signal_invmap
618 && sig < 32
619 ? current_thread_info()->exec_domain->signal_invmap[sig]
620 : sig;
621
622 err |= __put_user(&frame->info, &frame->pinfo);
623 err |= __put_user(&frame->uc, &frame->puc);
624 err |= copy_siginfo_to_user(&frame->info, info);
625
626 /* Give up earlier as i386, in case */
627 if (err)
628 goto give_sigsegv;
629
630 /* Create the ucontext. */
631 err |= __put_user(0, &frame->uc.uc_flags);
632 err |= __put_user(0, &frame->uc.uc_link);
633 err |= __put_user((void *)current->sas_ss_sp,
634 &frame->uc.uc_stack.ss_sp);
635 err |= __put_user(sas_ss_flags(regs->regs[REG_SP]),
636 &frame->uc.uc_stack.ss_flags);
637 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
638 err |= setup_sigcontext(&frame->uc.uc_mcontext,
639 regs, set->sig[0]);
640 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
641
642 /* Give up earlier as i386, in case */
643 if (err)
644 goto give_sigsegv;
645
646 /* Set up to return from userspace. If provided, use a stub
647 already in userspace. */
648 if (ka->sa.sa_flags & SA_RESTORER) {
649 DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1;
650
651 /*
652 * On SH5 all edited pointers are subject to NEFF
653 */
654 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
655 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
656 } else {
657 /*
658 * Different approach on SH5.
659 * . Endianness independent asm code gets placed in entry.S .
660 * This is limited to four ASM instructions corresponding
661 * to two long longs in size.
662 * . err checking is done on the else branch only
663 * . flush_icache_range() is called upon __put_user() only
664 * . all edited pointers are subject to NEFF
665 * . being code, linker turns ShMedia bit on, always
666 * dereference index -1.
667 */
668
669 DEREF_REG_PR = (unsigned long) frame->retcode | 0x01;
670 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
671 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
672
673 if (__copy_to_user(frame->retcode,
674 (unsigned long long)sa_default_rt_restorer & (~1), 16) != 0)
675 goto give_sigsegv;
676
677 flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
678 }
679
680 /*
681 * Set up registers for signal handler.
682 * All edited pointers are subject to NEFF.
683 */
684 regs->regs[REG_SP] = (unsigned long) frame;
685 regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ?
686 (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP];
687 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
688 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
689 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
690 regs->pc = (unsigned long) ka->sa.sa_handler;
691 regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc;
692
693 set_fs(USER_DS);
694
695#if DEBUG_SIG
696 /* Broken %016Lx */
697 printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
698 signal,
699 current->comm, current->pid, frame,
700 regs->pc >> 32, regs->pc & 0xffffffff,
701 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
702#endif
703
704 return;
705
706give_sigsegv:
707 force_sigsegv(sig, current);
708}
709
710/*
711 * OK, we're invoking a handler
712 */
713
714static void
715handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
716 sigset_t *oldset, struct pt_regs * regs)
717{
718 /* Are we from a system call? */
719 if (regs->syscall_nr >= 0) {
720 /* If so, check system call restarting.. */
721 switch (regs->regs[REG_RET]) {
Paul Mundte227e8f2007-06-19 12:41:32 +0900722 case -ERESTART_RESTARTBLOCK:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 case -ERESTARTNOHAND:
Paul Mundtab99c732008-07-30 19:55:30 +0900724 no_system_call_restart:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 regs->regs[REG_RET] = -EINTR;
726 break;
727
728 case -ERESTARTSYS:
Paul Mundtab99c732008-07-30 19:55:30 +0900729 if (!(ka->sa.sa_flags & SA_RESTART))
730 goto no_system_call_restart;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 /* fallthrough */
732 case -ERESTARTNOINTR:
733 /* Decode syscall # */
734 regs->regs[REG_RET] = regs->syscall_nr;
735 regs->pc -= 4;
736 }
737 }
738
739 /* Set up the stack frame */
740 if (ka->sa.sa_flags & SA_SIGINFO)
741 setup_rt_frame(sig, ka, info, oldset, regs);
742 else
743 setup_frame(sig, ka, oldset, regs);
744
Steven Rostedt69be8f12005-08-29 11:44:09 -0400745 spin_lock_irq(&current->sighand->siglock);
746 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
747 if (!(ka->sa.sa_flags & SA_NODEFER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 sigaddset(&current->blocked,sig);
Steven Rostedt69be8f12005-08-29 11:44:09 -0400749 recalc_sigpending();
750 spin_unlock_irq(&current->sighand->siglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751}
752
Paul Mundtab99c732008-07-30 19:55:30 +0900753asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754{
Paul Mundtab99c732008-07-30 19:55:30 +0900755 if (thread_info_flags & _TIF_SIGPENDING)
756 do_signal(regs, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757
Paul Mundtab99c732008-07-30 19:55:30 +0900758 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
759 clear_thread_flag(TIF_NOTIFY_RESUME);
760 tracehook_notify_resume(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762}