blob: cc22d2b2e3f2a0d3ad9d8bde5c3122c12dd28b81 [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,
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 Virob7f9a112012-05-02 09:59:21 -0400106 if (handle_signal(signr, &info, &ka, regs) == 0) {
Paul Mundt6ac03432008-12-10 19:26:44 +0900107 /*
108 * If a signal was successfully delivered, the
109 * saved sigmask is in its frame, and we can
Paul Mundt56bfc422009-10-14 16:05:42 +0900110 * clear the TS_RESTORE_SIGMASK flag.
Paul Mundt6ac03432008-12-10 19:26:44 +0900111 */
Paul Mundt56bfc422009-10-14 16:05:42 +0900112 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
Paul Mundt4b505db2010-02-15 14:17:45 +0900113
114 tracehook_signal_handler(signr, &info, &ka, regs,
115 test_thread_flag(TIF_SINGLESTEP));
Al Viro9ef461a2012-04-22 01:16:34 -0400116 return;
Paul Mundt6ac03432008-12-10 19:26:44 +0900117 }
Paul Mundtab99c732008-07-30 19:55:30 +0900118 }
119
Paul Mundtab99c732008-07-30 19:55:30 +0900120 /* Did we come from a system call? */
121 if (regs->syscall_nr >= 0) {
122 /* Restart the system call - no handlers present */
123 switch (regs->regs[REG_RET]) {
124 case -ERESTARTNOHAND:
125 case -ERESTARTSYS:
126 case -ERESTARTNOINTR:
127 /* Decode Syscall # */
128 regs->regs[REG_RET] = regs->syscall_nr;
129 regs->pc -= 4;
130 break;
131
132 case -ERESTART_RESTARTBLOCK:
133 regs->regs[REG_RET] = __NR_restart_syscall;
134 regs->pc -= 4;
135 break;
136 }
137 }
138
139 /* No signal to deliver -- put the saved sigmask back */
Al Viro51a7b442012-05-21 23:33:55 -0400140 restore_saved_sigmask();
Paul Mundtab99c732008-07-30 19:55:30 +0900141}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
143/*
144 * Atomically swap in the new signal mask, and wait for a signal.
145 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146asmlinkage int
Al Viro9ef461a2012-04-22 01:16:34 -0400147sys_sigsuspend(old_sigset_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148{
Al Viro9ef461a2012-04-22 01:16:34 -0400149 sigset_t blocked;
Matt Fleming5e047fa2012-03-28 15:16:32 -0700150 siginitset(&blocked, mask);
Al Viro9ef461a2012-04-22 01:16:34 -0400151 return sigsuspend(&blocked);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152}
153
154asmlinkage int
155sys_sigaction(int sig, const struct old_sigaction __user *act,
156 struct old_sigaction __user *oact)
157{
158 struct k_sigaction new_ka, old_ka;
159 int ret;
160
161 if (act) {
162 old_sigset_t mask;
163 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
164 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
Al Viroa46808e2012-04-22 16:59:56 -0400165 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
166 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
167 __get_user(mask, &act->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 siginitset(&new_ka.sa.sa_mask, mask);
170 }
171
172 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
173
174 if (!ret && oact) {
175 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
176 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
Al Viroa46808e2012-04-22 16:59:56 -0400177 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
178 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
179 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 }
182
183 return ret;
184}
185
186asmlinkage int
187sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
188 unsigned long r4, unsigned long r5, unsigned long r6,
189 unsigned long r7,
190 struct pt_regs * regs)
191{
192 return do_sigaltstack(uss, uoss, REF_REG_SP);
193}
194
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195/*
196 * Do a signal return; undo the signal stack.
197 */
Paul Mundt94e2fb32008-12-10 19:46:18 +0900198struct sigframe {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 struct sigcontext sc;
200 unsigned long extramask[_NSIG_WORDS-1];
201 long long retcode[2];
202};
203
Paul Mundt94e2fb32008-12-10 19:46:18 +0900204struct rt_sigframe {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 struct siginfo __user *pinfo;
206 void *puc;
207 struct siginfo info;
208 struct ucontext uc;
209 long long retcode[2];
210};
211
212#ifdef CONFIG_SH_FPU
213static inline int
214restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
215{
216 int err = 0;
217 int fpvalid;
218
219 err |= __get_user (fpvalid, &sc->sc_fpvalid);
220 conditional_used_math(fpvalid);
221 if (! fpvalid)
222 return err;
223
224 if (current == last_task_used_math) {
225 last_task_used_math = NULL;
226 regs->sr |= SR_FD;
227 }
228
Paul Mundt3ef29322010-01-19 15:40:03 +0900229 err |= __copy_from_user(&current->thread.xstate->hardfpu, &sc->sc_fpregs[0],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 (sizeof(long long) * 32) + (sizeof(int) * 1));
231
232 return err;
233}
234
235static inline int
236setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
237{
238 int err = 0;
239 int fpvalid;
240
241 fpvalid = !!used_math();
242 err |= __put_user(fpvalid, &sc->sc_fpvalid);
243 if (! fpvalid)
244 return err;
245
246 if (current == last_task_used_math) {
Paul Mundt600ee242007-11-19 19:13:38 +0900247 enable_fpu();
Matt Fleming61cc7b02009-12-14 20:12:04 +0000248 save_fpu(current);
Paul Mundt600ee242007-11-19 19:13:38 +0900249 disable_fpu();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 last_task_used_math = NULL;
251 regs->sr |= SR_FD;
252 }
253
Paul Mundt3ef29322010-01-19 15:40:03 +0900254 err |= __copy_to_user(&sc->sc_fpregs[0], &current->thread.xstate->hardfpu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 (sizeof(long long) * 32) + (sizeof(int) * 1));
256 clear_used_math();
257
258 return err;
259}
260#else
261static inline int
262restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900263{
264 return 0;
265}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266static inline int
267setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900268{
269 return 0;
270}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271#endif
272
273static int
274restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, long long *r2_p)
275{
276 unsigned int err = 0;
277 unsigned long long current_sr, new_sr;
278#define SR_MASK 0xffff8cfd
279
280#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
281
282 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
283 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
284 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
285 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
286 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
287 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
288 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
289 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
290 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
291 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
292 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
293 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
294 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
295 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
296 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
297 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
298 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
299 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
300
301 /* Prevent the signal handler manipulating SR in a way that can
302 crash the kernel. i.e. only allow S, Q, M, PR, SZ, FR to be
303 modified */
304 current_sr = regs->sr;
305 err |= __get_user(new_sr, &sc->sc_sr);
306 regs->sr &= SR_MASK;
307 regs->sr |= (new_sr & ~SR_MASK);
308
309 COPY(pc);
310
311#undef COPY
312
313 /* Must do this last in case it sets regs->sr.fd (i.e. after rest of sr
314 * has been restored above.) */
315 err |= restore_sigcontext_fpu(regs, sc);
316
317 regs->syscall_nr = -1; /* disable syscall checks */
318 err |= __get_user(*r2_p, &sc->sc_regs[REG_RET]);
319 return err;
320}
321
322asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
323 unsigned long r4, unsigned long r5,
324 unsigned long r6, unsigned long r7,
325 struct pt_regs * regs)
326{
327 struct sigframe __user *frame = (struct sigframe __user *) (long) REF_REG_SP;
328 sigset_t set;
329 long long ret;
330
Paul Mundt1bec1572008-09-24 14:37:35 +0900331 /* Always make any pending restarted system calls return -EINTR */
332 current_thread_info()->restart_block.fn = do_no_restart_syscall;
333
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
335 goto badframe;
336
337 if (__get_user(set.sig[0], &frame->sc.oldmask)
338 || (_NSIG_WORDS > 1
339 && __copy_from_user(&set.sig[1], &frame->extramask,
340 sizeof(frame->extramask))))
341 goto badframe;
342
343 sigdelsetmask(&set, ~_BLOCKABLE);
Matt Fleming5e047fa2012-03-28 15:16:32 -0700344 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345
346 if (restore_sigcontext(regs, &frame->sc, &ret))
347 goto badframe;
348 regs->pc -= 4;
349
350 return (int) ret;
351
352badframe:
353 force_sig(SIGSEGV, current);
354 return 0;
355}
356
357asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
358 unsigned long r4, unsigned long r5,
359 unsigned long r6, unsigned long r7,
360 struct pt_regs * regs)
361{
362 struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP;
363 sigset_t set;
364 stack_t __user st;
365 long long ret;
366
Paul Mundt1bec1572008-09-24 14:37:35 +0900367 /* Always make any pending restarted system calls return -EINTR */
368 current_thread_info()->restart_block.fn = do_no_restart_syscall;
369
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
371 goto badframe;
372
373 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
374 goto badframe;
375
376 sigdelsetmask(&set, ~_BLOCKABLE);
Matt Fleming5e047fa2012-03-28 15:16:32 -0700377 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
379 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret))
380 goto badframe;
381 regs->pc -= 4;
382
383 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
384 goto badframe;
385 /* It is more difficult to avoid calling this function than to
386 call it and ignore errors. */
387 do_sigaltstack(&st, NULL, REF_REG_SP);
388
389 return (int) ret;
390
391badframe:
392 force_sig(SIGSEGV, current);
393 return 0;
394}
395
396/*
397 * Set up a signal frame.
398 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399static int
400setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
401 unsigned long mask)
402{
403 int err = 0;
404
405 /* Do this first, otherwise is this sets sr->fd, that value isn't preserved. */
406 err |= setup_sigcontext_fpu(regs, sc);
407
408#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
409
410 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
411 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
412 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
413 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
414 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
415 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
416 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
417 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
418 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
419 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
420 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
421 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
422 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
423 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
424 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
425 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
426 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
427 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
428 COPY(sr); COPY(pc);
429
430#undef COPY
431
432 err |= __put_user(mask, &sc->oldmask);
433
434 return err;
435}
436
437/*
438 * Determine which stack to use..
439 */
440static inline void __user *
441get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
442{
Laurent MEYERd09042d2006-06-23 02:05:36 -0700443 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 sp = current->sas_ss_sp + current->sas_ss_size;
445
446 return (void __user *)((sp - frame_size) & -8ul);
447}
448
449void sa_default_restorer(void); /* See comments below */
450void sa_default_rt_restorer(void); /* See comments below */
451
Paul Mundt6ac03432008-12-10 19:26:44 +0900452static int setup_frame(int sig, struct k_sigaction *ka,
453 sigset_t *set, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454{
455 struct sigframe __user *frame;
456 int err = 0;
457 int signal;
458
459 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
460
461 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
462 goto give_sigsegv;
463
464 signal = current_thread_info()->exec_domain
465 && current_thread_info()->exec_domain->signal_invmap
466 && sig < 32
467 ? current_thread_info()->exec_domain->signal_invmap[sig]
468 : sig;
469
470 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
471
472 /* Give up earlier as i386, in case */
473 if (err)
474 goto give_sigsegv;
475
476 if (_NSIG_WORDS > 1) {
477 err |= __copy_to_user(frame->extramask, &set->sig[1],
478 sizeof(frame->extramask)); }
479
480 /* Give up earlier as i386, in case */
481 if (err)
482 goto give_sigsegv;
483
484 /* Set up to return from userspace. If provided, use a stub
485 already in userspace. */
486 if (ka->sa.sa_flags & SA_RESTORER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 /*
488 * On SH5 all edited pointers are subject to NEFF
489 */
Paul Mundtc7914832009-08-04 17:14:39 +0900490 DEREF_REG_PR = neff_sign_extend((unsigned long)
491 ka->sa.sa_restorer | 0x1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 } else {
493 /*
494 * Different approach on SH5.
495 * . Endianness independent asm code gets placed in entry.S .
496 * This is limited to four ASM instructions corresponding
497 * to two long longs in size.
498 * . err checking is done on the else branch only
499 * . flush_icache_range() is called upon __put_user() only
500 * . all edited pointers are subject to NEFF
501 * . being code, linker turns ShMedia bit on, always
502 * dereference index -1.
503 */
Paul Mundtc7914832009-08-04 17:14:39 +0900504 DEREF_REG_PR = neff_sign_extend((unsigned long)
505 frame->retcode | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
507 if (__copy_to_user(frame->retcode,
Paul Mundt091db042008-09-29 19:44:40 +0900508 (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 goto give_sigsegv;
510
511 /* Cohere the trampoline with the I-cache. */
Paul Mundtb6138812007-11-11 15:53:51 +0900512 flush_cache_sigtramp(DEREF_REG_PR-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 }
514
515 /*
516 * Set up registers for signal handler.
517 * All edited pointers are subject to NEFF.
518 */
Paul Mundtc7914832009-08-04 17:14:39 +0900519 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
521
522 /* FIXME:
523 The glibc profiling support for SH-5 needs to be passed a sigcontext
524 so it can retrieve the PC. At some point during 2003 the glibc
525 support was changed to receive the sigcontext through the 2nd
526 argument, but there are still versions of libc.so in use that use
527 the 3rd argument. Until libc.so is stabilised, pass the sigcontext
528 through both 2nd and 3rd arguments.
529 */
530
531 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
532 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
533
Paul Mundtc7914832009-08-04 17:14:39 +0900534 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535
536 set_fs(USER_DS);
537
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 /* Broken %016Lx */
Paul Mundt6ac03432008-12-10 19:26:44 +0900539 pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
540 signal, current->comm, current->pid, frame,
541 regs->pc >> 32, regs->pc & 0xffffffff,
542 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
Paul Mundt6ac03432008-12-10 19:26:44 +0900544 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
546give_sigsegv:
547 force_sigsegv(sig, current);
Paul Mundt6ac03432008-12-10 19:26:44 +0900548 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549}
550
Paul Mundt6ac03432008-12-10 19:26:44 +0900551static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
552 sigset_t *set, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553{
554 struct rt_sigframe __user *frame;
555 int err = 0;
556 int signal;
557
558 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
559
560 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
561 goto give_sigsegv;
562
563 signal = current_thread_info()->exec_domain
564 && current_thread_info()->exec_domain->signal_invmap
565 && sig < 32
566 ? current_thread_info()->exec_domain->signal_invmap[sig]
567 : sig;
568
569 err |= __put_user(&frame->info, &frame->pinfo);
570 err |= __put_user(&frame->uc, &frame->puc);
571 err |= copy_siginfo_to_user(&frame->info, info);
572
573 /* Give up earlier as i386, in case */
574 if (err)
575 goto give_sigsegv;
576
577 /* Create the ucontext. */
578 err |= __put_user(0, &frame->uc.uc_flags);
579 err |= __put_user(0, &frame->uc.uc_link);
580 err |= __put_user((void *)current->sas_ss_sp,
581 &frame->uc.uc_stack.ss_sp);
582 err |= __put_user(sas_ss_flags(regs->regs[REG_SP]),
583 &frame->uc.uc_stack.ss_flags);
584 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
585 err |= setup_sigcontext(&frame->uc.uc_mcontext,
586 regs, set->sig[0]);
587 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
588
589 /* Give up earlier as i386, in case */
590 if (err)
591 goto give_sigsegv;
592
593 /* Set up to return from userspace. If provided, use a stub
594 already in userspace. */
595 if (ka->sa.sa_flags & SA_RESTORER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 /*
597 * On SH5 all edited pointers are subject to NEFF
598 */
Paul Mundtc7914832009-08-04 17:14:39 +0900599 DEREF_REG_PR = neff_sign_extend((unsigned long)
600 ka->sa.sa_restorer | 0x1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 } else {
602 /*
603 * Different approach on SH5.
604 * . Endianness independent asm code gets placed in entry.S .
605 * This is limited to four ASM instructions corresponding
606 * to two long longs in size.
607 * . err checking is done on the else branch only
608 * . flush_icache_range() is called upon __put_user() only
609 * . all edited pointers are subject to NEFF
610 * . being code, linker turns ShMedia bit on, always
611 * dereference index -1.
612 */
Paul Mundtc7914832009-08-04 17:14:39 +0900613 DEREF_REG_PR = neff_sign_extend((unsigned long)
614 frame->retcode | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615
616 if (__copy_to_user(frame->retcode,
Paul Mundt091db042008-09-29 19:44:40 +0900617 (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 goto give_sigsegv;
619
Paul Mundtc7914832009-08-04 17:14:39 +0900620 /* Cohere the trampoline with the I-cache. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
622 }
623
624 /*
625 * Set up registers for signal handler.
626 * All edited pointers are subject to NEFF.
627 */
Paul Mundtc7914832009-08-04 17:14:39 +0900628 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
630 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
631 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
Paul Mundtc7914832009-08-04 17:14:39 +0900632 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633
634 set_fs(USER_DS);
635
Paul Mundt6ac03432008-12-10 19:26:44 +0900636 pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
637 signal, current->comm, current->pid, frame,
638 regs->pc >> 32, regs->pc & 0xffffffff,
639 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
Paul Mundt6ac03432008-12-10 19:26:44 +0900641 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642
643give_sigsegv:
644 force_sigsegv(sig, current);
Paul Mundt6ac03432008-12-10 19:26:44 +0900645 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646}
647
648/*
649 * OK, we're invoking a handler
650 */
Paul Mundt6ac03432008-12-10 19:26:44 +0900651static int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
Al Virob7f9a112012-05-02 09:59:21 -0400653 struct pt_regs * regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654{
Al Virob7f9a112012-05-02 09:59:21 -0400655 sigset_t *oldset = sigmask_to_save();
Paul Mundt6ac03432008-12-10 19:26:44 +0900656 int ret;
657
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 /* Set up the stack frame */
659 if (ka->sa.sa_flags & SA_SIGINFO)
Paul Mundt6ac03432008-12-10 19:26:44 +0900660 ret = setup_rt_frame(sig, ka, info, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 else
Paul Mundt6ac03432008-12-10 19:26:44 +0900662 ret = setup_frame(sig, ka, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663
Matt Fleming5e047fa2012-03-28 15:16:32 -0700664 if (ret == 0)
665 block_sigmask(ka, sig);
Paul Mundt6ac03432008-12-10 19:26:44 +0900666
667 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668}
669
Paul Mundtab99c732008-07-30 19:55:30 +0900670asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671{
Paul Mundtab99c732008-07-30 19:55:30 +0900672 if (thread_info_flags & _TIF_SIGPENDING)
Al Viro9ef461a2012-04-22 01:16:34 -0400673 do_signal(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674
Paul Mundtab99c732008-07-30 19:55:30 +0900675 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
676 clear_thread_flag(TIF_NOTIFY_RESUME);
677 tracehook_notify_resume(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679}