blob: 8f6ed236c932019cebfd2c34f4350984ebab2646 [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 */
Paul Mundt56bfc422009-10-14 16:05:42 +0900146 if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
147 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
Paul Mundtab99c732008-07-30 19:55:30 +0900148 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
149 }
150
Al Viro9ef461a2012-04-22 01:16:34 -0400151 return;
Paul Mundtab99c732008-07-30 19:55:30 +0900152}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153
154/*
155 * Atomically swap in the new signal mask, and wait for a signal.
156 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157asmlinkage int
Al Viro9ef461a2012-04-22 01:16:34 -0400158sys_sigsuspend(old_sigset_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159{
Al Viro9ef461a2012-04-22 01:16:34 -0400160 sigset_t blocked;
Matt Fleming5e047fa2012-03-28 15:16:32 -0700161 siginitset(&blocked, mask);
Al Viro9ef461a2012-04-22 01:16:34 -0400162 return sigsuspend(&blocked);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163}
164
165asmlinkage int
166sys_sigaction(int sig, const struct old_sigaction __user *act,
167 struct old_sigaction __user *oact)
168{
169 struct k_sigaction new_ka, old_ka;
170 int ret;
171
172 if (act) {
173 old_sigset_t mask;
174 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
175 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
176 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
177 return -EFAULT;
178 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
179 __get_user(mask, &act->sa_mask);
180 siginitset(&new_ka.sa.sa_mask, mask);
181 }
182
183 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
184
185 if (!ret && oact) {
186 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
187 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
188 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
189 return -EFAULT;
190 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
191 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
192 }
193
194 return ret;
195}
196
197asmlinkage int
198sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
199 unsigned long r4, unsigned long r5, unsigned long r6,
200 unsigned long r7,
201 struct pt_regs * regs)
202{
203 return do_sigaltstack(uss, uoss, REF_REG_SP);
204}
205
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206/*
207 * Do a signal return; undo the signal stack.
208 */
Paul Mundt94e2fb32008-12-10 19:46:18 +0900209struct sigframe {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 struct sigcontext sc;
211 unsigned long extramask[_NSIG_WORDS-1];
212 long long retcode[2];
213};
214
Paul Mundt94e2fb32008-12-10 19:46:18 +0900215struct rt_sigframe {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 struct siginfo __user *pinfo;
217 void *puc;
218 struct siginfo info;
219 struct ucontext uc;
220 long long retcode[2];
221};
222
223#ifdef CONFIG_SH_FPU
224static inline int
225restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
226{
227 int err = 0;
228 int fpvalid;
229
230 err |= __get_user (fpvalid, &sc->sc_fpvalid);
231 conditional_used_math(fpvalid);
232 if (! fpvalid)
233 return err;
234
235 if (current == last_task_used_math) {
236 last_task_used_math = NULL;
237 regs->sr |= SR_FD;
238 }
239
Paul Mundt3ef29322010-01-19 15:40:03 +0900240 err |= __copy_from_user(&current->thread.xstate->hardfpu, &sc->sc_fpregs[0],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 (sizeof(long long) * 32) + (sizeof(int) * 1));
242
243 return err;
244}
245
246static inline int
247setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
248{
249 int err = 0;
250 int fpvalid;
251
252 fpvalid = !!used_math();
253 err |= __put_user(fpvalid, &sc->sc_fpvalid);
254 if (! fpvalid)
255 return err;
256
257 if (current == last_task_used_math) {
Paul Mundt600ee242007-11-19 19:13:38 +0900258 enable_fpu();
Matt Fleming61cc7b02009-12-14 20:12:04 +0000259 save_fpu(current);
Paul Mundt600ee242007-11-19 19:13:38 +0900260 disable_fpu();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 last_task_used_math = NULL;
262 regs->sr |= SR_FD;
263 }
264
Paul Mundt3ef29322010-01-19 15:40:03 +0900265 err |= __copy_to_user(&sc->sc_fpregs[0], &current->thread.xstate->hardfpu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 (sizeof(long long) * 32) + (sizeof(int) * 1));
267 clear_used_math();
268
269 return err;
270}
271#else
272static inline int
273restore_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 -0700277static inline int
278setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900279{
280 return 0;
281}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282#endif
283
284static int
285restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, long long *r2_p)
286{
287 unsigned int err = 0;
288 unsigned long long current_sr, new_sr;
289#define SR_MASK 0xffff8cfd
290
291#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
292
293 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
294 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
295 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
296 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
297 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
298 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
299 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
300 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
301 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
302 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
303 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
304 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
305 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
306 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
307 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
308 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
309 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
310 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
311
312 /* Prevent the signal handler manipulating SR in a way that can
313 crash the kernel. i.e. only allow S, Q, M, PR, SZ, FR to be
314 modified */
315 current_sr = regs->sr;
316 err |= __get_user(new_sr, &sc->sc_sr);
317 regs->sr &= SR_MASK;
318 regs->sr |= (new_sr & ~SR_MASK);
319
320 COPY(pc);
321
322#undef COPY
323
324 /* Must do this last in case it sets regs->sr.fd (i.e. after rest of sr
325 * has been restored above.) */
326 err |= restore_sigcontext_fpu(regs, sc);
327
328 regs->syscall_nr = -1; /* disable syscall checks */
329 err |= __get_user(*r2_p, &sc->sc_regs[REG_RET]);
330 return err;
331}
332
333asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
334 unsigned long r4, unsigned long r5,
335 unsigned long r6, unsigned long r7,
336 struct pt_regs * regs)
337{
338 struct sigframe __user *frame = (struct sigframe __user *) (long) REF_REG_SP;
339 sigset_t set;
340 long long ret;
341
Paul Mundt1bec1572008-09-24 14:37:35 +0900342 /* Always make any pending restarted system calls return -EINTR */
343 current_thread_info()->restart_block.fn = do_no_restart_syscall;
344
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
346 goto badframe;
347
348 if (__get_user(set.sig[0], &frame->sc.oldmask)
349 || (_NSIG_WORDS > 1
350 && __copy_from_user(&set.sig[1], &frame->extramask,
351 sizeof(frame->extramask))))
352 goto badframe;
353
354 sigdelsetmask(&set, ~_BLOCKABLE);
Matt Fleming5e047fa2012-03-28 15:16:32 -0700355 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
357 if (restore_sigcontext(regs, &frame->sc, &ret))
358 goto badframe;
359 regs->pc -= 4;
360
361 return (int) ret;
362
363badframe:
364 force_sig(SIGSEGV, current);
365 return 0;
366}
367
368asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
369 unsigned long r4, unsigned long r5,
370 unsigned long r6, unsigned long r7,
371 struct pt_regs * regs)
372{
373 struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP;
374 sigset_t set;
375 stack_t __user st;
376 long long ret;
377
Paul Mundt1bec1572008-09-24 14:37:35 +0900378 /* Always make any pending restarted system calls return -EINTR */
379 current_thread_info()->restart_block.fn = do_no_restart_syscall;
380
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
382 goto badframe;
383
384 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
385 goto badframe;
386
387 sigdelsetmask(&set, ~_BLOCKABLE);
Matt Fleming5e047fa2012-03-28 15:16:32 -0700388 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
390 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret))
391 goto badframe;
392 regs->pc -= 4;
393
394 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
395 goto badframe;
396 /* It is more difficult to avoid calling this function than to
397 call it and ignore errors. */
398 do_sigaltstack(&st, NULL, REF_REG_SP);
399
400 return (int) ret;
401
402badframe:
403 force_sig(SIGSEGV, current);
404 return 0;
405}
406
407/*
408 * Set up a signal frame.
409 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410static int
411setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
412 unsigned long mask)
413{
414 int err = 0;
415
416 /* Do this first, otherwise is this sets sr->fd, that value isn't preserved. */
417 err |= setup_sigcontext_fpu(regs, sc);
418
419#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
420
421 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
422 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
423 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
424 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
425 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
426 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
427 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
428 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
429 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
430 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
431 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
432 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
433 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
434 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
435 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
436 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
437 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
438 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
439 COPY(sr); COPY(pc);
440
441#undef COPY
442
443 err |= __put_user(mask, &sc->oldmask);
444
445 return err;
446}
447
448/*
449 * Determine which stack to use..
450 */
451static inline void __user *
452get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
453{
Laurent MEYERd09042d2006-06-23 02:05:36 -0700454 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 sp = current->sas_ss_sp + current->sas_ss_size;
456
457 return (void __user *)((sp - frame_size) & -8ul);
458}
459
460void sa_default_restorer(void); /* See comments below */
461void sa_default_rt_restorer(void); /* See comments below */
462
Paul Mundt6ac03432008-12-10 19:26:44 +0900463static int setup_frame(int sig, struct k_sigaction *ka,
464 sigset_t *set, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465{
466 struct sigframe __user *frame;
467 int err = 0;
468 int signal;
469
470 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
471
472 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
473 goto give_sigsegv;
474
475 signal = current_thread_info()->exec_domain
476 && current_thread_info()->exec_domain->signal_invmap
477 && sig < 32
478 ? current_thread_info()->exec_domain->signal_invmap[sig]
479 : sig;
480
481 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
482
483 /* Give up earlier as i386, in case */
484 if (err)
485 goto give_sigsegv;
486
487 if (_NSIG_WORDS > 1) {
488 err |= __copy_to_user(frame->extramask, &set->sig[1],
489 sizeof(frame->extramask)); }
490
491 /* Give up earlier as i386, in case */
492 if (err)
493 goto give_sigsegv;
494
495 /* Set up to return from userspace. If provided, use a stub
496 already in userspace. */
497 if (ka->sa.sa_flags & SA_RESTORER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 /*
499 * On SH5 all edited pointers are subject to NEFF
500 */
Paul Mundtc7914832009-08-04 17:14:39 +0900501 DEREF_REG_PR = neff_sign_extend((unsigned long)
502 ka->sa.sa_restorer | 0x1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 } else {
504 /*
505 * Different approach on SH5.
506 * . Endianness independent asm code gets placed in entry.S .
507 * This is limited to four ASM instructions corresponding
508 * to two long longs in size.
509 * . err checking is done on the else branch only
510 * . flush_icache_range() is called upon __put_user() only
511 * . all edited pointers are subject to NEFF
512 * . being code, linker turns ShMedia bit on, always
513 * dereference index -1.
514 */
Paul Mundtc7914832009-08-04 17:14:39 +0900515 DEREF_REG_PR = neff_sign_extend((unsigned long)
516 frame->retcode | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517
518 if (__copy_to_user(frame->retcode,
Paul Mundt091db042008-09-29 19:44:40 +0900519 (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 goto give_sigsegv;
521
522 /* Cohere the trampoline with the I-cache. */
Paul Mundtb6138812007-11-11 15:53:51 +0900523 flush_cache_sigtramp(DEREF_REG_PR-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 }
525
526 /*
527 * Set up registers for signal handler.
528 * All edited pointers are subject to NEFF.
529 */
Paul Mundtc7914832009-08-04 17:14:39 +0900530 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
532
533 /* FIXME:
534 The glibc profiling support for SH-5 needs to be passed a sigcontext
535 so it can retrieve the PC. At some point during 2003 the glibc
536 support was changed to receive the sigcontext through the 2nd
537 argument, but there are still versions of libc.so in use that use
538 the 3rd argument. Until libc.so is stabilised, pass the sigcontext
539 through both 2nd and 3rd arguments.
540 */
541
542 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
543 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
544
Paul Mundtc7914832009-08-04 17:14:39 +0900545 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546
547 set_fs(USER_DS);
548
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 /* Broken %016Lx */
Paul Mundt6ac03432008-12-10 19:26:44 +0900550 pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
551 signal, current->comm, current->pid, frame,
552 regs->pc >> 32, regs->pc & 0xffffffff,
553 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554
Paul Mundt6ac03432008-12-10 19:26:44 +0900555 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
557give_sigsegv:
558 force_sigsegv(sig, current);
Paul Mundt6ac03432008-12-10 19:26:44 +0900559 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560}
561
Paul Mundt6ac03432008-12-10 19:26:44 +0900562static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
563 sigset_t *set, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564{
565 struct rt_sigframe __user *frame;
566 int err = 0;
567 int signal;
568
569 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
570
571 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
572 goto give_sigsegv;
573
574 signal = current_thread_info()->exec_domain
575 && current_thread_info()->exec_domain->signal_invmap
576 && sig < 32
577 ? current_thread_info()->exec_domain->signal_invmap[sig]
578 : sig;
579
580 err |= __put_user(&frame->info, &frame->pinfo);
581 err |= __put_user(&frame->uc, &frame->puc);
582 err |= copy_siginfo_to_user(&frame->info, info);
583
584 /* Give up earlier as i386, in case */
585 if (err)
586 goto give_sigsegv;
587
588 /* Create the ucontext. */
589 err |= __put_user(0, &frame->uc.uc_flags);
590 err |= __put_user(0, &frame->uc.uc_link);
591 err |= __put_user((void *)current->sas_ss_sp,
592 &frame->uc.uc_stack.ss_sp);
593 err |= __put_user(sas_ss_flags(regs->regs[REG_SP]),
594 &frame->uc.uc_stack.ss_flags);
595 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
596 err |= setup_sigcontext(&frame->uc.uc_mcontext,
597 regs, set->sig[0]);
598 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
599
600 /* Give up earlier as i386, in case */
601 if (err)
602 goto give_sigsegv;
603
604 /* Set up to return from userspace. If provided, use a stub
605 already in userspace. */
606 if (ka->sa.sa_flags & SA_RESTORER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 /*
608 * On SH5 all edited pointers are subject to NEFF
609 */
Paul Mundtc7914832009-08-04 17:14:39 +0900610 DEREF_REG_PR = neff_sign_extend((unsigned long)
611 ka->sa.sa_restorer | 0x1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 } else {
613 /*
614 * Different approach on SH5.
615 * . Endianness independent asm code gets placed in entry.S .
616 * This is limited to four ASM instructions corresponding
617 * to two long longs in size.
618 * . err checking is done on the else branch only
619 * . flush_icache_range() is called upon __put_user() only
620 * . all edited pointers are subject to NEFF
621 * . being code, linker turns ShMedia bit on, always
622 * dereference index -1.
623 */
Paul Mundtc7914832009-08-04 17:14:39 +0900624 DEREF_REG_PR = neff_sign_extend((unsigned long)
625 frame->retcode | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626
627 if (__copy_to_user(frame->retcode,
Paul Mundt091db042008-09-29 19:44:40 +0900628 (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 goto give_sigsegv;
630
Paul Mundtc7914832009-08-04 17:14:39 +0900631 /* Cohere the trampoline with the I-cache. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
633 }
634
635 /*
636 * Set up registers for signal handler.
637 * All edited pointers are subject to NEFF.
638 */
Paul Mundtc7914832009-08-04 17:14:39 +0900639 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
641 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
642 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
Paul Mundtc7914832009-08-04 17:14:39 +0900643 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
645 set_fs(USER_DS);
646
Paul Mundt6ac03432008-12-10 19:26:44 +0900647 pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
648 signal, current->comm, current->pid, frame,
649 regs->pc >> 32, regs->pc & 0xffffffff,
650 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651
Paul Mundt6ac03432008-12-10 19:26:44 +0900652 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
654give_sigsegv:
655 force_sigsegv(sig, current);
Paul Mundt6ac03432008-12-10 19:26:44 +0900656 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657}
658
659/*
660 * OK, we're invoking a handler
661 */
Paul Mundt6ac03432008-12-10 19:26:44 +0900662static int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
664 sigset_t *oldset, struct pt_regs * regs)
665{
Paul Mundt6ac03432008-12-10 19:26:44 +0900666 int ret;
667
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 /* Set up the stack frame */
669 if (ka->sa.sa_flags & SA_SIGINFO)
Paul Mundt6ac03432008-12-10 19:26:44 +0900670 ret = setup_rt_frame(sig, ka, info, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 else
Paul Mundt6ac03432008-12-10 19:26:44 +0900672 ret = setup_frame(sig, ka, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
Matt Fleming5e047fa2012-03-28 15:16:32 -0700674 if (ret == 0)
675 block_sigmask(ka, sig);
Paul Mundt6ac03432008-12-10 19:26:44 +0900676
677 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678}
679
Paul Mundtab99c732008-07-30 19:55:30 +0900680asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681{
Paul Mundtab99c732008-07-30 19:55:30 +0900682 if (thread_info_flags & _TIF_SIGPENDING)
Al Viro9ef461a2012-04-22 01:16:34 -0400683 do_signal(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
Paul Mundtab99c732008-07-30 19:55:30 +0900685 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
686 clear_thread_flag(TIF_NOTIFY_RESUME);
687 tracehook_notify_resume(regs);
David Howellsee18d642009-09-02 09:14:21 +0100688 if (current->replacement_session_keyring)
689 key_replace_session_keyring();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691}