blob: 6e191ef0aa624fe4333dd03db0b00f97c90b4380 [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;
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;
Al Viro9ef461a2012-04-22 01:16:34 -040091 sigset_t *oldset;
Paul Mundtab99c732008-07-30 19:55:30 +090092
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))
Al Viro9ef461a2012-04-22 01:16:34 -0400100 return;
Paul Mundtab99c732008-07-30 19:55:30 +0900101
Paul Mundt56bfc422009-10-14 16:05:42 +0900102 if (current_thread_info()->status & TS_RESTORE_SIGMASK)
Paul Mundtab99c732008-07-30 19:55:30 +0900103 oldset = &current->saved_sigmask;
Al Viro9ef461a2012-04-22 01:16:34 -0400104 else
Paul Mundtab99c732008-07-30 19:55:30 +0900105 oldset = &current->blocked;
106
107 signr = get_signal_to_deliver(&info, &ka, regs, 0);
Paul Mundtab99c732008-07-30 19:55:30 +0900108 if (signr > 0) {
Paul Mundt03f07872009-01-29 11:21:38 +0900109 handle_syscall_restart(regs, &ka.sa);
Paul Mundt94e2fb32008-12-10 19:46:18 +0900110
Paul Mundtab99c732008-07-30 19:55:30 +0900111 /* Whee! Actually deliver the signal. */
Paul Mundt6ac03432008-12-10 19:26:44 +0900112 if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
113 /*
114 * If a signal was successfully delivered, the
115 * saved sigmask is in its frame, and we can
Paul Mundt56bfc422009-10-14 16:05:42 +0900116 * clear the TS_RESTORE_SIGMASK flag.
Paul Mundt6ac03432008-12-10 19:26:44 +0900117 */
Paul Mundt56bfc422009-10-14 16:05:42 +0900118 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
Paul Mundt4b505db2010-02-15 14:17:45 +0900119
120 tracehook_signal_handler(signr, &info, &ka, regs,
121 test_thread_flag(TIF_SINGLESTEP));
Al Viro9ef461a2012-04-22 01:16:34 -0400122 return;
Paul Mundt6ac03432008-12-10 19:26:44 +0900123 }
Paul Mundtab99c732008-07-30 19:55:30 +0900124 }
125
Paul Mundtab99c732008-07-30 19:55:30 +0900126 /* Did we come from a system call? */
127 if (regs->syscall_nr >= 0) {
128 /* Restart the system call - no handlers present */
129 switch (regs->regs[REG_RET]) {
130 case -ERESTARTNOHAND:
131 case -ERESTARTSYS:
132 case -ERESTARTNOINTR:
133 /* Decode Syscall # */
134 regs->regs[REG_RET] = regs->syscall_nr;
135 regs->pc -= 4;
136 break;
137
138 case -ERESTART_RESTARTBLOCK:
139 regs->regs[REG_RET] = __NR_restart_syscall;
140 regs->pc -= 4;
141 break;
142 }
143 }
144
145 /* No signal to deliver -- put the saved sigmask back */
Al Viro51a7b442012-05-21 23:33:55 -0400146 restore_saved_sigmask();
Paul Mundtab99c732008-07-30 19:55:30 +0900147}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
149/*
150 * Atomically swap in the new signal mask, and wait for a signal.
151 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152asmlinkage int
Al Viro9ef461a2012-04-22 01:16:34 -0400153sys_sigsuspend(old_sigset_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154{
Al Viro9ef461a2012-04-22 01:16:34 -0400155 sigset_t blocked;
Matt Fleming5e047fa2012-03-28 15:16:32 -0700156 siginitset(&blocked, mask);
Al Viro9ef461a2012-04-22 01:16:34 -0400157 return sigsuspend(&blocked);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158}
159
160asmlinkage int
161sys_sigaction(int sig, const struct old_sigaction __user *act,
162 struct old_sigaction __user *oact)
163{
164 struct k_sigaction new_ka, old_ka;
165 int ret;
166
167 if (act) {
168 old_sigset_t mask;
169 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
170 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
Al Viroa46808e2012-04-22 16:59:56 -0400171 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
172 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
173 __get_user(mask, &act->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175 siginitset(&new_ka.sa.sa_mask, mask);
176 }
177
178 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
179
180 if (!ret && oact) {
181 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
182 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
Al Viroa46808e2012-04-22 16:59:56 -0400183 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
184 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
185 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 }
188
189 return ret;
190}
191
192asmlinkage int
193sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
194 unsigned long r4, unsigned long r5, unsigned long r6,
195 unsigned long r7,
196 struct pt_regs * regs)
197{
198 return do_sigaltstack(uss, uoss, REF_REG_SP);
199}
200
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201/*
202 * Do a signal return; undo the signal stack.
203 */
Paul Mundt94e2fb32008-12-10 19:46:18 +0900204struct sigframe {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 struct sigcontext sc;
206 unsigned long extramask[_NSIG_WORDS-1];
207 long long retcode[2];
208};
209
Paul Mundt94e2fb32008-12-10 19:46:18 +0900210struct rt_sigframe {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 struct siginfo __user *pinfo;
212 void *puc;
213 struct siginfo info;
214 struct ucontext uc;
215 long long retcode[2];
216};
217
218#ifdef CONFIG_SH_FPU
219static inline int
220restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
221{
222 int err = 0;
223 int fpvalid;
224
225 err |= __get_user (fpvalid, &sc->sc_fpvalid);
226 conditional_used_math(fpvalid);
227 if (! fpvalid)
228 return err;
229
230 if (current == last_task_used_math) {
231 last_task_used_math = NULL;
232 regs->sr |= SR_FD;
233 }
234
Paul Mundt3ef29322010-01-19 15:40:03 +0900235 err |= __copy_from_user(&current->thread.xstate->hardfpu, &sc->sc_fpregs[0],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 (sizeof(long long) * 32) + (sizeof(int) * 1));
237
238 return err;
239}
240
241static inline int
242setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
243{
244 int err = 0;
245 int fpvalid;
246
247 fpvalid = !!used_math();
248 err |= __put_user(fpvalid, &sc->sc_fpvalid);
249 if (! fpvalid)
250 return err;
251
252 if (current == last_task_used_math) {
Paul Mundt600ee242007-11-19 19:13:38 +0900253 enable_fpu();
Matt Fleming61cc7b02009-12-14 20:12:04 +0000254 save_fpu(current);
Paul Mundt600ee242007-11-19 19:13:38 +0900255 disable_fpu();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 last_task_used_math = NULL;
257 regs->sr |= SR_FD;
258 }
259
Paul Mundt3ef29322010-01-19 15:40:03 +0900260 err |= __copy_to_user(&sc->sc_fpregs[0], &current->thread.xstate->hardfpu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 (sizeof(long long) * 32) + (sizeof(int) * 1));
262 clear_used_math();
263
264 return err;
265}
266#else
267static inline int
268restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900269{
270 return 0;
271}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272static inline int
273setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900274{
275 return 0;
276}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277#endif
278
279static int
280restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, long long *r2_p)
281{
282 unsigned int err = 0;
283 unsigned long long current_sr, new_sr;
284#define SR_MASK 0xffff8cfd
285
286#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
287
288 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
289 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
290 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
291 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
292 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
293 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
294 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
295 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
296 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
297 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
298 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
299 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
300 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
301 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
302 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
303 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
304 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
305 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
306
307 /* Prevent the signal handler manipulating SR in a way that can
308 crash the kernel. i.e. only allow S, Q, M, PR, SZ, FR to be
309 modified */
310 current_sr = regs->sr;
311 err |= __get_user(new_sr, &sc->sc_sr);
312 regs->sr &= SR_MASK;
313 regs->sr |= (new_sr & ~SR_MASK);
314
315 COPY(pc);
316
317#undef COPY
318
319 /* Must do this last in case it sets regs->sr.fd (i.e. after rest of sr
320 * has been restored above.) */
321 err |= restore_sigcontext_fpu(regs, sc);
322
323 regs->syscall_nr = -1; /* disable syscall checks */
324 err |= __get_user(*r2_p, &sc->sc_regs[REG_RET]);
325 return err;
326}
327
328asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
329 unsigned long r4, unsigned long r5,
330 unsigned long r6, unsigned long r7,
331 struct pt_regs * regs)
332{
333 struct sigframe __user *frame = (struct sigframe __user *) (long) REF_REG_SP;
334 sigset_t set;
335 long long ret;
336
Paul Mundt1bec1572008-09-24 14:37:35 +0900337 /* Always make any pending restarted system calls return -EINTR */
338 current_thread_info()->restart_block.fn = do_no_restart_syscall;
339
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
341 goto badframe;
342
343 if (__get_user(set.sig[0], &frame->sc.oldmask)
344 || (_NSIG_WORDS > 1
345 && __copy_from_user(&set.sig[1], &frame->extramask,
346 sizeof(frame->extramask))))
347 goto badframe;
348
349 sigdelsetmask(&set, ~_BLOCKABLE);
Matt Fleming5e047fa2012-03-28 15:16:32 -0700350 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351
352 if (restore_sigcontext(regs, &frame->sc, &ret))
353 goto badframe;
354 regs->pc -= 4;
355
356 return (int) ret;
357
358badframe:
359 force_sig(SIGSEGV, current);
360 return 0;
361}
362
363asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
364 unsigned long r4, unsigned long r5,
365 unsigned long r6, unsigned long r7,
366 struct pt_regs * regs)
367{
368 struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP;
369 sigset_t set;
370 stack_t __user st;
371 long long ret;
372
Paul Mundt1bec1572008-09-24 14:37:35 +0900373 /* Always make any pending restarted system calls return -EINTR */
374 current_thread_info()->restart_block.fn = do_no_restart_syscall;
375
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
377 goto badframe;
378
379 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
380 goto badframe;
381
382 sigdelsetmask(&set, ~_BLOCKABLE);
Matt Fleming5e047fa2012-03-28 15:16:32 -0700383 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
385 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret))
386 goto badframe;
387 regs->pc -= 4;
388
389 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
390 goto badframe;
391 /* It is more difficult to avoid calling this function than to
392 call it and ignore errors. */
393 do_sigaltstack(&st, NULL, REF_REG_SP);
394
395 return (int) ret;
396
397badframe:
398 force_sig(SIGSEGV, current);
399 return 0;
400}
401
402/*
403 * Set up a signal frame.
404 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405static int
406setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
407 unsigned long mask)
408{
409 int err = 0;
410
411 /* Do this first, otherwise is this sets sr->fd, that value isn't preserved. */
412 err |= setup_sigcontext_fpu(regs, sc);
413
414#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
415
416 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
417 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
418 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
419 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
420 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
421 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
422 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
423 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
424 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
425 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
426 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
427 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
428 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
429 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
430 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
431 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
432 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
433 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
434 COPY(sr); COPY(pc);
435
436#undef COPY
437
438 err |= __put_user(mask, &sc->oldmask);
439
440 return err;
441}
442
443/*
444 * Determine which stack to use..
445 */
446static inline void __user *
447get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
448{
Laurent MEYERd09042d2006-06-23 02:05:36 -0700449 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 sp = current->sas_ss_sp + current->sas_ss_size;
451
452 return (void __user *)((sp - frame_size) & -8ul);
453}
454
455void sa_default_restorer(void); /* See comments below */
456void sa_default_rt_restorer(void); /* See comments below */
457
Paul Mundt6ac03432008-12-10 19:26:44 +0900458static int setup_frame(int sig, struct k_sigaction *ka,
459 sigset_t *set, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460{
461 struct sigframe __user *frame;
462 int err = 0;
463 int signal;
464
465 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
466
467 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
468 goto give_sigsegv;
469
470 signal = current_thread_info()->exec_domain
471 && current_thread_info()->exec_domain->signal_invmap
472 && sig < 32
473 ? current_thread_info()->exec_domain->signal_invmap[sig]
474 : sig;
475
476 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
477
478 /* Give up earlier as i386, in case */
479 if (err)
480 goto give_sigsegv;
481
482 if (_NSIG_WORDS > 1) {
483 err |= __copy_to_user(frame->extramask, &set->sig[1],
484 sizeof(frame->extramask)); }
485
486 /* Give up earlier as i386, in case */
487 if (err)
488 goto give_sigsegv;
489
490 /* Set up to return from userspace. If provided, use a stub
491 already in userspace. */
492 if (ka->sa.sa_flags & SA_RESTORER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 /*
494 * On SH5 all edited pointers are subject to NEFF
495 */
Paul Mundtc7914832009-08-04 17:14:39 +0900496 DEREF_REG_PR = neff_sign_extend((unsigned long)
497 ka->sa.sa_restorer | 0x1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 } else {
499 /*
500 * Different approach on SH5.
501 * . Endianness independent asm code gets placed in entry.S .
502 * This is limited to four ASM instructions corresponding
503 * to two long longs in size.
504 * . err checking is done on the else branch only
505 * . flush_icache_range() is called upon __put_user() only
506 * . all edited pointers are subject to NEFF
507 * . being code, linker turns ShMedia bit on, always
508 * dereference index -1.
509 */
Paul Mundtc7914832009-08-04 17:14:39 +0900510 DEREF_REG_PR = neff_sign_extend((unsigned long)
511 frame->retcode | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
513 if (__copy_to_user(frame->retcode,
Paul Mundt091db042008-09-29 19:44:40 +0900514 (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 goto give_sigsegv;
516
517 /* Cohere the trampoline with the I-cache. */
Paul Mundtb6138812007-11-11 15:53:51 +0900518 flush_cache_sigtramp(DEREF_REG_PR-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 }
520
521 /*
522 * Set up registers for signal handler.
523 * All edited pointers are subject to NEFF.
524 */
Paul Mundtc7914832009-08-04 17:14:39 +0900525 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
527
528 /* FIXME:
529 The glibc profiling support for SH-5 needs to be passed a sigcontext
530 so it can retrieve the PC. At some point during 2003 the glibc
531 support was changed to receive the sigcontext through the 2nd
532 argument, but there are still versions of libc.so in use that use
533 the 3rd argument. Until libc.so is stabilised, pass the sigcontext
534 through both 2nd and 3rd arguments.
535 */
536
537 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
538 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
539
Paul Mundtc7914832009-08-04 17:14:39 +0900540 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541
542 set_fs(USER_DS);
543
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 /* Broken %016Lx */
Paul Mundt6ac03432008-12-10 19:26:44 +0900545 pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
546 signal, current->comm, current->pid, frame,
547 regs->pc >> 32, regs->pc & 0xffffffff,
548 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
Paul Mundt6ac03432008-12-10 19:26:44 +0900550 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551
552give_sigsegv:
553 force_sigsegv(sig, current);
Paul Mundt6ac03432008-12-10 19:26:44 +0900554 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555}
556
Paul Mundt6ac03432008-12-10 19:26:44 +0900557static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
558 sigset_t *set, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559{
560 struct rt_sigframe __user *frame;
561 int err = 0;
562 int signal;
563
564 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
565
566 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
567 goto give_sigsegv;
568
569 signal = current_thread_info()->exec_domain
570 && current_thread_info()->exec_domain->signal_invmap
571 && sig < 32
572 ? current_thread_info()->exec_domain->signal_invmap[sig]
573 : sig;
574
575 err |= __put_user(&frame->info, &frame->pinfo);
576 err |= __put_user(&frame->uc, &frame->puc);
577 err |= copy_siginfo_to_user(&frame->info, info);
578
579 /* Give up earlier as i386, in case */
580 if (err)
581 goto give_sigsegv;
582
583 /* Create the ucontext. */
584 err |= __put_user(0, &frame->uc.uc_flags);
585 err |= __put_user(0, &frame->uc.uc_link);
586 err |= __put_user((void *)current->sas_ss_sp,
587 &frame->uc.uc_stack.ss_sp);
588 err |= __put_user(sas_ss_flags(regs->regs[REG_SP]),
589 &frame->uc.uc_stack.ss_flags);
590 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
591 err |= setup_sigcontext(&frame->uc.uc_mcontext,
592 regs, set->sig[0]);
593 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
594
595 /* Give up earlier as i386, in case */
596 if (err)
597 goto give_sigsegv;
598
599 /* Set up to return from userspace. If provided, use a stub
600 already in userspace. */
601 if (ka->sa.sa_flags & SA_RESTORER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 /*
603 * On SH5 all edited pointers are subject to NEFF
604 */
Paul Mundtc7914832009-08-04 17:14:39 +0900605 DEREF_REG_PR = neff_sign_extend((unsigned long)
606 ka->sa.sa_restorer | 0x1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 } else {
608 /*
609 * Different approach on SH5.
610 * . Endianness independent asm code gets placed in entry.S .
611 * This is limited to four ASM instructions corresponding
612 * to two long longs in size.
613 * . err checking is done on the else branch only
614 * . flush_icache_range() is called upon __put_user() only
615 * . all edited pointers are subject to NEFF
616 * . being code, linker turns ShMedia bit on, always
617 * dereference index -1.
618 */
Paul Mundtc7914832009-08-04 17:14:39 +0900619 DEREF_REG_PR = neff_sign_extend((unsigned long)
620 frame->retcode | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
622 if (__copy_to_user(frame->retcode,
Paul Mundt091db042008-09-29 19:44:40 +0900623 (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 goto give_sigsegv;
625
Paul Mundtc7914832009-08-04 17:14:39 +0900626 /* Cohere the trampoline with the I-cache. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
628 }
629
630 /*
631 * Set up registers for signal handler.
632 * All edited pointers are subject to NEFF.
633 */
Paul Mundtc7914832009-08-04 17:14:39 +0900634 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
636 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
637 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
Paul Mundtc7914832009-08-04 17:14:39 +0900638 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639
640 set_fs(USER_DS);
641
Paul Mundt6ac03432008-12-10 19:26:44 +0900642 pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
643 signal, current->comm, current->pid, frame,
644 regs->pc >> 32, regs->pc & 0xffffffff,
645 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
Paul Mundt6ac03432008-12-10 19:26:44 +0900647 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648
649give_sigsegv:
650 force_sigsegv(sig, current);
Paul Mundt6ac03432008-12-10 19:26:44 +0900651 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652}
653
654/*
655 * OK, we're invoking a handler
656 */
Paul Mundt6ac03432008-12-10 19:26:44 +0900657static int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
659 sigset_t *oldset, struct pt_regs * regs)
660{
Paul Mundt6ac03432008-12-10 19:26:44 +0900661 int ret;
662
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 /* Set up the stack frame */
664 if (ka->sa.sa_flags & SA_SIGINFO)
Paul Mundt6ac03432008-12-10 19:26:44 +0900665 ret = setup_rt_frame(sig, ka, info, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 else
Paul Mundt6ac03432008-12-10 19:26:44 +0900667 ret = setup_frame(sig, ka, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668
Matt Fleming5e047fa2012-03-28 15:16:32 -0700669 if (ret == 0)
670 block_sigmask(ka, sig);
Paul Mundt6ac03432008-12-10 19:26:44 +0900671
672 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673}
674
Paul Mundtab99c732008-07-30 19:55:30 +0900675asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676{
Paul Mundtab99c732008-07-30 19:55:30 +0900677 if (thread_info_flags & _TIF_SIGPENDING)
Al Viro9ef461a2012-04-22 01:16:34 -0400678 do_signal(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Paul Mundtab99c732008-07-30 19:55:30 +0900680 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
681 clear_thread_flag(TIF_NOTIFY_RESUME);
682 tracehook_notify_resume(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684}