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