blob: 23d4c71c91afb032c341b2c3b41da7220ed2f38b [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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130/*
131 * Do a signal return; undo the signal stack.
132 */
Paul Mundt94e2fb32008-12-10 19:46:18 +0900133struct sigframe {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134 struct sigcontext sc;
135 unsigned long extramask[_NSIG_WORDS-1];
136 long long retcode[2];
137};
138
Paul Mundt94e2fb32008-12-10 19:46:18 +0900139struct rt_sigframe {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 struct siginfo __user *pinfo;
141 void *puc;
142 struct siginfo info;
143 struct ucontext uc;
144 long long retcode[2];
145};
146
147#ifdef CONFIG_SH_FPU
148static inline int
149restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
150{
151 int err = 0;
152 int fpvalid;
153
154 err |= __get_user (fpvalid, &sc->sc_fpvalid);
155 conditional_used_math(fpvalid);
156 if (! fpvalid)
157 return err;
158
159 if (current == last_task_used_math) {
160 last_task_used_math = NULL;
161 regs->sr |= SR_FD;
162 }
163
Paul Mundt3ef29322010-01-19 15:40:03 +0900164 err |= __copy_from_user(&current->thread.xstate->hardfpu, &sc->sc_fpregs[0],
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 (sizeof(long long) * 32) + (sizeof(int) * 1));
166
167 return err;
168}
169
170static inline int
171setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
172{
173 int err = 0;
174 int fpvalid;
175
176 fpvalid = !!used_math();
177 err |= __put_user(fpvalid, &sc->sc_fpvalid);
178 if (! fpvalid)
179 return err;
180
181 if (current == last_task_used_math) {
Paul Mundt600ee242007-11-19 19:13:38 +0900182 enable_fpu();
Matt Fleming61cc7b02009-12-14 20:12:04 +0000183 save_fpu(current);
Paul Mundt600ee242007-11-19 19:13:38 +0900184 disable_fpu();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 last_task_used_math = NULL;
186 regs->sr |= SR_FD;
187 }
188
Paul Mundt3ef29322010-01-19 15:40:03 +0900189 err |= __copy_to_user(&sc->sc_fpregs[0], &current->thread.xstate->hardfpu,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 (sizeof(long long) * 32) + (sizeof(int) * 1));
191 clear_used_math();
192
193 return err;
194}
195#else
196static inline int
197restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900198{
199 return 0;
200}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201static inline int
202setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900203{
204 return 0;
205}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206#endif
207
208static int
209restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, long long *r2_p)
210{
211 unsigned int err = 0;
212 unsigned long long current_sr, new_sr;
213#define SR_MASK 0xffff8cfd
214
215#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
216
217 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
218 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
219 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
220 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
221 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
222 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
223 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
224 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
225 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
226 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
227 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
228 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
229 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
230 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
231 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
232 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
233 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
234 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
235
236 /* Prevent the signal handler manipulating SR in a way that can
237 crash the kernel. i.e. only allow S, Q, M, PR, SZ, FR to be
238 modified */
239 current_sr = regs->sr;
240 err |= __get_user(new_sr, &sc->sc_sr);
241 regs->sr &= SR_MASK;
242 regs->sr |= (new_sr & ~SR_MASK);
243
244 COPY(pc);
245
246#undef COPY
247
248 /* Must do this last in case it sets regs->sr.fd (i.e. after rest of sr
249 * has been restored above.) */
250 err |= restore_sigcontext_fpu(regs, sc);
251
252 regs->syscall_nr = -1; /* disable syscall checks */
253 err |= __get_user(*r2_p, &sc->sc_regs[REG_RET]);
254 return err;
255}
256
257asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
258 unsigned long r4, unsigned long r5,
259 unsigned long r6, unsigned long r7,
260 struct pt_regs * regs)
261{
262 struct sigframe __user *frame = (struct sigframe __user *) (long) REF_REG_SP;
263 sigset_t set;
264 long long ret;
265
Paul Mundt1bec1572008-09-24 14:37:35 +0900266 /* Always make any pending restarted system calls return -EINTR */
267 current_thread_info()->restart_block.fn = do_no_restart_syscall;
268
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
270 goto badframe;
271
272 if (__get_user(set.sig[0], &frame->sc.oldmask)
273 || (_NSIG_WORDS > 1
274 && __copy_from_user(&set.sig[1], &frame->extramask,
275 sizeof(frame->extramask))))
276 goto badframe;
277
Matt Fleming5e047fa2012-03-28 15:16:32 -0700278 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
280 if (restore_sigcontext(regs, &frame->sc, &ret))
281 goto badframe;
282 regs->pc -= 4;
283
284 return (int) ret;
285
286badframe:
287 force_sig(SIGSEGV, current);
288 return 0;
289}
290
291asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
292 unsigned long r4, unsigned long r5,
293 unsigned long r6, unsigned long r7,
294 struct pt_regs * regs)
295{
296 struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP;
297 sigset_t set;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 long long ret;
299
Paul Mundt1bec1572008-09-24 14:37:35 +0900300 /* Always make any pending restarted system calls return -EINTR */
301 current_thread_info()->restart_block.fn = do_no_restart_syscall;
302
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
304 goto badframe;
305
306 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
307 goto badframe;
308
Matt Fleming5e047fa2012-03-28 15:16:32 -0700309 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310
311 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret))
312 goto badframe;
313 regs->pc -= 4;
314
Al Viro7a879a92012-12-23 03:46:05 -0500315 if (restore_altstack(&frame->uc.uc_stack))
Al Viro9dc87c72012-09-20 16:38:34 -0400316 goto badframe;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317
318 return (int) ret;
319
320badframe:
321 force_sig(SIGSEGV, current);
322 return 0;
323}
324
325/*
326 * Set up a signal frame.
327 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328static int
329setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
330 unsigned long mask)
331{
332 int err = 0;
333
334 /* Do this first, otherwise is this sets sr->fd, that value isn't preserved. */
335 err |= setup_sigcontext_fpu(regs, sc);
336
337#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
338
339 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
340 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
341 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
342 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
343 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
344 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
345 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
346 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
347 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
348 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
349 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
350 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
351 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
352 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
353 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
354 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
355 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
356 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
357 COPY(sr); COPY(pc);
358
359#undef COPY
360
361 err |= __put_user(mask, &sc->oldmask);
362
363 return err;
364}
365
366/*
367 * Determine which stack to use..
368 */
369static inline void __user *
370get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
371{
Laurent MEYERd09042d2006-06-23 02:05:36 -0700372 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 sp = current->sas_ss_sp + current->sas_ss_size;
374
375 return (void __user *)((sp - frame_size) & -8ul);
376}
377
378void sa_default_restorer(void); /* See comments below */
379void sa_default_rt_restorer(void); /* See comments below */
380
Paul Mundt6ac03432008-12-10 19:26:44 +0900381static int setup_frame(int sig, struct k_sigaction *ka,
382 sigset_t *set, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383{
384 struct sigframe __user *frame;
385 int err = 0;
386 int signal;
387
388 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
389
390 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
391 goto give_sigsegv;
392
393 signal = current_thread_info()->exec_domain
394 && current_thread_info()->exec_domain->signal_invmap
395 && sig < 32
396 ? current_thread_info()->exec_domain->signal_invmap[sig]
397 : sig;
398
399 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
400
401 /* Give up earlier as i386, in case */
402 if (err)
403 goto give_sigsegv;
404
405 if (_NSIG_WORDS > 1) {
406 err |= __copy_to_user(frame->extramask, &set->sig[1],
407 sizeof(frame->extramask)); }
408
409 /* Give up earlier as i386, in case */
410 if (err)
411 goto give_sigsegv;
412
413 /* Set up to return from userspace. If provided, use a stub
414 already in userspace. */
415 if (ka->sa.sa_flags & SA_RESTORER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 /*
417 * On SH5 all edited pointers are subject to NEFF
418 */
Paul Mundtc7914832009-08-04 17:14:39 +0900419 DEREF_REG_PR = neff_sign_extend((unsigned long)
420 ka->sa.sa_restorer | 0x1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 } else {
422 /*
423 * Different approach on SH5.
424 * . Endianness independent asm code gets placed in entry.S .
425 * This is limited to four ASM instructions corresponding
426 * to two long longs in size.
427 * . err checking is done on the else branch only
428 * . flush_icache_range() is called upon __put_user() only
429 * . all edited pointers are subject to NEFF
430 * . being code, linker turns ShMedia bit on, always
431 * dereference index -1.
432 */
Paul Mundtc7914832009-08-04 17:14:39 +0900433 DEREF_REG_PR = neff_sign_extend((unsigned long)
434 frame->retcode | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
436 if (__copy_to_user(frame->retcode,
Paul Mundt091db042008-09-29 19:44:40 +0900437 (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 goto give_sigsegv;
439
440 /* Cohere the trampoline with the I-cache. */
Paul Mundtb6138812007-11-11 15:53:51 +0900441 flush_cache_sigtramp(DEREF_REG_PR-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 }
443
444 /*
445 * Set up registers for signal handler.
446 * All edited pointers are subject to NEFF.
447 */
Paul Mundtc7914832009-08-04 17:14:39 +0900448 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
450
451 /* FIXME:
452 The glibc profiling support for SH-5 needs to be passed a sigcontext
453 so it can retrieve the PC. At some point during 2003 the glibc
454 support was changed to receive the sigcontext through the 2nd
455 argument, but there are still versions of libc.so in use that use
456 the 3rd argument. Until libc.so is stabilised, pass the sigcontext
457 through both 2nd and 3rd arguments.
458 */
459
460 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
461 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
462
Paul Mundtc7914832009-08-04 17:14:39 +0900463 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464
465 set_fs(USER_DS);
466
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 /* Broken %016Lx */
Paul Mundt6ac03432008-12-10 19:26:44 +0900468 pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
469 signal, current->comm, current->pid, frame,
470 regs->pc >> 32, regs->pc & 0xffffffff,
471 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472
Paul Mundt6ac03432008-12-10 19:26:44 +0900473 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474
475give_sigsegv:
476 force_sigsegv(sig, current);
Paul Mundt6ac03432008-12-10 19:26:44 +0900477 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478}
479
Paul Mundt6ac03432008-12-10 19:26:44 +0900480static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
481 sigset_t *set, struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482{
483 struct rt_sigframe __user *frame;
484 int err = 0;
485 int signal;
486
487 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
488
489 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
490 goto give_sigsegv;
491
492 signal = current_thread_info()->exec_domain
493 && current_thread_info()->exec_domain->signal_invmap
494 && sig < 32
495 ? current_thread_info()->exec_domain->signal_invmap[sig]
496 : sig;
497
498 err |= __put_user(&frame->info, &frame->pinfo);
499 err |= __put_user(&frame->uc, &frame->puc);
500 err |= copy_siginfo_to_user(&frame->info, info);
501
502 /* Give up earlier as i386, in case */
503 if (err)
504 goto give_sigsegv;
505
506 /* Create the ucontext. */
507 err |= __put_user(0, &frame->uc.uc_flags);
508 err |= __put_user(0, &frame->uc.uc_link);
Al Viro7a879a92012-12-23 03:46:05 -0500509 err |= __save_altstack(&frame->uc.uc_stack, regs->regs[REG_SP]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 err |= setup_sigcontext(&frame->uc.uc_mcontext,
511 regs, set->sig[0]);
512 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
513
514 /* Give up earlier as i386, in case */
515 if (err)
516 goto give_sigsegv;
517
518 /* Set up to return from userspace. If provided, use a stub
519 already in userspace. */
520 if (ka->sa.sa_flags & SA_RESTORER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 /*
522 * On SH5 all edited pointers are subject to NEFF
523 */
Paul Mundtc7914832009-08-04 17:14:39 +0900524 DEREF_REG_PR = neff_sign_extend((unsigned long)
525 ka->sa.sa_restorer | 0x1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 } else {
527 /*
528 * Different approach on SH5.
529 * . Endianness independent asm code gets placed in entry.S .
530 * This is limited to four ASM instructions corresponding
531 * to two long longs in size.
532 * . err checking is done on the else branch only
533 * . flush_icache_range() is called upon __put_user() only
534 * . all edited pointers are subject to NEFF
535 * . being code, linker turns ShMedia bit on, always
536 * dereference index -1.
537 */
Paul Mundtc7914832009-08-04 17:14:39 +0900538 DEREF_REG_PR = neff_sign_extend((unsigned long)
539 frame->retcode | 0x01);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540
541 if (__copy_to_user(frame->retcode,
Paul Mundt091db042008-09-29 19:44:40 +0900542 (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 goto give_sigsegv;
544
Paul Mundtc7914832009-08-04 17:14:39 +0900545 /* Cohere the trampoline with the I-cache. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
547 }
548
549 /*
550 * Set up registers for signal handler.
551 * All edited pointers are subject to NEFF.
552 */
Paul Mundtc7914832009-08-04 17:14:39 +0900553 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
555 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
556 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
Paul Mundtc7914832009-08-04 17:14:39 +0900557 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558
559 set_fs(USER_DS);
560
Paul Mundt6ac03432008-12-10 19:26:44 +0900561 pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
562 signal, current->comm, current->pid, frame,
563 regs->pc >> 32, regs->pc & 0xffffffff,
564 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
Paul Mundt6ac03432008-12-10 19:26:44 +0900566 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567
568give_sigsegv:
569 force_sigsegv(sig, current);
Paul Mundt6ac03432008-12-10 19:26:44 +0900570 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571}
572
573/*
574 * OK, we're invoking a handler
575 */
Al Viroa610d6e2012-05-21 23:42:15 -0400576static void
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
Al Virob7f9a112012-05-02 09:59:21 -0400578 struct pt_regs * regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579{
Al Virob7f9a112012-05-02 09:59:21 -0400580 sigset_t *oldset = sigmask_to_save();
Paul Mundt6ac03432008-12-10 19:26:44 +0900581 int ret;
582
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 /* Set up the stack frame */
584 if (ka->sa.sa_flags & SA_SIGINFO)
Paul Mundt6ac03432008-12-10 19:26:44 +0900585 ret = setup_rt_frame(sig, ka, info, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 else
Paul Mundt6ac03432008-12-10 19:26:44 +0900587 ret = setup_frame(sig, ka, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588
Al Viroa610d6e2012-05-21 23:42:15 -0400589 if (ret)
590 return;
Paul Mundt6ac03432008-12-10 19:26:44 +0900591
Al Viroefee9842012-04-28 02:04:15 -0400592 signal_delivered(sig, info, ka, regs,
Al Viroa610d6e2012-05-21 23:42:15 -0400593 test_thread_flag(TIF_SINGLESTEP));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594}
595
Paul Mundtab99c732008-07-30 19:55:30 +0900596asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597{
Paul Mundtab99c732008-07-30 19:55:30 +0900598 if (thread_info_flags & _TIF_SIGPENDING)
Al Viro9ef461a2012-04-22 01:16:34 -0400599 do_signal(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
Paul Mundtab99c732008-07-30 19:55:30 +0900601 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
602 clear_thread_flag(TIF_NOTIFY_RESUME);
603 tracehook_notify_resume(regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605}