blob: 552eb810cd85e6c9199b5558d567f292eacbad20 [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
5 * Copyright (C) 2003 Paul Mundt
6 * 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>
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
43#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
44
45asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
46
47/*
48 * Atomically swap in the new signal mask, and wait for a signal.
49 */
50
51asmlinkage int
52sys_sigsuspend(old_sigset_t mask,
53 unsigned long r3, unsigned long r4, unsigned long r5,
54 unsigned long r6, unsigned long r7,
55 struct pt_regs * regs)
56{
57 sigset_t saveset;
58
59 mask &= _BLOCKABLE;
60 spin_lock_irq(&current->sighand->siglock);
61 saveset = current->blocked;
62 siginitset(&current->blocked, mask);
63 recalc_sigpending();
64 spin_unlock_irq(&current->sighand->siglock);
65
66 REF_REG_RET = -EINTR;
67 while (1) {
68 current->state = TASK_INTERRUPTIBLE;
69 schedule();
70 regs->pc += 4; /* because sys_sigreturn decrements the pc */
71 if (do_signal(regs, &saveset)) {
72 /* pc now points at signal handler. Need to decrement
73 it because entry.S will increment it. */
74 regs->pc -= 4;
75 return -EINTR;
76 }
77 }
78}
79
80asmlinkage int
81sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
82 unsigned long r4, unsigned long r5, unsigned long r6,
83 unsigned long r7,
84 struct pt_regs * regs)
85{
86 sigset_t saveset, newset;
87
88 /* XXX: Don't preclude handling different sized sigset_t's. */
89 if (sigsetsize != sizeof(sigset_t))
90 return -EINVAL;
91
92 if (copy_from_user(&newset, unewset, sizeof(newset)))
93 return -EFAULT;
94 sigdelsetmask(&newset, ~_BLOCKABLE);
95 spin_lock_irq(&current->sighand->siglock);
96 saveset = current->blocked;
97 current->blocked = newset;
98 recalc_sigpending();
99 spin_unlock_irq(&current->sighand->siglock);
100
101 REF_REG_RET = -EINTR;
102 while (1) {
103 current->state = TASK_INTERRUPTIBLE;
104 schedule();
105 regs->pc += 4; /* because sys_sigreturn decrements the pc */
106 if (do_signal(regs, &saveset)) {
107 /* pc now points at signal handler. Need to decrement
108 it because entry.S will increment it. */
109 regs->pc -= 4;
110 return -EINTR;
111 }
112 }
113}
114
115asmlinkage int
116sys_sigaction(int sig, const struct old_sigaction __user *act,
117 struct old_sigaction __user *oact)
118{
119 struct k_sigaction new_ka, old_ka;
120 int ret;
121
122 if (act) {
123 old_sigset_t mask;
124 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
125 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
126 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
127 return -EFAULT;
128 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
129 __get_user(mask, &act->sa_mask);
130 siginitset(&new_ka.sa.sa_mask, mask);
131 }
132
133 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
134
135 if (!ret && oact) {
136 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
137 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
138 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
139 return -EFAULT;
140 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
141 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
142 }
143
144 return ret;
145}
146
147asmlinkage int
148sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
149 unsigned long r4, unsigned long r5, unsigned long r6,
150 unsigned long r7,
151 struct pt_regs * regs)
152{
153 return do_sigaltstack(uss, uoss, REF_REG_SP);
154}
155
156
157/*
158 * Do a signal return; undo the signal stack.
159 */
160
161struct sigframe
162{
163 struct sigcontext sc;
164 unsigned long extramask[_NSIG_WORDS-1];
165 long long retcode[2];
166};
167
168struct rt_sigframe
169{
170 struct siginfo __user *pinfo;
171 void *puc;
172 struct siginfo info;
173 struct ucontext uc;
174 long long retcode[2];
175};
176
177#ifdef CONFIG_SH_FPU
178static inline int
179restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
180{
181 int err = 0;
182 int fpvalid;
183
184 err |= __get_user (fpvalid, &sc->sc_fpvalid);
185 conditional_used_math(fpvalid);
186 if (! fpvalid)
187 return err;
188
189 if (current == last_task_used_math) {
190 last_task_used_math = NULL;
191 regs->sr |= SR_FD;
192 }
193
194 err |= __copy_from_user(&current->thread.fpu.hard, &sc->sc_fpregs[0],
195 (sizeof(long long) * 32) + (sizeof(int) * 1));
196
197 return err;
198}
199
200static inline int
201setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
202{
203 int err = 0;
204 int fpvalid;
205
206 fpvalid = !!used_math();
207 err |= __put_user(fpvalid, &sc->sc_fpvalid);
208 if (! fpvalid)
209 return err;
210
211 if (current == last_task_used_math) {
Paul Mundt600ee242007-11-19 19:13:38 +0900212 enable_fpu();
Paul Mundt332fd572007-11-22 17:30:50 +0900213 save_fpu(current, regs);
Paul Mundt600ee242007-11-19 19:13:38 +0900214 disable_fpu();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 last_task_used_math = NULL;
216 regs->sr |= SR_FD;
217 }
218
219 err |= __copy_to_user(&sc->sc_fpregs[0], &current->thread.fpu.hard,
220 (sizeof(long long) * 32) + (sizeof(int) * 1));
221 clear_used_math();
222
223 return err;
224}
225#else
226static inline int
227restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900228{
229 return 0;
230}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231static inline int
232setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
Paul Mundtf7a7b152007-11-10 20:07:57 +0900233{
234 return 0;
235}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236#endif
237
238static int
239restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, long long *r2_p)
240{
241 unsigned int err = 0;
242 unsigned long long current_sr, new_sr;
243#define SR_MASK 0xffff8cfd
244
245#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
246
247 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
248 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
249 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
250 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
251 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
252 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
253 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
254 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
255 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
256 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
257 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
258 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
259 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
260 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
261 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
262 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
263 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
264 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
265
266 /* Prevent the signal handler manipulating SR in a way that can
267 crash the kernel. i.e. only allow S, Q, M, PR, SZ, FR to be
268 modified */
269 current_sr = regs->sr;
270 err |= __get_user(new_sr, &sc->sc_sr);
271 regs->sr &= SR_MASK;
272 regs->sr |= (new_sr & ~SR_MASK);
273
274 COPY(pc);
275
276#undef COPY
277
278 /* Must do this last in case it sets regs->sr.fd (i.e. after rest of sr
279 * has been restored above.) */
280 err |= restore_sigcontext_fpu(regs, sc);
281
282 regs->syscall_nr = -1; /* disable syscall checks */
283 err |= __get_user(*r2_p, &sc->sc_regs[REG_RET]);
284 return err;
285}
286
287asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
288 unsigned long r4, unsigned long r5,
289 unsigned long r6, unsigned long r7,
290 struct pt_regs * regs)
291{
292 struct sigframe __user *frame = (struct sigframe __user *) (long) REF_REG_SP;
293 sigset_t set;
294 long long ret;
295
296 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
297 goto badframe;
298
299 if (__get_user(set.sig[0], &frame->sc.oldmask)
300 || (_NSIG_WORDS > 1
301 && __copy_from_user(&set.sig[1], &frame->extramask,
302 sizeof(frame->extramask))))
303 goto badframe;
304
305 sigdelsetmask(&set, ~_BLOCKABLE);
306
307 spin_lock_irq(&current->sighand->siglock);
308 current->blocked = set;
309 recalc_sigpending();
310 spin_unlock_irq(&current->sighand->siglock);
311
312 if (restore_sigcontext(regs, &frame->sc, &ret))
313 goto badframe;
314 regs->pc -= 4;
315
316 return (int) ret;
317
318badframe:
319 force_sig(SIGSEGV, current);
320 return 0;
321}
322
323asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
324 unsigned long r4, unsigned long r5,
325 unsigned long r6, unsigned long r7,
326 struct pt_regs * regs)
327{
328 struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP;
329 sigset_t set;
330 stack_t __user st;
331 long long ret;
332
333 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
334 goto badframe;
335
336 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
337 goto badframe;
338
339 sigdelsetmask(&set, ~_BLOCKABLE);
340 spin_lock_irq(&current->sighand->siglock);
341 current->blocked = set;
342 recalc_sigpending();
343 spin_unlock_irq(&current->sighand->siglock);
344
345 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret))
346 goto badframe;
347 regs->pc -= 4;
348
349 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
350 goto badframe;
351 /* It is more difficult to avoid calling this function than to
352 call it and ignore errors. */
353 do_sigaltstack(&st, NULL, REF_REG_SP);
354
355 return (int) ret;
356
357badframe:
358 force_sig(SIGSEGV, current);
359 return 0;
360}
361
362/*
363 * Set up a signal frame.
364 */
365
366static int
367setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
368 unsigned long mask)
369{
370 int err = 0;
371
372 /* Do this first, otherwise is this sets sr->fd, that value isn't preserved. */
373 err |= setup_sigcontext_fpu(regs, sc);
374
375#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
376
377 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
378 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
379 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
380 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
381 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
382 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
383 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
384 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
385 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
386 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
387 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
388 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
389 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
390 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
391 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
392 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
393 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
394 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
395 COPY(sr); COPY(pc);
396
397#undef COPY
398
399 err |= __put_user(mask, &sc->oldmask);
400
401 return err;
402}
403
404/*
405 * Determine which stack to use..
406 */
407static inline void __user *
408get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
409{
Laurent MEYERd09042d2006-06-23 02:05:36 -0700410 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 sp = current->sas_ss_sp + current->sas_ss_size;
412
413 return (void __user *)((sp - frame_size) & -8ul);
414}
415
416void sa_default_restorer(void); /* See comments below */
417void sa_default_rt_restorer(void); /* See comments below */
418
419static void setup_frame(int sig, struct k_sigaction *ka,
420 sigset_t *set, struct pt_regs *regs)
421{
422 struct sigframe __user *frame;
423 int err = 0;
424 int signal;
425
426 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
427
428 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
429 goto give_sigsegv;
430
431 signal = current_thread_info()->exec_domain
432 && current_thread_info()->exec_domain->signal_invmap
433 && sig < 32
434 ? current_thread_info()->exec_domain->signal_invmap[sig]
435 : sig;
436
437 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
438
439 /* Give up earlier as i386, in case */
440 if (err)
441 goto give_sigsegv;
442
443 if (_NSIG_WORDS > 1) {
444 err |= __copy_to_user(frame->extramask, &set->sig[1],
445 sizeof(frame->extramask)); }
446
447 /* Give up earlier as i386, in case */
448 if (err)
449 goto give_sigsegv;
450
451 /* Set up to return from userspace. If provided, use a stub
452 already in userspace. */
453 if (ka->sa.sa_flags & SA_RESTORER) {
454 DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1;
455
456 /*
457 * On SH5 all edited pointers are subject to NEFF
458 */
459 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
460 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
461 } else {
462 /*
463 * Different approach on SH5.
464 * . Endianness independent asm code gets placed in entry.S .
465 * This is limited to four ASM instructions corresponding
466 * to two long longs in size.
467 * . err checking is done on the else branch only
468 * . flush_icache_range() is called upon __put_user() only
469 * . all edited pointers are subject to NEFF
470 * . being code, linker turns ShMedia bit on, always
471 * dereference index -1.
472 */
473 DEREF_REG_PR = (unsigned long) frame->retcode | 0x01;
474 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
475 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
476
477 if (__copy_to_user(frame->retcode,
478 (unsigned long long)sa_default_restorer & (~1), 16) != 0)
479 goto give_sigsegv;
480
481 /* Cohere the trampoline with the I-cache. */
Paul Mundtb6138812007-11-11 15:53:51 +0900482 flush_cache_sigtramp(DEREF_REG_PR-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 }
484
485 /*
486 * Set up registers for signal handler.
487 * All edited pointers are subject to NEFF.
488 */
489 regs->regs[REG_SP] = (unsigned long) frame;
490 regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ?
491 (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP];
492 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
506 regs->pc = (unsigned long) ka->sa.sa_handler;
507 regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc;
508
509 set_fs(USER_DS);
510
511#if DEBUG_SIG
512 /* Broken %016Lx */
513 printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
514 signal,
515 current->comm, current->pid, frame,
516 regs->pc >> 32, regs->pc & 0xffffffff,
517 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
518#endif
519
520 return;
521
522give_sigsegv:
523 force_sigsegv(sig, current);
524}
525
526static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
527 sigset_t *set, struct pt_regs *regs)
528{
529 struct rt_sigframe __user *frame;
530 int err = 0;
531 int signal;
532
533 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
534
535 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
536 goto give_sigsegv;
537
538 signal = current_thread_info()->exec_domain
539 && current_thread_info()->exec_domain->signal_invmap
540 && sig < 32
541 ? current_thread_info()->exec_domain->signal_invmap[sig]
542 : sig;
543
544 err |= __put_user(&frame->info, &frame->pinfo);
545 err |= __put_user(&frame->uc, &frame->puc);
546 err |= copy_siginfo_to_user(&frame->info, info);
547
548 /* Give up earlier as i386, in case */
549 if (err)
550 goto give_sigsegv;
551
552 /* Create the ucontext. */
553 err |= __put_user(0, &frame->uc.uc_flags);
554 err |= __put_user(0, &frame->uc.uc_link);
555 err |= __put_user((void *)current->sas_ss_sp,
556 &frame->uc.uc_stack.ss_sp);
557 err |= __put_user(sas_ss_flags(regs->regs[REG_SP]),
558 &frame->uc.uc_stack.ss_flags);
559 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
560 err |= setup_sigcontext(&frame->uc.uc_mcontext,
561 regs, set->sig[0]);
562 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
563
564 /* Give up earlier as i386, in case */
565 if (err)
566 goto give_sigsegv;
567
568 /* Set up to return from userspace. If provided, use a stub
569 already in userspace. */
570 if (ka->sa.sa_flags & SA_RESTORER) {
571 DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1;
572
573 /*
574 * On SH5 all edited pointers are subject to NEFF
575 */
576 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
577 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
578 } else {
579 /*
580 * Different approach on SH5.
581 * . Endianness independent asm code gets placed in entry.S .
582 * This is limited to four ASM instructions corresponding
583 * to two long longs in size.
584 * . err checking is done on the else branch only
585 * . flush_icache_range() is called upon __put_user() only
586 * . all edited pointers are subject to NEFF
587 * . being code, linker turns ShMedia bit on, always
588 * dereference index -1.
589 */
590
591 DEREF_REG_PR = (unsigned long) frame->retcode | 0x01;
592 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
593 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
594
595 if (__copy_to_user(frame->retcode,
596 (unsigned long long)sa_default_rt_restorer & (~1), 16) != 0)
597 goto give_sigsegv;
598
599 flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
600 }
601
602 /*
603 * Set up registers for signal handler.
604 * All edited pointers are subject to NEFF.
605 */
606 regs->regs[REG_SP] = (unsigned long) frame;
607 regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ?
608 (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP];
609 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
610 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
611 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
612 regs->pc = (unsigned long) ka->sa.sa_handler;
613 regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc;
614
615 set_fs(USER_DS);
616
617#if DEBUG_SIG
618 /* Broken %016Lx */
619 printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
620 signal,
621 current->comm, current->pid, frame,
622 regs->pc >> 32, regs->pc & 0xffffffff,
623 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
624#endif
625
626 return;
627
628give_sigsegv:
629 force_sigsegv(sig, current);
630}
631
632/*
633 * OK, we're invoking a handler
634 */
635
636static void
637handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
638 sigset_t *oldset, struct pt_regs * regs)
639{
640 /* Are we from a system call? */
641 if (regs->syscall_nr >= 0) {
642 /* If so, check system call restarting.. */
643 switch (regs->regs[REG_RET]) {
Paul Mundte227e8f2007-06-19 12:41:32 +0900644 case -ERESTART_RESTARTBLOCK:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 case -ERESTARTNOHAND:
646 regs->regs[REG_RET] = -EINTR;
647 break;
648
649 case -ERESTARTSYS:
650 if (!(ka->sa.sa_flags & SA_RESTART)) {
651 regs->regs[REG_RET] = -EINTR;
652 break;
653 }
654 /* fallthrough */
655 case -ERESTARTNOINTR:
656 /* Decode syscall # */
657 regs->regs[REG_RET] = regs->syscall_nr;
658 regs->pc -= 4;
659 }
660 }
661
662 /* Set up the stack frame */
663 if (ka->sa.sa_flags & SA_SIGINFO)
664 setup_rt_frame(sig, ka, info, oldset, regs);
665 else
666 setup_frame(sig, ka, oldset, regs);
667
Steven Rostedt69be8f12005-08-29 11:44:09 -0400668 spin_lock_irq(&current->sighand->siglock);
669 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
670 if (!(ka->sa.sa_flags & SA_NODEFER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 sigaddset(&current->blocked,sig);
Steven Rostedt69be8f12005-08-29 11:44:09 -0400672 recalc_sigpending();
673 spin_unlock_irq(&current->sighand->siglock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674}
675
676/*
677 * Note that 'init' is a special process: it doesn't get signals it doesn't
678 * want to handle. Thus you cannot kill init even with a SIGKILL even by
679 * mistake.
680 *
681 * Note that we go through the signals twice: once to check the signals that
682 * the kernel can handle, and then we build all the user-level signal handling
683 * stack-frames in one go after that.
684 */
685int do_signal(struct pt_regs *regs, sigset_t *oldset)
686{
687 siginfo_t info;
688 int signr;
689 struct k_sigaction ka;
690
691 /*
692 * We want the common case to go fast, which
693 * is why we may in certain cases get here from
694 * kernel mode. Just return without doing anything
695 * if so.
696 */
697 if (!user_mode(regs))
698 return 1;
699
Nigel Cunningham0e6c1f52005-07-27 11:43:34 -0700700 if (try_to_freeze())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 goto no_signal;
702
Paul Mundtc18fe9a2007-05-14 09:12:39 +0900703 if (test_thread_flag(TIF_RESTORE_SIGMASK))
704 oldset = &current->saved_sigmask;
705 else if (!oldset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 oldset = &current->blocked;
707
708 signr = get_signal_to_deliver(&info, &ka, regs, 0);
709
710 if (signr > 0) {
711 /* Whee! Actually deliver the signal. */
712 handle_signal(signr, &info, &ka, oldset, regs);
Paul Mundtc18fe9a2007-05-14 09:12:39 +0900713
714 /*
715 * If a signal was successfully delivered, the saved sigmask
716 * is in its frame, and we can clear the TIF_RESTORE_SIGMASK
717 * flag.
718 */
719 if (test_thread_flag(TIF_RESTORE_SIGMASK))
720 clear_thread_flag(TIF_RESTORE_SIGMASK);
721
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 return 1;
723 }
724
725no_signal:
726 /* Did we come from a system call? */
727 if (regs->syscall_nr >= 0) {
728 /* Restart the system call - no handlers present */
Paul Mundtc18fe9a2007-05-14 09:12:39 +0900729 switch (regs->regs[REG_RET]) {
730 case -ERESTARTNOHAND:
731 case -ERESTARTSYS:
732 case -ERESTARTNOINTR:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 /* Decode Syscall # */
734 regs->regs[REG_RET] = regs->syscall_nr;
735 regs->pc -= 4;
Paul Mundtc18fe9a2007-05-14 09:12:39 +0900736 break;
737
738 case -ERESTART_RESTARTBLOCK:
739 regs->regs[REG_RET] = __NR_restart_syscall;
740 regs->pc -= 4;
741 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 }
743 }
Paul Mundtc18fe9a2007-05-14 09:12:39 +0900744
745 /* No signal to deliver -- put the saved sigmask back */
746 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
747 clear_thread_flag(TIF_RESTORE_SIGMASK);
748 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
749 }
750
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 return 0;
752}