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