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