blob: 6b5b3dfe886b2d3c15a4b08a4d4f21ab74e90da0 [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
Al Viroa610d6e2012-05-21 23:42:15 -040044static void
Paul Mundt8a80a5e2008-09-17 23:14:36 +090045handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
Al Virob7f9a112012-05-02 09:59:21 -040046 struct pt_regs * regs);
Paul Mundt8a80a5e2008-09-17 23:14:36 +090047
Paul Mundt94e2fb32008-12-10 19:46:18 +090048static inline void
49handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
50{
51 /* If we're not from a syscall, bail out */
52 if (regs->syscall_nr < 0)
53 return;
54
55 /* check for system call restart.. */
56 switch (regs->regs[REG_RET]) {
57 case -ERESTART_RESTARTBLOCK:
58 case -ERESTARTNOHAND:
59 no_system_call_restart:
60 regs->regs[REG_RET] = -EINTR;
Paul Mundt94e2fb32008-12-10 19:46:18 +090061 break;
62
63 case -ERESTARTSYS:
64 if (!(sa->sa_flags & SA_RESTART))
65 goto no_system_call_restart;
66 /* fallthrough */
67 case -ERESTARTNOINTR:
68 /* Decode syscall # */
69 regs->regs[REG_RET] = regs->syscall_nr;
70 regs->pc -= 4;
71 break;
72 }
73}
74
Paul Mundtab99c732008-07-30 19:55:30 +090075/*
76 * Note that 'init' is a special process: it doesn't get signals it doesn't
77 * want to handle. Thus you cannot kill init even with a SIGKILL even by
78 * mistake.
79 *
80 * Note that we go through the signals twice: once to check the signals that
81 * the kernel can handle, and then we build all the user-level signal handling
82 * stack-frames in one go after that.
83 */
Al Viro9ef461a2012-04-22 01:16:34 -040084static void do_signal(struct pt_regs *regs)
Paul Mundtab99c732008-07-30 19:55:30 +090085{
86 siginfo_t info;
87 int signr;
88 struct k_sigaction ka;
89
90 /*
91 * We want the common case to go fast, which
92 * is why we may in certain cases get here from
93 * kernel mode. Just return without doing anything
94 * if so.
95 */
96 if (!user_mode(regs))
Al Viro9ef461a2012-04-22 01:16:34 -040097 return;
Paul Mundtab99c732008-07-30 19:55:30 +090098
Paul Mundtab99c732008-07-30 19:55:30 +090099 signr = get_signal_to_deliver(&info, &ka, regs, 0);
Paul Mundtab99c732008-07-30 19:55:30 +0900100 if (signr > 0) {
Paul Mundt03f07872009-01-29 11:21:38 +0900101 handle_syscall_restart(regs, &ka.sa);
Paul Mundt94e2fb32008-12-10 19:46:18 +0900102
Paul Mundtab99c732008-07-30 19:55:30 +0900103 /* Whee! Actually deliver the signal. */
Al Viroa610d6e2012-05-21 23:42:15 -0400104 handle_signal(signr, &info, &ka, regs);
Al Viro5754f412012-04-26 23:52:33 -0400105 return;
Paul Mundtab99c732008-07-30 19:55:30 +0900106 }
107
Paul Mundtab99c732008-07-30 19:55:30 +0900108 /* Did we come from a system call? */
109 if (regs->syscall_nr >= 0) {
110 /* Restart the system call - no handlers present */
111 switch (regs->regs[REG_RET]) {
112 case -ERESTARTNOHAND:
113 case -ERESTARTSYS:
114 case -ERESTARTNOINTR:
115 /* Decode Syscall # */
116 regs->regs[REG_RET] = regs->syscall_nr;
117 regs->pc -= 4;
118 break;
119
120 case -ERESTART_RESTARTBLOCK:
121 regs->regs[REG_RET] = __NR_restart_syscall;
122 regs->pc -= 4;
123 break;
124 }
125 }
126
127 /* No signal to deliver -- put the saved sigmask back */
Al Viro51a7b442012-05-21 23:33:55 -0400128 restore_saved_sigmask();
Paul Mundtab99c732008-07-30 19:55:30 +0900129}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
131/*
132 * Atomically swap in the new signal mask, and wait for a signal.
133 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134asmlinkage int
Al Viro9ef461a2012-04-22 01:16:34 -0400135sys_sigsuspend(old_sigset_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136{
Al Viro9ef461a2012-04-22 01:16:34 -0400137 sigset_t blocked;
Matt Fleming5e047fa2012-03-28 15:16:32 -0700138 siginitset(&blocked, mask);
Al Viro9ef461a2012-04-22 01:16:34 -0400139 return sigsuspend(&blocked);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140}
141
142asmlinkage int
143sys_sigaction(int sig, const struct old_sigaction __user *act,
144 struct old_sigaction __user *oact)
145{
146 struct k_sigaction new_ka, old_ka;
147 int ret;
148
149 if (act) {
150 old_sigset_t mask;
151 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
152 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
Al Viroa46808e2012-04-22 16:59:56 -0400153 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
154 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
155 __get_user(mask, &act->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 siginitset(&new_ka.sa.sa_mask, mask);
158 }
159
160 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
161
162 if (!ret && oact) {
163 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
164 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
Al Viroa46808e2012-04-22 16:59:56 -0400165 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
166 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
167 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 }
170
171 return ret;
172}
173
174asmlinkage int
175sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
176 unsigned long r4, unsigned long r5, unsigned long r6,
177 unsigned long r7,
178 struct pt_regs * regs)
179{
180 return do_sigaltstack(uss, uoss, REF_REG_SP);
181}
182
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183/*
184 * Do a signal return; undo the signal stack.
185 */
Paul Mundt94e2fb32008-12-10 19:46:18 +0900186struct sigframe {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 struct sigcontext sc;
188 unsigned long extramask[_NSIG_WORDS-1];
189 long long retcode[2];
190};
191
Paul Mundt94e2fb32008-12-10 19:46:18 +0900192struct rt_sigframe {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 struct siginfo __user *pinfo;
194 void *puc;
195 struct siginfo info;
196 struct ucontext uc;
197 long long retcode[2];
198};
199
200#ifdef CONFIG_SH_FPU
201static inline int
202restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
203{
204 int err = 0;
205 int fpvalid;
206
207 err |= __get_user (fpvalid, &sc->sc_fpvalid);
208 conditional_used_math(fpvalid);
209 if (! fpvalid)
210 return err;
211
212 if (current == last_task_used_math) {
213 last_task_used_math = NULL;
214 regs->sr |= SR_FD;
215 }
216
Paul Mundt3ef29322010-01-19 15:40:03 +0900217 err |= __copy_from_user(&current->thread.xstate->hardfpu, &sc->sc_fpregs[0],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 (sizeof(long long) * 32) + (sizeof(int) * 1));
219
220 return err;
221}
222
223static inline int
224setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
225{
226 int err = 0;
227 int fpvalid;
228
229 fpvalid = !!used_math();
230 err |= __put_user(fpvalid, &sc->sc_fpvalid);
231 if (! fpvalid)
232 return err;
233
234 if (current == last_task_used_math) {
Paul Mundt600ee242007-11-19 19:13:38 +0900235 enable_fpu();
Matt Fleming61cc7b02009-12-14 20:12:04 +0000236 save_fpu(current);
Paul Mundt600ee242007-11-19 19:13:38 +0900237 disable_fpu();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 last_task_used_math = NULL;
239 regs->sr |= SR_FD;
240 }
241
Paul Mundt3ef29322010-01-19 15:40:03 +0900242 err |= __copy_to_user(&sc->sc_fpregs[0], &current->thread.xstate->hardfpu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 (sizeof(long long) * 32) + (sizeof(int) * 1));
244 clear_used_math();
245
246 return err;
247}
248#else
249static inline int
250restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900251{
252 return 0;
253}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254static inline int
255setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900256{
257 return 0;
258}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259#endif
260
261static int
262restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, long long *r2_p)
263{
264 unsigned int err = 0;
265 unsigned long long current_sr, new_sr;
266#define SR_MASK 0xffff8cfd
267
268#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
269
270 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
271 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
272 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
273 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
274 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
275 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
276 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
277 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
278 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
279 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
280 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
281 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
282 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
283 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
284 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
285 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
286 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
287 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
288
289 /* Prevent the signal handler manipulating SR in a way that can
290 crash the kernel. i.e. only allow S, Q, M, PR, SZ, FR to be
291 modified */
292 current_sr = regs->sr;
293 err |= __get_user(new_sr, &sc->sc_sr);
294 regs->sr &= SR_MASK;
295 regs->sr |= (new_sr & ~SR_MASK);
296
297 COPY(pc);
298
299#undef COPY
300
301 /* Must do this last in case it sets regs->sr.fd (i.e. after rest of sr
302 * has been restored above.) */
303 err |= restore_sigcontext_fpu(regs, sc);
304
305 regs->syscall_nr = -1; /* disable syscall checks */
306 err |= __get_user(*r2_p, &sc->sc_regs[REG_RET]);
307 return err;
308}
309
310asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
311 unsigned long r4, unsigned long r5,
312 unsigned long r6, unsigned long r7,
313 struct pt_regs * regs)
314{
315 struct sigframe __user *frame = (struct sigframe __user *) (long) REF_REG_SP;
316 sigset_t set;
317 long long ret;
318
Paul Mundt1bec1572008-09-24 14:37:35 +0900319 /* Always make any pending restarted system calls return -EINTR */
320 current_thread_info()->restart_block.fn = do_no_restart_syscall;
321
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
323 goto badframe;
324
325 if (__get_user(set.sig[0], &frame->sc.oldmask)
326 || (_NSIG_WORDS > 1
327 && __copy_from_user(&set.sig[1], &frame->extramask,
328 sizeof(frame->extramask))))
329 goto badframe;
330
Matt Fleming5e047fa2012-03-28 15:16:32 -0700331 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332
333 if (restore_sigcontext(regs, &frame->sc, &ret))
334 goto badframe;
335 regs->pc -= 4;
336
337 return (int) ret;
338
339badframe:
340 force_sig(SIGSEGV, current);
341 return 0;
342}
343
344asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
345 unsigned long r4, unsigned long r5,
346 unsigned long r6, unsigned long r7,
347 struct pt_regs * regs)
348{
349 struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP;
350 sigset_t set;
351 stack_t __user st;
352 long long ret;
353
Paul Mundt1bec1572008-09-24 14:37:35 +0900354 /* Always make any pending restarted system calls return -EINTR */
355 current_thread_info()->restart_block.fn = do_no_restart_syscall;
356
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
358 goto badframe;
359
360 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
361 goto badframe;
362
Matt Fleming5e047fa2012-03-28 15:16:32 -0700363 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
365 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret))
366 goto badframe;
367 regs->pc -= 4;
368
369 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
370 goto badframe;
371 /* It is more difficult to avoid calling this function than to
372 call it and ignore errors. */
373 do_sigaltstack(&st, NULL, REF_REG_SP);
374
375 return (int) ret;
376
377badframe:
378 force_sig(SIGSEGV, current);
379 return 0;
380}
381
382/*
383 * Set up a signal frame.
384 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385static int
386setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
387 unsigned long mask)
388{
389 int err = 0;
390
391 /* Do this first, otherwise is this sets sr->fd, that value isn't preserved. */
392 err |= setup_sigcontext_fpu(regs, sc);
393
394#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
395
396 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
397 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
398 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
399 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
400 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
401 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
402 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
403 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
404 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
405 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
406 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
407 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
408 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
409 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
410 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
411 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
412 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
413 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
414 COPY(sr); COPY(pc);
415
416#undef COPY
417
418 err |= __put_user(mask, &sc->oldmask);
419
420 return err;
421}
422
423/*
424 * Determine which stack to use..
425 */
426static inline void __user *
427get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
428{
Laurent MEYERd09042d2006-06-23 02:05:36 -0700429 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 sp = current->sas_ss_sp + current->sas_ss_size;
431
432 return (void __user *)((sp - frame_size) & -8ul);
433}
434
435void sa_default_restorer(void); /* See comments below */
436void sa_default_rt_restorer(void); /* See comments below */
437
Paul Mundt6ac03432008-12-10 19:26:44 +0900438static int setup_frame(int sig, struct k_sigaction *ka,
439 sigset_t *set, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440{
441 struct sigframe __user *frame;
442 int err = 0;
443 int signal;
444
445 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
446
447 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
448 goto give_sigsegv;
449
450 signal = current_thread_info()->exec_domain
451 && current_thread_info()->exec_domain->signal_invmap
452 && sig < 32
453 ? current_thread_info()->exec_domain->signal_invmap[sig]
454 : sig;
455
456 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
457
458 /* Give up earlier as i386, in case */
459 if (err)
460 goto give_sigsegv;
461
462 if (_NSIG_WORDS > 1) {
463 err |= __copy_to_user(frame->extramask, &set->sig[1],
464 sizeof(frame->extramask)); }
465
466 /* Give up earlier as i386, in case */
467 if (err)
468 goto give_sigsegv;
469
470 /* Set up to return from userspace. If provided, use a stub
471 already in userspace. */
472 if (ka->sa.sa_flags & SA_RESTORER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 /*
474 * On SH5 all edited pointers are subject to NEFF
475 */
Paul Mundtc7914832009-08-04 17:14:39 +0900476 DEREF_REG_PR = neff_sign_extend((unsigned long)
477 ka->sa.sa_restorer | 0x1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 } else {
479 /*
480 * Different approach on SH5.
481 * . Endianness independent asm code gets placed in entry.S .
482 * This is limited to four ASM instructions corresponding
483 * to two long longs in size.
484 * . err checking is done on the else branch only
485 * . flush_icache_range() is called upon __put_user() only
486 * . all edited pointers are subject to NEFF
487 * . being code, linker turns ShMedia bit on, always
488 * dereference index -1.
489 */
Paul Mundtc7914832009-08-04 17:14:39 +0900490 DEREF_REG_PR = neff_sign_extend((unsigned long)
491 frame->retcode | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492
493 if (__copy_to_user(frame->retcode,
Paul Mundt091db042008-09-29 19:44:40 +0900494 (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 goto give_sigsegv;
496
497 /* Cohere the trampoline with the I-cache. */
Paul Mundtb6138812007-11-11 15:53:51 +0900498 flush_cache_sigtramp(DEREF_REG_PR-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 }
500
501 /*
502 * Set up registers for signal handler.
503 * All edited pointers are subject to NEFF.
504 */
Paul Mundtc7914832009-08-04 17:14:39 +0900505 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
507
508 /* FIXME:
509 The glibc profiling support for SH-5 needs to be passed a sigcontext
510 so it can retrieve the PC. At some point during 2003 the glibc
511 support was changed to receive the sigcontext through the 2nd
512 argument, but there are still versions of libc.so in use that use
513 the 3rd argument. Until libc.so is stabilised, pass the sigcontext
514 through both 2nd and 3rd arguments.
515 */
516
517 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
518 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
519
Paul Mundtc7914832009-08-04 17:14:39 +0900520 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521
522 set_fs(USER_DS);
523
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 /* Broken %016Lx */
Paul Mundt6ac03432008-12-10 19:26:44 +0900525 pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
526 signal, current->comm, current->pid, frame,
527 regs->pc >> 32, regs->pc & 0xffffffff,
528 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529
Paul Mundt6ac03432008-12-10 19:26:44 +0900530 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531
532give_sigsegv:
533 force_sigsegv(sig, current);
Paul Mundt6ac03432008-12-10 19:26:44 +0900534 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535}
536
Paul Mundt6ac03432008-12-10 19:26:44 +0900537static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
538 sigset_t *set, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539{
540 struct rt_sigframe __user *frame;
541 int err = 0;
542 int signal;
543
544 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
545
546 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
547 goto give_sigsegv;
548
549 signal = current_thread_info()->exec_domain
550 && current_thread_info()->exec_domain->signal_invmap
551 && sig < 32
552 ? current_thread_info()->exec_domain->signal_invmap[sig]
553 : sig;
554
555 err |= __put_user(&frame->info, &frame->pinfo);
556 err |= __put_user(&frame->uc, &frame->puc);
557 err |= copy_siginfo_to_user(&frame->info, info);
558
559 /* Give up earlier as i386, in case */
560 if (err)
561 goto give_sigsegv;
562
563 /* Create the ucontext. */
564 err |= __put_user(0, &frame->uc.uc_flags);
565 err |= __put_user(0, &frame->uc.uc_link);
566 err |= __put_user((void *)current->sas_ss_sp,
567 &frame->uc.uc_stack.ss_sp);
568 err |= __put_user(sas_ss_flags(regs->regs[REG_SP]),
569 &frame->uc.uc_stack.ss_flags);
570 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
571 err |= setup_sigcontext(&frame->uc.uc_mcontext,
572 regs, set->sig[0]);
573 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
574
575 /* Give up earlier as i386, in case */
576 if (err)
577 goto give_sigsegv;
578
579 /* Set up to return from userspace. If provided, use a stub
580 already in userspace. */
581 if (ka->sa.sa_flags & SA_RESTORER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 /*
583 * On SH5 all edited pointers are subject to NEFF
584 */
Paul Mundtc7914832009-08-04 17:14:39 +0900585 DEREF_REG_PR = neff_sign_extend((unsigned long)
586 ka->sa.sa_restorer | 0x1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 } else {
588 /*
589 * Different approach on SH5.
590 * . Endianness independent asm code gets placed in entry.S .
591 * This is limited to four ASM instructions corresponding
592 * to two long longs in size.
593 * . err checking is done on the else branch only
594 * . flush_icache_range() is called upon __put_user() only
595 * . all edited pointers are subject to NEFF
596 * . being code, linker turns ShMedia bit on, always
597 * dereference index -1.
598 */
Paul Mundtc7914832009-08-04 17:14:39 +0900599 DEREF_REG_PR = neff_sign_extend((unsigned long)
600 frame->retcode | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601
602 if (__copy_to_user(frame->retcode,
Paul Mundt091db042008-09-29 19:44:40 +0900603 (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 goto give_sigsegv;
605
Paul Mundtc7914832009-08-04 17:14:39 +0900606 /* Cohere the trampoline with the I-cache. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
608 }
609
610 /*
611 * Set up registers for signal handler.
612 * All edited pointers are subject to NEFF.
613 */
Paul Mundtc7914832009-08-04 17:14:39 +0900614 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
616 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
617 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
Paul Mundtc7914832009-08-04 17:14:39 +0900618 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619
620 set_fs(USER_DS);
621
Paul Mundt6ac03432008-12-10 19:26:44 +0900622 pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
623 signal, current->comm, current->pid, frame,
624 regs->pc >> 32, regs->pc & 0xffffffff,
625 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626
Paul Mundt6ac03432008-12-10 19:26:44 +0900627 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628
629give_sigsegv:
630 force_sigsegv(sig, current);
Paul Mundt6ac03432008-12-10 19:26:44 +0900631 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632}
633
634/*
635 * OK, we're invoking a handler
636 */
Al Viroa610d6e2012-05-21 23:42:15 -0400637static void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
Al Virob7f9a112012-05-02 09:59:21 -0400639 struct pt_regs * regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640{
Al Virob7f9a112012-05-02 09:59:21 -0400641 sigset_t *oldset = sigmask_to_save();
Paul Mundt6ac03432008-12-10 19:26:44 +0900642 int ret;
643
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 /* Set up the stack frame */
645 if (ka->sa.sa_flags & SA_SIGINFO)
Paul Mundt6ac03432008-12-10 19:26:44 +0900646 ret = setup_rt_frame(sig, ka, info, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 else
Paul Mundt6ac03432008-12-10 19:26:44 +0900648 ret = setup_frame(sig, ka, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649
Al Viroa610d6e2012-05-21 23:42:15 -0400650 if (ret)
651 return;
Paul Mundt6ac03432008-12-10 19:26:44 +0900652
Al Viroefee9842012-04-28 02:04:15 -0400653 signal_delivered(sig, info, ka, regs,
Al Viroa610d6e2012-05-21 23:42:15 -0400654 test_thread_flag(TIF_SINGLESTEP));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655}
656
Paul Mundtab99c732008-07-30 19:55:30 +0900657asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658{
Paul Mundtab99c732008-07-30 19:55:30 +0900659 if (thread_info_flags & _TIF_SIGPENDING)
Al Viro9ef461a2012-04-22 01:16:34 -0400660 do_signal(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661
Paul Mundtab99c732008-07-30 19:55:30 +0900662 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
663 clear_thread_flag(TIF_NOTIFY_RESUME);
664 tracehook_notify_resume(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666}