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