blob: 0fba66e2b2023e04c8ea7bddc848b8fbdb92ae5e [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <linux/ptrace.h>
22#include <linux/unistd.h>
23#include <linux/stddef.h>
Paul Mundtab99c732008-07-30 19:55:30 +090024#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <asm/ucontext.h>
26#include <asm/uaccess.h>
27#include <asm/pgtable.h>
Paul Mundtf7a7b152007-11-10 20:07:57 +090028#include <asm/cacheflush.h>
Adrian Bunk50387b32008-04-13 21:15:38 +030029#include <asm/fpu.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
31#define REG_RET 9
32#define REG_ARG1 2
33#define REG_ARG2 3
34#define REG_ARG3 4
35#define REG_SP 15
36#define REG_PR 18
37#define REF_REG_RET regs->regs[REG_RET]
38#define REF_REG_SP regs->regs[REG_SP]
39#define DEREF_REG_PR regs->regs[REG_PR]
40
41#define DEBUG_SIG 0
42
Al Viroa610d6e2012-05-21 23:42:15 -040043static void
Paul Mundt8a80a5e2008-09-17 23:14:36 +090044handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
Al Virob7f9a112012-05-02 09:59:21 -040045 struct pt_regs * regs);
Paul Mundt8a80a5e2008-09-17 23:14:36 +090046
Paul Mundt94e2fb32008-12-10 19:46:18 +090047static inline void
48handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
49{
50 /* If we're not from a syscall, bail out */
51 if (regs->syscall_nr < 0)
52 return;
53
54 /* check for system call restart.. */
55 switch (regs->regs[REG_RET]) {
56 case -ERESTART_RESTARTBLOCK:
57 case -ERESTARTNOHAND:
58 no_system_call_restart:
59 regs->regs[REG_RET] = -EINTR;
Paul Mundt94e2fb32008-12-10 19:46:18 +090060 break;
61
62 case -ERESTARTSYS:
63 if (!(sa->sa_flags & SA_RESTART))
64 goto no_system_call_restart;
65 /* fallthrough */
66 case -ERESTARTNOINTR:
67 /* Decode syscall # */
68 regs->regs[REG_RET] = regs->syscall_nr;
69 regs->pc -= 4;
70 break;
71 }
72}
73
Paul Mundtab99c732008-07-30 19:55:30 +090074/*
75 * Note that 'init' is a special process: it doesn't get signals it doesn't
76 * want to handle. Thus you cannot kill init even with a SIGKILL even by
77 * mistake.
78 *
79 * Note that we go through the signals twice: once to check the signals that
80 * the kernel can handle, and then we build all the user-level signal handling
81 * stack-frames in one go after that.
82 */
Al Viro9ef461a2012-04-22 01:16:34 -040083static void do_signal(struct pt_regs *regs)
Paul Mundtab99c732008-07-30 19:55:30 +090084{
85 siginfo_t info;
86 int signr;
87 struct k_sigaction ka;
88
89 /*
90 * We want the common case to go fast, which
91 * is why we may in certain cases get here from
92 * kernel mode. Just return without doing anything
93 * if so.
94 */
95 if (!user_mode(regs))
Al Viro9ef461a2012-04-22 01:16:34 -040096 return;
Paul Mundtab99c732008-07-30 19:55:30 +090097
Paul Mundtab99c732008-07-30 19:55:30 +090098 signr = get_signal_to_deliver(&info, &ka, regs, 0);
Paul Mundtab99c732008-07-30 19:55:30 +090099 if (signr > 0) {
Paul Mundt03f07872009-01-29 11:21:38 +0900100 handle_syscall_restart(regs, &ka.sa);
Paul Mundt94e2fb32008-12-10 19:46:18 +0900101
Paul Mundtab99c732008-07-30 19:55:30 +0900102 /* Whee! Actually deliver the signal. */
Al Viroa610d6e2012-05-21 23:42:15 -0400103 handle_signal(signr, &info, &ka, regs);
Al Viro5754f412012-04-26 23:52:33 -0400104 return;
Paul Mundtab99c732008-07-30 19:55:30 +0900105 }
106
Paul Mundtab99c732008-07-30 19:55:30 +0900107 /* Did we come from a system call? */
108 if (regs->syscall_nr >= 0) {
109 /* Restart the system call - no handlers present */
110 switch (regs->regs[REG_RET]) {
111 case -ERESTARTNOHAND:
112 case -ERESTARTSYS:
113 case -ERESTARTNOINTR:
114 /* Decode Syscall # */
115 regs->regs[REG_RET] = regs->syscall_nr;
116 regs->pc -= 4;
117 break;
118
119 case -ERESTART_RESTARTBLOCK:
120 regs->regs[REG_RET] = __NR_restart_syscall;
121 regs->pc -= 4;
122 break;
123 }
124 }
125
126 /* No signal to deliver -- put the saved sigmask back */
Al Viro51a7b442012-05-21 23:33:55 -0400127 restore_saved_sigmask();
Paul Mundtab99c732008-07-30 19:55:30 +0900128}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
130/*
131 * Atomically swap in the new signal mask, and wait for a signal.
132 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133asmlinkage int
Al Viro9ef461a2012-04-22 01:16:34 -0400134sys_sigsuspend(old_sigset_t mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135{
Al Viro9ef461a2012-04-22 01:16:34 -0400136 sigset_t blocked;
Matt Fleming5e047fa2012-03-28 15:16:32 -0700137 siginitset(&blocked, mask);
Al Viro9ef461a2012-04-22 01:16:34 -0400138 return sigsuspend(&blocked);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139}
140
141asmlinkage int
142sys_sigaction(int sig, const struct old_sigaction __user *act,
143 struct old_sigaction __user *oact)
144{
145 struct k_sigaction new_ka, old_ka;
146 int ret;
147
148 if (act) {
149 old_sigset_t mask;
150 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
151 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
Al Viroa46808e2012-04-22 16:59:56 -0400152 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
153 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
154 __get_user(mask, &act->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 siginitset(&new_ka.sa.sa_mask, mask);
157 }
158
159 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
160
161 if (!ret && oact) {
162 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
163 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
Al Viroa46808e2012-04-22 16:59:56 -0400164 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
165 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
166 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 }
169
170 return ret;
171}
172
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173/*
174 * Do a signal return; undo the signal stack.
175 */
Paul Mundt94e2fb32008-12-10 19:46:18 +0900176struct sigframe {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 struct sigcontext sc;
178 unsigned long extramask[_NSIG_WORDS-1];
179 long long retcode[2];
180};
181
Paul Mundt94e2fb32008-12-10 19:46:18 +0900182struct rt_sigframe {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 struct siginfo __user *pinfo;
184 void *puc;
185 struct siginfo info;
186 struct ucontext uc;
187 long long retcode[2];
188};
189
190#ifdef CONFIG_SH_FPU
191static inline int
192restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
193{
194 int err = 0;
195 int fpvalid;
196
197 err |= __get_user (fpvalid, &sc->sc_fpvalid);
198 conditional_used_math(fpvalid);
199 if (! fpvalid)
200 return err;
201
202 if (current == last_task_used_math) {
203 last_task_used_math = NULL;
204 regs->sr |= SR_FD;
205 }
206
Paul Mundt3ef29322010-01-19 15:40:03 +0900207 err |= __copy_from_user(&current->thread.xstate->hardfpu, &sc->sc_fpregs[0],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 (sizeof(long long) * 32) + (sizeof(int) * 1));
209
210 return err;
211}
212
213static inline int
214setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
215{
216 int err = 0;
217 int fpvalid;
218
219 fpvalid = !!used_math();
220 err |= __put_user(fpvalid, &sc->sc_fpvalid);
221 if (! fpvalid)
222 return err;
223
224 if (current == last_task_used_math) {
Paul Mundt600ee242007-11-19 19:13:38 +0900225 enable_fpu();
Matt Fleming61cc7b02009-12-14 20:12:04 +0000226 save_fpu(current);
Paul Mundt600ee242007-11-19 19:13:38 +0900227 disable_fpu();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 last_task_used_math = NULL;
229 regs->sr |= SR_FD;
230 }
231
Paul Mundt3ef29322010-01-19 15:40:03 +0900232 err |= __copy_to_user(&sc->sc_fpregs[0], &current->thread.xstate->hardfpu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 (sizeof(long long) * 32) + (sizeof(int) * 1));
234 clear_used_math();
235
236 return err;
237}
238#else
239static inline int
240restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900241{
242 return 0;
243}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244static inline int
245setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900246{
247 return 0;
248}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249#endif
250
251static int
252restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, long long *r2_p)
253{
254 unsigned int err = 0;
255 unsigned long long current_sr, new_sr;
256#define SR_MASK 0xffff8cfd
257
258#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
259
260 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
261 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
262 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
263 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
264 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
265 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
266 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
267 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
268 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
269 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
270 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
271 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
272 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
273 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
274 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
275 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
276 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
277 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
278
279 /* Prevent the signal handler manipulating SR in a way that can
280 crash the kernel. i.e. only allow S, Q, M, PR, SZ, FR to be
281 modified */
282 current_sr = regs->sr;
283 err |= __get_user(new_sr, &sc->sc_sr);
284 regs->sr &= SR_MASK;
285 regs->sr |= (new_sr & ~SR_MASK);
286
287 COPY(pc);
288
289#undef COPY
290
291 /* Must do this last in case it sets regs->sr.fd (i.e. after rest of sr
292 * has been restored above.) */
293 err |= restore_sigcontext_fpu(regs, sc);
294
295 regs->syscall_nr = -1; /* disable syscall checks */
296 err |= __get_user(*r2_p, &sc->sc_regs[REG_RET]);
297 return err;
298}
299
300asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
301 unsigned long r4, unsigned long r5,
302 unsigned long r6, unsigned long r7,
303 struct pt_regs * regs)
304{
305 struct sigframe __user *frame = (struct sigframe __user *) (long) REF_REG_SP;
306 sigset_t set;
307 long long ret;
308
Paul Mundt1bec1572008-09-24 14:37:35 +0900309 /* Always make any pending restarted system calls return -EINTR */
310 current_thread_info()->restart_block.fn = do_no_restart_syscall;
311
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
313 goto badframe;
314
315 if (__get_user(set.sig[0], &frame->sc.oldmask)
316 || (_NSIG_WORDS > 1
317 && __copy_from_user(&set.sig[1], &frame->extramask,
318 sizeof(frame->extramask))))
319 goto badframe;
320
Matt Fleming5e047fa2012-03-28 15:16:32 -0700321 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322
323 if (restore_sigcontext(regs, &frame->sc, &ret))
324 goto badframe;
325 regs->pc -= 4;
326
327 return (int) ret;
328
329badframe:
330 force_sig(SIGSEGV, current);
331 return 0;
332}
333
334asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
335 unsigned long r4, unsigned long r5,
336 unsigned long r6, unsigned long r7,
337 struct pt_regs * regs)
338{
339 struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP;
340 sigset_t set;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 long long ret;
342
Paul Mundt1bec1572008-09-24 14:37:35 +0900343 /* Always make any pending restarted system calls return -EINTR */
344 current_thread_info()->restart_block.fn = do_no_restart_syscall;
345
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
347 goto badframe;
348
349 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
350 goto badframe;
351
Matt Fleming5e047fa2012-03-28 15:16:32 -0700352 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
354 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret))
355 goto badframe;
356 regs->pc -= 4;
357
Al Viro7a879a92012-12-23 03:46:05 -0500358 if (restore_altstack(&frame->uc.uc_stack))
Al Viro9dc87c72012-09-20 16:38:34 -0400359 goto badframe;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
361 return (int) ret;
362
363badframe:
364 force_sig(SIGSEGV, current);
365 return 0;
366}
367
368/*
369 * Set up a signal frame.
370 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371static int
372setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
373 unsigned long mask)
374{
375 int err = 0;
376
377 /* Do this first, otherwise is this sets sr->fd, that value isn't preserved. */
378 err |= setup_sigcontext_fpu(regs, sc);
379
380#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
381
382 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
383 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
384 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
385 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
386 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
387 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
388 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
389 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
390 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
391 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
392 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
393 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
394 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
395 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
396 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
397 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
398 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
399 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
400 COPY(sr); COPY(pc);
401
402#undef COPY
403
404 err |= __put_user(mask, &sc->oldmask);
405
406 return err;
407}
408
409/*
410 * Determine which stack to use..
411 */
412static inline void __user *
413get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
414{
Laurent MEYERd09042d2006-06-23 02:05:36 -0700415 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 sp = current->sas_ss_sp + current->sas_ss_size;
417
418 return (void __user *)((sp - frame_size) & -8ul);
419}
420
421void sa_default_restorer(void); /* See comments below */
422void sa_default_rt_restorer(void); /* See comments below */
423
Paul Mundt6ac03432008-12-10 19:26:44 +0900424static int setup_frame(int sig, struct k_sigaction *ka,
425 sigset_t *set, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426{
427 struct sigframe __user *frame;
428 int err = 0;
429 int signal;
430
431 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
432
433 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
434 goto give_sigsegv;
435
436 signal = current_thread_info()->exec_domain
437 && current_thread_info()->exec_domain->signal_invmap
438 && sig < 32
439 ? current_thread_info()->exec_domain->signal_invmap[sig]
440 : sig;
441
442 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
443
444 /* Give up earlier as i386, in case */
445 if (err)
446 goto give_sigsegv;
447
448 if (_NSIG_WORDS > 1) {
449 err |= __copy_to_user(frame->extramask, &set->sig[1],
450 sizeof(frame->extramask)); }
451
452 /* Give up earlier as i386, in case */
453 if (err)
454 goto give_sigsegv;
455
456 /* Set up to return from userspace. If provided, use a stub
457 already in userspace. */
458 if (ka->sa.sa_flags & SA_RESTORER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 /*
460 * On SH5 all edited pointers are subject to NEFF
461 */
Paul Mundtc7914832009-08-04 17:14:39 +0900462 DEREF_REG_PR = neff_sign_extend((unsigned long)
463 ka->sa.sa_restorer | 0x1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 } else {
465 /*
466 * Different approach on SH5.
467 * . Endianness independent asm code gets placed in entry.S .
468 * This is limited to four ASM instructions corresponding
469 * to two long longs in size.
470 * . err checking is done on the else branch only
471 * . flush_icache_range() is called upon __put_user() only
472 * . all edited pointers are subject to NEFF
473 * . being code, linker turns ShMedia bit on, always
474 * dereference index -1.
475 */
Paul Mundtc7914832009-08-04 17:14:39 +0900476 DEREF_REG_PR = neff_sign_extend((unsigned long)
477 frame->retcode | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
479 if (__copy_to_user(frame->retcode,
Paul Mundt091db042008-09-29 19:44:40 +0900480 (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 goto give_sigsegv;
482
483 /* Cohere the trampoline with the I-cache. */
Paul Mundtb6138812007-11-11 15:53:51 +0900484 flush_cache_sigtramp(DEREF_REG_PR-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 }
486
487 /*
488 * Set up registers for signal handler.
489 * All edited pointers are subject to NEFF.
490 */
Paul Mundtc7914832009-08-04 17:14:39 +0900491 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
493
494 /* FIXME:
495 The glibc profiling support for SH-5 needs to be passed a sigcontext
496 so it can retrieve the PC. At some point during 2003 the glibc
497 support was changed to receive the sigcontext through the 2nd
498 argument, but there are still versions of libc.so in use that use
499 the 3rd argument. Until libc.so is stabilised, pass the sigcontext
500 through both 2nd and 3rd arguments.
501 */
502
503 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
504 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
505
Paul Mundtc7914832009-08-04 17:14:39 +0900506 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
508 set_fs(USER_DS);
509
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 /* Broken %016Lx */
Paul Mundt6ac03432008-12-10 19:26:44 +0900511 pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
512 signal, current->comm, current->pid, frame,
513 regs->pc >> 32, regs->pc & 0xffffffff,
514 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515
Paul Mundt6ac03432008-12-10 19:26:44 +0900516 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517
518give_sigsegv:
519 force_sigsegv(sig, current);
Paul Mundt6ac03432008-12-10 19:26:44 +0900520 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521}
522
Paul Mundt6ac03432008-12-10 19:26:44 +0900523static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
524 sigset_t *set, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525{
526 struct rt_sigframe __user *frame;
527 int err = 0;
528 int signal;
529
530 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
531
532 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
533 goto give_sigsegv;
534
535 signal = current_thread_info()->exec_domain
536 && current_thread_info()->exec_domain->signal_invmap
537 && sig < 32
538 ? current_thread_info()->exec_domain->signal_invmap[sig]
539 : sig;
540
541 err |= __put_user(&frame->info, &frame->pinfo);
542 err |= __put_user(&frame->uc, &frame->puc);
543 err |= copy_siginfo_to_user(&frame->info, info);
544
545 /* Give up earlier as i386, in case */
546 if (err)
547 goto give_sigsegv;
548
549 /* Create the ucontext. */
550 err |= __put_user(0, &frame->uc.uc_flags);
551 err |= __put_user(0, &frame->uc.uc_link);
Al Viro7a879a92012-12-23 03:46:05 -0500552 err |= __save_altstack(&frame->uc.uc_stack, regs->regs[REG_SP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 err |= setup_sigcontext(&frame->uc.uc_mcontext,
554 regs, set->sig[0]);
555 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
556
557 /* Give up earlier as i386, in case */
558 if (err)
559 goto give_sigsegv;
560
561 /* Set up to return from userspace. If provided, use a stub
562 already in userspace. */
563 if (ka->sa.sa_flags & SA_RESTORER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 /*
565 * On SH5 all edited pointers are subject to NEFF
566 */
Paul Mundtc7914832009-08-04 17:14:39 +0900567 DEREF_REG_PR = neff_sign_extend((unsigned long)
568 ka->sa.sa_restorer | 0x1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 } else {
570 /*
571 * Different approach on SH5.
572 * . Endianness independent asm code gets placed in entry.S .
573 * This is limited to four ASM instructions corresponding
574 * to two long longs in size.
575 * . err checking is done on the else branch only
576 * . flush_icache_range() is called upon __put_user() only
577 * . all edited pointers are subject to NEFF
578 * . being code, linker turns ShMedia bit on, always
579 * dereference index -1.
580 */
Paul Mundtc7914832009-08-04 17:14:39 +0900581 DEREF_REG_PR = neff_sign_extend((unsigned long)
582 frame->retcode | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583
584 if (__copy_to_user(frame->retcode,
Paul Mundt091db042008-09-29 19:44:40 +0900585 (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 goto give_sigsegv;
587
Paul Mundtc7914832009-08-04 17:14:39 +0900588 /* Cohere the trampoline with the I-cache. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
590 }
591
592 /*
593 * Set up registers for signal handler.
594 * All edited pointers are subject to NEFF.
595 */
Paul Mundtc7914832009-08-04 17:14:39 +0900596 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
598 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
599 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
Paul Mundtc7914832009-08-04 17:14:39 +0900600 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601
602 set_fs(USER_DS);
603
Paul Mundt6ac03432008-12-10 19:26:44 +0900604 pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
605 signal, current->comm, current->pid, frame,
606 regs->pc >> 32, regs->pc & 0xffffffff,
607 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
Paul Mundt6ac03432008-12-10 19:26:44 +0900609 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
611give_sigsegv:
612 force_sigsegv(sig, current);
Paul Mundt6ac03432008-12-10 19:26:44 +0900613 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614}
615
616/*
617 * OK, we're invoking a handler
618 */
Al Viroa610d6e2012-05-21 23:42:15 -0400619static void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
Al Virob7f9a112012-05-02 09:59:21 -0400621 struct pt_regs * regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622{
Al Virob7f9a112012-05-02 09:59:21 -0400623 sigset_t *oldset = sigmask_to_save();
Paul Mundt6ac03432008-12-10 19:26:44 +0900624 int ret;
625
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 /* Set up the stack frame */
627 if (ka->sa.sa_flags & SA_SIGINFO)
Paul Mundt6ac03432008-12-10 19:26:44 +0900628 ret = setup_rt_frame(sig, ka, info, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 else
Paul Mundt6ac03432008-12-10 19:26:44 +0900630 ret = setup_frame(sig, ka, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631
Al Viroa610d6e2012-05-21 23:42:15 -0400632 if (ret)
633 return;
Paul Mundt6ac03432008-12-10 19:26:44 +0900634
Al Viroefee9842012-04-28 02:04:15 -0400635 signal_delivered(sig, info, ka, regs,
Al Viroa610d6e2012-05-21 23:42:15 -0400636 test_thread_flag(TIF_SINGLESTEP));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637}
638
Paul Mundtab99c732008-07-30 19:55:30 +0900639asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640{
Paul Mundtab99c732008-07-30 19:55:30 +0900641 if (thread_info_flags & _TIF_SIGPENDING)
Al Viro9ef461a2012-04-22 01:16:34 -0400642 do_signal(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643
Paul Mundtab99c732008-07-30 19:55:30 +0900644 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
645 clear_thread_flag(TIF_NOTIFY_RESUME);
646 tracehook_notify_resume(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648}