blob: 7075c63bfc6f3417fd671d72a7c77bc1f9df9f15 [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
Al Viroa610d6e2012-05-21 23:42:15 -040046static void
Paul Mundt8a80a5e2008-09-17 23:14:36 +090047handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
Al Virob7f9a112012-05-02 09:59:21 -040048 struct pt_regs * regs);
Paul Mundt8a80a5e2008-09-17 23:14:36 +090049
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;
Paul Mundt94e2fb32008-12-10 19:46:18 +090063 break;
64
65 case -ERESTARTSYS:
66 if (!(sa->sa_flags & SA_RESTART))
67 goto no_system_call_restart;
68 /* fallthrough */
69 case -ERESTARTNOINTR:
70 /* Decode syscall # */
71 regs->regs[REG_RET] = regs->syscall_nr;
72 regs->pc -= 4;
73 break;
74 }
75}
76
Paul Mundtab99c732008-07-30 19:55:30 +090077/*
78 * Note that 'init' is a special process: it doesn't get signals it doesn't
79 * want to handle. Thus you cannot kill init even with a SIGKILL even by
80 * mistake.
81 *
82 * Note that we go through the signals twice: once to check the signals that
83 * the kernel can handle, and then we build all the user-level signal handling
84 * stack-frames in one go after that.
85 */
Al Viro9ef461a2012-04-22 01:16:34 -040086static void do_signal(struct pt_regs *regs)
Paul Mundtab99c732008-07-30 19:55:30 +090087{
88 siginfo_t info;
89 int signr;
90 struct k_sigaction ka;
91
92 /*
93 * We want the common case to go fast, which
94 * is why we may in certain cases get here from
95 * kernel mode. Just return without doing anything
96 * if so.
97 */
98 if (!user_mode(regs))
Al Viro9ef461a2012-04-22 01:16:34 -040099 return;
Paul Mundtab99c732008-07-30 19:55:30 +0900100
Paul Mundtab99c732008-07-30 19:55:30 +0900101 signr = get_signal_to_deliver(&info, &ka, regs, 0);
Paul Mundtab99c732008-07-30 19:55:30 +0900102 if (signr > 0) {
Paul Mundt03f07872009-01-29 11:21:38 +0900103 handle_syscall_restart(regs, &ka.sa);
Paul Mundt94e2fb32008-12-10 19:46:18 +0900104
Paul Mundtab99c732008-07-30 19:55:30 +0900105 /* Whee! Actually deliver the signal. */
Al Viroa610d6e2012-05-21 23:42:15 -0400106 handle_signal(signr, &info, &ka, regs);
Al Viro5754f412012-04-26 23:52:33 -0400107 return;
Paul Mundtab99c732008-07-30 19:55:30 +0900108 }
109
Paul Mundtab99c732008-07-30 19:55:30 +0900110 /* Did we come from a system call? */
111 if (regs->syscall_nr >= 0) {
112 /* Restart the system call - no handlers present */
113 switch (regs->regs[REG_RET]) {
114 case -ERESTARTNOHAND:
115 case -ERESTARTSYS:
116 case -ERESTARTNOINTR:
117 /* Decode Syscall # */
118 regs->regs[REG_RET] = regs->syscall_nr;
119 regs->pc -= 4;
120 break;
121
122 case -ERESTART_RESTARTBLOCK:
123 regs->regs[REG_RET] = __NR_restart_syscall;
124 regs->pc -= 4;
125 break;
126 }
127 }
128
129 /* No signal to deliver -- put the saved sigmask back */
Al Viro51a7b442012-05-21 23:33:55 -0400130 restore_saved_sigmask();
Paul Mundtab99c732008-07-30 19:55:30 +0900131}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
133/*
134 * Atomically swap in the new signal mask, and wait for a signal.
135 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136asmlinkage int
Al Viro9ef461a2012-04-22 01:16:34 -0400137sys_sigsuspend(old_sigset_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138{
Al Viro9ef461a2012-04-22 01:16:34 -0400139 sigset_t blocked;
Matt Fleming5e047fa2012-03-28 15:16:32 -0700140 siginitset(&blocked, mask);
Al Viro9ef461a2012-04-22 01:16:34 -0400141 return sigsuspend(&blocked);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142}
143
144asmlinkage int
145sys_sigaction(int sig, const struct old_sigaction __user *act,
146 struct old_sigaction __user *oact)
147{
148 struct k_sigaction new_ka, old_ka;
149 int ret;
150
151 if (act) {
152 old_sigset_t mask;
153 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
154 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
Al Viroa46808e2012-04-22 16:59:56 -0400155 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
156 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
157 __get_user(mask, &act->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159 siginitset(&new_ka.sa.sa_mask, mask);
160 }
161
162 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
163
164 if (!ret && oact) {
165 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
166 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
Al Viroa46808e2012-04-22 16:59:56 -0400167 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
168 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
169 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 }
172
173 return ret;
174}
175
176asmlinkage int
177sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
178 unsigned long r4, unsigned long r5, unsigned long r6,
179 unsigned long r7,
180 struct pt_regs * regs)
181{
182 return do_sigaltstack(uss, uoss, REF_REG_SP);
183}
184
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185/*
186 * Do a signal return; undo the signal stack.
187 */
Paul Mundt94e2fb32008-12-10 19:46:18 +0900188struct sigframe {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 struct sigcontext sc;
190 unsigned long extramask[_NSIG_WORDS-1];
191 long long retcode[2];
192};
193
Paul Mundt94e2fb32008-12-10 19:46:18 +0900194struct rt_sigframe {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 struct siginfo __user *pinfo;
196 void *puc;
197 struct siginfo info;
198 struct ucontext uc;
199 long long retcode[2];
200};
201
202#ifdef CONFIG_SH_FPU
203static inline int
204restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
205{
206 int err = 0;
207 int fpvalid;
208
209 err |= __get_user (fpvalid, &sc->sc_fpvalid);
210 conditional_used_math(fpvalid);
211 if (! fpvalid)
212 return err;
213
214 if (current == last_task_used_math) {
215 last_task_used_math = NULL;
216 regs->sr |= SR_FD;
217 }
218
Paul Mundt3ef29322010-01-19 15:40:03 +0900219 err |= __copy_from_user(&current->thread.xstate->hardfpu, &sc->sc_fpregs[0],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 (sizeof(long long) * 32) + (sizeof(int) * 1));
221
222 return err;
223}
224
225static inline int
226setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
227{
228 int err = 0;
229 int fpvalid;
230
231 fpvalid = !!used_math();
232 err |= __put_user(fpvalid, &sc->sc_fpvalid);
233 if (! fpvalid)
234 return err;
235
236 if (current == last_task_used_math) {
Paul Mundt600ee242007-11-19 19:13:38 +0900237 enable_fpu();
Matt Fleming61cc7b02009-12-14 20:12:04 +0000238 save_fpu(current);
Paul Mundt600ee242007-11-19 19:13:38 +0900239 disable_fpu();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 last_task_used_math = NULL;
241 regs->sr |= SR_FD;
242 }
243
Paul Mundt3ef29322010-01-19 15:40:03 +0900244 err |= __copy_to_user(&sc->sc_fpregs[0], &current->thread.xstate->hardfpu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 (sizeof(long long) * 32) + (sizeof(int) * 1));
246 clear_used_math();
247
248 return err;
249}
250#else
251static inline int
252restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900253{
254 return 0;
255}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256static inline int
257setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900258{
259 return 0;
260}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261#endif
262
263static int
264restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, long long *r2_p)
265{
266 unsigned int err = 0;
267 unsigned long long current_sr, new_sr;
268#define SR_MASK 0xffff8cfd
269
270#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
271
272 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
273 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
274 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
275 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
276 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
277 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
278 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
279 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
280 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
281 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
282 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
283 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
284 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
285 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
286 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
287 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
288 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
289 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
290
291 /* Prevent the signal handler manipulating SR in a way that can
292 crash the kernel. i.e. only allow S, Q, M, PR, SZ, FR to be
293 modified */
294 current_sr = regs->sr;
295 err |= __get_user(new_sr, &sc->sc_sr);
296 regs->sr &= SR_MASK;
297 regs->sr |= (new_sr & ~SR_MASK);
298
299 COPY(pc);
300
301#undef COPY
302
303 /* Must do this last in case it sets regs->sr.fd (i.e. after rest of sr
304 * has been restored above.) */
305 err |= restore_sigcontext_fpu(regs, sc);
306
307 regs->syscall_nr = -1; /* disable syscall checks */
308 err |= __get_user(*r2_p, &sc->sc_regs[REG_RET]);
309 return err;
310}
311
312asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
313 unsigned long r4, unsigned long r5,
314 unsigned long r6, unsigned long r7,
315 struct pt_regs * regs)
316{
317 struct sigframe __user *frame = (struct sigframe __user *) (long) REF_REG_SP;
318 sigset_t set;
319 long long ret;
320
Paul Mundt1bec1572008-09-24 14:37:35 +0900321 /* Always make any pending restarted system calls return -EINTR */
322 current_thread_info()->restart_block.fn = do_no_restart_syscall;
323
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
325 goto badframe;
326
327 if (__get_user(set.sig[0], &frame->sc.oldmask)
328 || (_NSIG_WORDS > 1
329 && __copy_from_user(&set.sig[1], &frame->extramask,
330 sizeof(frame->extramask))))
331 goto badframe;
332
333 sigdelsetmask(&set, ~_BLOCKABLE);
Matt Fleming5e047fa2012-03-28 15:16:32 -0700334 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335
336 if (restore_sigcontext(regs, &frame->sc, &ret))
337 goto badframe;
338 regs->pc -= 4;
339
340 return (int) ret;
341
342badframe:
343 force_sig(SIGSEGV, current);
344 return 0;
345}
346
347asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
348 unsigned long r4, unsigned long r5,
349 unsigned long r6, unsigned long r7,
350 struct pt_regs * regs)
351{
352 struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP;
353 sigset_t set;
354 stack_t __user st;
355 long long ret;
356
Paul Mundt1bec1572008-09-24 14:37:35 +0900357 /* Always make any pending restarted system calls return -EINTR */
358 current_thread_info()->restart_block.fn = do_no_restart_syscall;
359
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
361 goto badframe;
362
363 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
364 goto badframe;
365
366 sigdelsetmask(&set, ~_BLOCKABLE);
Matt Fleming5e047fa2012-03-28 15:16:32 -0700367 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
369 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret))
370 goto badframe;
371 regs->pc -= 4;
372
373 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
374 goto badframe;
375 /* It is more difficult to avoid calling this function than to
376 call it and ignore errors. */
377 do_sigaltstack(&st, NULL, REF_REG_SP);
378
379 return (int) ret;
380
381badframe:
382 force_sig(SIGSEGV, current);
383 return 0;
384}
385
386/*
387 * Set up a signal frame.
388 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389static int
390setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
391 unsigned long mask)
392{
393 int err = 0;
394
395 /* Do this first, otherwise is this sets sr->fd, that value isn't preserved. */
396 err |= setup_sigcontext_fpu(regs, sc);
397
398#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
399
400 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
401 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
402 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
403 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
404 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
405 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
406 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
407 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
408 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
409 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
410 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
411 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
412 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
413 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
414 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
415 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
416 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
417 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
418 COPY(sr); COPY(pc);
419
420#undef COPY
421
422 err |= __put_user(mask, &sc->oldmask);
423
424 return err;
425}
426
427/*
428 * Determine which stack to use..
429 */
430static inline void __user *
431get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
432{
Laurent MEYERd09042d2006-06-23 02:05:36 -0700433 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 sp = current->sas_ss_sp + current->sas_ss_size;
435
436 return (void __user *)((sp - frame_size) & -8ul);
437}
438
439void sa_default_restorer(void); /* See comments below */
440void sa_default_rt_restorer(void); /* See comments below */
441
Paul Mundt6ac03432008-12-10 19:26:44 +0900442static int setup_frame(int sig, struct k_sigaction *ka,
443 sigset_t *set, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444{
445 struct sigframe __user *frame;
446 int err = 0;
447 int signal;
448
449 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
450
451 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
452 goto give_sigsegv;
453
454 signal = current_thread_info()->exec_domain
455 && current_thread_info()->exec_domain->signal_invmap
456 && sig < 32
457 ? current_thread_info()->exec_domain->signal_invmap[sig]
458 : sig;
459
460 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
461
462 /* Give up earlier as i386, in case */
463 if (err)
464 goto give_sigsegv;
465
466 if (_NSIG_WORDS > 1) {
467 err |= __copy_to_user(frame->extramask, &set->sig[1],
468 sizeof(frame->extramask)); }
469
470 /* Give up earlier as i386, in case */
471 if (err)
472 goto give_sigsegv;
473
474 /* Set up to return from userspace. If provided, use a stub
475 already in userspace. */
476 if (ka->sa.sa_flags & SA_RESTORER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 /*
478 * On SH5 all edited pointers are subject to NEFF
479 */
Paul Mundtc7914832009-08-04 17:14:39 +0900480 DEREF_REG_PR = neff_sign_extend((unsigned long)
481 ka->sa.sa_restorer | 0x1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 } else {
483 /*
484 * Different approach on SH5.
485 * . Endianness independent asm code gets placed in entry.S .
486 * This is limited to four ASM instructions corresponding
487 * to two long longs in size.
488 * . err checking is done on the else branch only
489 * . flush_icache_range() is called upon __put_user() only
490 * . all edited pointers are subject to NEFF
491 * . being code, linker turns ShMedia bit on, always
492 * dereference index -1.
493 */
Paul Mundtc7914832009-08-04 17:14:39 +0900494 DEREF_REG_PR = neff_sign_extend((unsigned long)
495 frame->retcode | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496
497 if (__copy_to_user(frame->retcode,
Paul Mundt091db042008-09-29 19:44:40 +0900498 (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 goto give_sigsegv;
500
501 /* Cohere the trampoline with the I-cache. */
Paul Mundtb6138812007-11-11 15:53:51 +0900502 flush_cache_sigtramp(DEREF_REG_PR-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 }
504
505 /*
506 * Set up registers for signal handler.
507 * All edited pointers are subject to NEFF.
508 */
Paul Mundtc7914832009-08-04 17:14:39 +0900509 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
511
512 /* FIXME:
513 The glibc profiling support for SH-5 needs to be passed a sigcontext
514 so it can retrieve the PC. At some point during 2003 the glibc
515 support was changed to receive the sigcontext through the 2nd
516 argument, but there are still versions of libc.so in use that use
517 the 3rd argument. Until libc.so is stabilised, pass the sigcontext
518 through both 2nd and 3rd arguments.
519 */
520
521 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
522 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
523
Paul Mundtc7914832009-08-04 17:14:39 +0900524 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
526 set_fs(USER_DS);
527
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 /* Broken %016Lx */
Paul Mundt6ac03432008-12-10 19:26:44 +0900529 pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
530 signal, current->comm, current->pid, frame,
531 regs->pc >> 32, regs->pc & 0xffffffff,
532 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533
Paul Mundt6ac03432008-12-10 19:26:44 +0900534 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535
536give_sigsegv:
537 force_sigsegv(sig, current);
Paul Mundt6ac03432008-12-10 19:26:44 +0900538 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539}
540
Paul Mundt6ac03432008-12-10 19:26:44 +0900541static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
542 sigset_t *set, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543{
544 struct rt_sigframe __user *frame;
545 int err = 0;
546 int signal;
547
548 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
549
550 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
551 goto give_sigsegv;
552
553 signal = current_thread_info()->exec_domain
554 && current_thread_info()->exec_domain->signal_invmap
555 && sig < 32
556 ? current_thread_info()->exec_domain->signal_invmap[sig]
557 : sig;
558
559 err |= __put_user(&frame->info, &frame->pinfo);
560 err |= __put_user(&frame->uc, &frame->puc);
561 err |= copy_siginfo_to_user(&frame->info, info);
562
563 /* Give up earlier as i386, in case */
564 if (err)
565 goto give_sigsegv;
566
567 /* Create the ucontext. */
568 err |= __put_user(0, &frame->uc.uc_flags);
569 err |= __put_user(0, &frame->uc.uc_link);
570 err |= __put_user((void *)current->sas_ss_sp,
571 &frame->uc.uc_stack.ss_sp);
572 err |= __put_user(sas_ss_flags(regs->regs[REG_SP]),
573 &frame->uc.uc_stack.ss_flags);
574 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
575 err |= setup_sigcontext(&frame->uc.uc_mcontext,
576 regs, set->sig[0]);
577 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
578
579 /* Give up earlier as i386, in case */
580 if (err)
581 goto give_sigsegv;
582
583 /* Set up to return from userspace. If provided, use a stub
584 already in userspace. */
585 if (ka->sa.sa_flags & SA_RESTORER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 /*
587 * On SH5 all edited pointers are subject to NEFF
588 */
Paul Mundtc7914832009-08-04 17:14:39 +0900589 DEREF_REG_PR = neff_sign_extend((unsigned long)
590 ka->sa.sa_restorer | 0x1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 } else {
592 /*
593 * Different approach on SH5.
594 * . Endianness independent asm code gets placed in entry.S .
595 * This is limited to four ASM instructions corresponding
596 * to two long longs in size.
597 * . err checking is done on the else branch only
598 * . flush_icache_range() is called upon __put_user() only
599 * . all edited pointers are subject to NEFF
600 * . being code, linker turns ShMedia bit on, always
601 * dereference index -1.
602 */
Paul Mundtc7914832009-08-04 17:14:39 +0900603 DEREF_REG_PR = neff_sign_extend((unsigned long)
604 frame->retcode | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605
606 if (__copy_to_user(frame->retcode,
Paul Mundt091db042008-09-29 19:44:40 +0900607 (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 goto give_sigsegv;
609
Paul Mundtc7914832009-08-04 17:14:39 +0900610 /* Cohere the trampoline with the I-cache. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
612 }
613
614 /*
615 * Set up registers for signal handler.
616 * All edited pointers are subject to NEFF.
617 */
Paul Mundtc7914832009-08-04 17:14:39 +0900618 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
620 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
621 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
Paul Mundtc7914832009-08-04 17:14:39 +0900622 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623
624 set_fs(USER_DS);
625
Paul Mundt6ac03432008-12-10 19:26:44 +0900626 pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
627 signal, current->comm, current->pid, frame,
628 regs->pc >> 32, regs->pc & 0xffffffff,
629 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
Paul Mundt6ac03432008-12-10 19:26:44 +0900631 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
633give_sigsegv:
634 force_sigsegv(sig, current);
Paul Mundt6ac03432008-12-10 19:26:44 +0900635 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636}
637
638/*
639 * OK, we're invoking a handler
640 */
Al Viroa610d6e2012-05-21 23:42:15 -0400641static void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
Al Virob7f9a112012-05-02 09:59:21 -0400643 struct pt_regs * regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644{
Al Virob7f9a112012-05-02 09:59:21 -0400645 sigset_t *oldset = sigmask_to_save();
Paul Mundt6ac03432008-12-10 19:26:44 +0900646 int ret;
647
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 /* Set up the stack frame */
649 if (ka->sa.sa_flags & SA_SIGINFO)
Paul Mundt6ac03432008-12-10 19:26:44 +0900650 ret = setup_rt_frame(sig, ka, info, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 else
Paul Mundt6ac03432008-12-10 19:26:44 +0900652 ret = setup_frame(sig, ka, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
Al Viroa610d6e2012-05-21 23:42:15 -0400654 if (ret)
655 return;
Paul Mundt6ac03432008-12-10 19:26:44 +0900656
Al Viroa610d6e2012-05-21 23:42:15 -0400657 block_sigmask(ka, sig);
658 tracehook_signal_handler(sig, info, ka, regs,
659 test_thread_flag(TIF_SINGLESTEP));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660}
661
Paul Mundtab99c732008-07-30 19:55:30 +0900662asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663{
Paul Mundtab99c732008-07-30 19:55:30 +0900664 if (thread_info_flags & _TIF_SIGPENDING)
Al Viro9ef461a2012-04-22 01:16:34 -0400665 do_signal(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666
Paul Mundtab99c732008-07-30 19:55:30 +0900667 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
668 clear_thread_flag(TIF_NOTIFY_RESUME);
669 tracehook_notify_resume(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671}