aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh64
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/sh64
parent76168c21b78a0bd684d4687d14a2bd76bcf92762 (diff)
sh: Move in the SH-5 signal trampoline impl.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh64')
-rw-r--r--arch/sh64/kernel/signal.c750
1 files changed, 0 insertions, 750 deletions
diff --git a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c
deleted file mode 100644
index 79fc48cf54c6..000000000000
--- a/arch/sh64/kernel/signal.c
+++ /dev/null
@@ -1,750 +0,0 @@
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
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{}
231static inline int
232setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
233{}
234#endif
235
236static int
237restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, long long *r2_p)
238{
239 unsigned int err = 0;
240 unsigned long long current_sr, new_sr;
241#define SR_MASK 0xffff8cfd
242
243#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
244
245 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
246 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
247 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
248 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
249 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
250 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
251 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
252 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
253 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
254 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
255 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
256 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
257 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
258 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
259 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
260 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
261 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
262 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
263
264 /* Prevent the signal handler manipulating SR in a way that can
265 crash the kernel. i.e. only allow S, Q, M, PR, SZ, FR to be
266 modified */
267 current_sr = regs->sr;
268 err |= __get_user(new_sr, &sc->sc_sr);
269 regs->sr &= SR_MASK;
270 regs->sr |= (new_sr & ~SR_MASK);
271
272 COPY(pc);
273
274#undef COPY
275
276 /* Must do this last in case it sets regs->sr.fd (i.e. after rest of sr
277 * has been restored above.) */
278 err |= restore_sigcontext_fpu(regs, sc);
279
280 regs->syscall_nr = -1; /* disable syscall checks */
281 err |= __get_user(*r2_p, &sc->sc_regs[REG_RET]);
282 return err;
283}
284
285asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
286 unsigned long r4, unsigned long r5,
287 unsigned long r6, unsigned long r7,
288 struct pt_regs * regs)
289{
290 struct sigframe __user *frame = (struct sigframe __user *) (long) REF_REG_SP;
291 sigset_t set;
292 long long ret;
293
294 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
295 goto badframe;
296
297 if (__get_user(set.sig[0], &frame->sc.oldmask)
298 || (_NSIG_WORDS > 1
299 && __copy_from_user(&set.sig[1], &frame->extramask,
300 sizeof(frame->extramask))))
301 goto badframe;
302
303 sigdelsetmask(&set, ~_BLOCKABLE);
304
305 spin_lock_irq(&current->sighand->siglock);
306 current->blocked = set;
307 recalc_sigpending();
308 spin_unlock_irq(&current->sighand->siglock);
309
310 if (restore_sigcontext(regs, &frame->sc, &ret))
311 goto badframe;
312 regs->pc -= 4;
313
314 return (int) ret;
315
316badframe:
317 force_sig(SIGSEGV, current);
318 return 0;
319}
320
321asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
322 unsigned long r4, unsigned long r5,
323 unsigned long r6, unsigned long r7,
324 struct pt_regs * regs)
325{
326 struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP;
327 sigset_t set;
328 stack_t __user st;
329 long long ret;
330
331 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
332 goto badframe;
333
334 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
335 goto badframe;
336
337 sigdelsetmask(&set, ~_BLOCKABLE);
338 spin_lock_irq(&current->sighand->siglock);
339 current->blocked = set;
340 recalc_sigpending();
341 spin_unlock_irq(&current->sighand->siglock);
342
343 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret))
344 goto badframe;
345 regs->pc -= 4;
346
347 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
348 goto badframe;
349 /* It is more difficult to avoid calling this function than to
350 call it and ignore errors. */
351 do_sigaltstack(&st, NULL, REF_REG_SP);
352
353 return (int) ret;
354
355badframe:
356 force_sig(SIGSEGV, current);
357 return 0;
358}
359
360/*
361 * Set up a signal frame.
362 */
363
364static int
365setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
366 unsigned long mask)
367{
368 int err = 0;
369
370 /* Do this first, otherwise is this sets sr->fd, that value isn't preserved. */
371 err |= setup_sigcontext_fpu(regs, sc);
372
373#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
374
375 COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]);
376 COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]);
377 COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]);
378 COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]);
379 COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]);
380 COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]);
381 COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]);
382 COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]);
383 COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]);
384 COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]);
385 COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]);
386 COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]);
387 COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]);
388 COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]);
389 COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]);
390 COPY(regs[60]); COPY(regs[61]); COPY(regs[62]);
391 COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]);
392 COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]);
393 COPY(sr); COPY(pc);
394
395#undef COPY
396
397 err |= __put_user(mask, &sc->oldmask);
398
399 return err;
400}
401
402/*
403 * Determine which stack to use..
404 */
405static inline void __user *
406get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
407{
408 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
409 sp = current->sas_ss_sp + current->sas_ss_size;
410
411 return (void __user *)((sp - frame_size) & -8ul);
412}
413
414void sa_default_restorer(void); /* See comments below */
415void sa_default_rt_restorer(void); /* See comments below */
416
417static void setup_frame(int sig, struct k_sigaction *ka,
418 sigset_t *set, struct pt_regs *regs)
419{
420 struct sigframe __user *frame;
421 int err = 0;
422 int signal;
423
424 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
425
426 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
427 goto give_sigsegv;
428
429 signal = current_thread_info()->exec_domain
430 && current_thread_info()->exec_domain->signal_invmap
431 && sig < 32
432 ? current_thread_info()->exec_domain->signal_invmap[sig]
433 : sig;
434
435 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
436
437 /* Give up earlier as i386, in case */
438 if (err)
439 goto give_sigsegv;
440
441 if (_NSIG_WORDS > 1) {
442 err |= __copy_to_user(frame->extramask, &set->sig[1],
443 sizeof(frame->extramask)); }
444
445 /* Give up earlier as i386, in case */
446 if (err)
447 goto give_sigsegv;
448
449 /* Set up to return from userspace. If provided, use a stub
450 already in userspace. */
451 if (ka->sa.sa_flags & SA_RESTORER) {
452 DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1;
453
454 /*
455 * On SH5 all edited pointers are subject to NEFF
456 */
457 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
458 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
459 } else {
460 /*
461 * Different approach on SH5.
462 * . Endianness independent asm code gets placed in entry.S .
463 * This is limited to four ASM instructions corresponding
464 * to two long longs in size.
465 * . err checking is done on the else branch only
466 * . flush_icache_range() is called upon __put_user() only
467 * . all edited pointers are subject to NEFF
468 * . being code, linker turns ShMedia bit on, always
469 * dereference index -1.
470 */
471 DEREF_REG_PR = (unsigned long) frame->retcode | 0x01;
472 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
473 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
474
475 if (__copy_to_user(frame->retcode,
476 (unsigned long long)sa_default_restorer & (~1), 16) != 0)
477 goto give_sigsegv;
478
479 /* Cohere the trampoline with the I-cache. */
480 flush_cache_sigtramp(DEREF_REG_PR-1, DEREF_REG_PR-1+16);
481 }
482
483 /*
484 * Set up registers for signal handler.
485 * All edited pointers are subject to NEFF.
486 */
487 regs->regs[REG_SP] = (unsigned long) frame;
488 regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ?
489 (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP];
490 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
491
492 /* FIXME:
493 The glibc profiling support for SH-5 needs to be passed a sigcontext
494 so it can retrieve the PC. At some point during 2003 the glibc
495 support was changed to receive the sigcontext through the 2nd
496 argument, but there are still versions of libc.so in use that use
497 the 3rd argument. Until libc.so is stabilised, pass the sigcontext
498 through both 2nd and 3rd arguments.
499 */
500
501 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
502 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
503
504 regs->pc = (unsigned long) ka->sa.sa_handler;
505 regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc;
506
507 set_fs(USER_DS);
508
509#if DEBUG_SIG
510 /* Broken %016Lx */
511 printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
512 signal,
513 current->comm, current->pid, frame,
514 regs->pc >> 32, regs->pc & 0xffffffff,
515 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
516#endif
517
518 return;
519
520give_sigsegv:
521 force_sigsegv(sig, current);
522}
523
524static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
525 sigset_t *set, struct pt_regs *regs)
526{
527 struct rt_sigframe __user *frame;
528 int err = 0;
529 int signal;
530
531 frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
532
533 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
534 goto give_sigsegv;
535
536 signal = current_thread_info()->exec_domain
537 && current_thread_info()->exec_domain->signal_invmap
538 && sig < 32
539 ? current_thread_info()->exec_domain->signal_invmap[sig]
540 : sig;
541
542 err |= __put_user(&frame->info, &frame->pinfo);
543 err |= __put_user(&frame->uc, &frame->puc);
544 err |= copy_siginfo_to_user(&frame->info, info);
545
546 /* Give up earlier as i386, in case */
547 if (err)
548 goto give_sigsegv;
549
550 /* Create the ucontext. */
551 err |= __put_user(0, &frame->uc.uc_flags);
552 err |= __put_user(0, &frame->uc.uc_link);
553 err |= __put_user((void *)current->sas_ss_sp,
554 &frame->uc.uc_stack.ss_sp);
555 err |= __put_user(sas_ss_flags(regs->regs[REG_SP]),
556 &frame->uc.uc_stack.ss_flags);
557 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
558 err |= setup_sigcontext(&frame->uc.uc_mcontext,
559 regs, set->sig[0]);
560 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
561
562 /* Give up earlier as i386, in case */
563 if (err)
564 goto give_sigsegv;
565
566 /* Set up to return from userspace. If provided, use a stub
567 already in userspace. */
568 if (ka->sa.sa_flags & SA_RESTORER) {
569 DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1;
570
571 /*
572 * On SH5 all edited pointers are subject to NEFF
573 */
574 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
575 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
576 } else {
577 /*
578 * Different approach on SH5.
579 * . Endianness independent asm code gets placed in entry.S .
580 * This is limited to four ASM instructions corresponding
581 * to two long longs in size.
582 * . err checking is done on the else branch only
583 * . flush_icache_range() is called upon __put_user() only
584 * . all edited pointers are subject to NEFF
585 * . being code, linker turns ShMedia bit on, always
586 * dereference index -1.
587 */
588
589 DEREF_REG_PR = (unsigned long) frame->retcode | 0x01;
590 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
591 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
592
593 if (__copy_to_user(frame->retcode,
594 (unsigned long long)sa_default_rt_restorer & (~1), 16) != 0)
595 goto give_sigsegv;
596
597 flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
598 }
599
600 /*
601 * Set up registers for signal handler.
602 * All edited pointers are subject to NEFF.
603 */
604 regs->regs[REG_SP] = (unsigned long) frame;
605 regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ?
606 (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP];
607 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
608 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
609 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
610 regs->pc = (unsigned long) ka->sa.sa_handler;
611 regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc;
612
613 set_fs(USER_DS);
614
615#if DEBUG_SIG
616 /* Broken %016Lx */
617 printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n",
618 signal,
619 current->comm, current->pid, frame,
620 regs->pc >> 32, regs->pc & 0xffffffff,
621 DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
622#endif
623
624 return;
625
626give_sigsegv:
627 force_sigsegv(sig, current);
628}
629
630/*
631 * OK, we're invoking a handler
632 */
633
634static void
635handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
636 sigset_t *oldset, struct pt_regs * regs)
637{
638 /* Are we from a system call? */
639 if (regs->syscall_nr >= 0) {
640 /* If so, check system call restarting.. */
641 switch (regs->regs[REG_RET]) {
642 case -ERESTART_RESTARTBLOCK:
643 case -ERESTARTNOHAND:
644 regs->regs[REG_RET] = -EINTR;
645 break;
646
647 case -ERESTARTSYS:
648 if (!(ka->sa.sa_flags & SA_RESTART)) {
649 regs->regs[REG_RET] = -EINTR;
650 break;
651 }
652 /* fallthrough */
653 case -ERESTARTNOINTR:
654 /* Decode syscall # */
655 regs->regs[REG_RET] = regs->syscall_nr;
656 regs->pc -= 4;
657 }
658 }
659
660 /* Set up the stack frame */
661 if (ka->sa.sa_flags & SA_SIGINFO)
662 setup_rt_frame(sig, ka, info, oldset, regs);
663 else
664 setup_frame(sig, ka, oldset, regs);
665
666 spin_lock_irq(&current->sighand->siglock);
667 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
668 if (!(ka->sa.sa_flags & SA_NODEFER))
669 sigaddset(&current->blocked,sig);
670 recalc_sigpending();
671 spin_unlock_irq(&current->sighand->siglock);
672}
673
674/*
675 * Note that 'init' is a special process: it doesn't get signals it doesn't
676 * want to handle. Thus you cannot kill init even with a SIGKILL even by
677 * mistake.
678 *
679 * Note that we go through the signals twice: once to check the signals that
680 * the kernel can handle, and then we build all the user-level signal handling
681 * stack-frames in one go after that.
682 */
683int do_signal(struct pt_regs *regs, sigset_t *oldset)
684{
685 siginfo_t info;
686 int signr;
687 struct k_sigaction ka;
688
689 /*
690 * We want the common case to go fast, which
691 * is why we may in certain cases get here from
692 * kernel mode. Just return without doing anything
693 * if so.
694 */
695 if (!user_mode(regs))
696 return 1;
697
698 if (try_to_freeze())
699 goto no_signal;
700
701 if (test_thread_flag(TIF_RESTORE_SIGMASK))
702 oldset = &current->saved_sigmask;
703 else if (!oldset)
704 oldset = &current->blocked;
705
706 signr = get_signal_to_deliver(&info, &ka, regs, 0);
707
708 if (signr > 0) {
709 /* Whee! Actually deliver the signal. */
710 handle_signal(signr, &info, &ka, oldset, regs);
711
712 /*
713 * If a signal was successfully delivered, the saved sigmask
714 * is in its frame, and we can clear the TIF_RESTORE_SIGMASK
715 * flag.
716 */
717 if (test_thread_flag(TIF_RESTORE_SIGMASK))
718 clear_thread_flag(TIF_RESTORE_SIGMASK);
719
720 return 1;
721 }
722
723no_signal:
724 /* Did we come from a system call? */
725 if (regs->syscall_nr >= 0) {
726 /* Restart the system call - no handlers present */
727 switch (regs->regs[REG_RET]) {
728 case -ERESTARTNOHAND:
729 case -ERESTARTSYS:
730 case -ERESTARTNOINTR:
731 /* Decode Syscall # */
732 regs->regs[REG_RET] = regs->syscall_nr;
733 regs->pc -= 4;
734 break;
735
736 case -ERESTART_RESTARTBLOCK:
737 regs->regs[REG_RET] = __NR_restart_syscall;
738 regs->pc -= 4;
739 break;
740 }
741 }
742
743 /* No signal to deliver -- put the saved sigmask back */
744 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
745 clear_thread_flag(TIF_RESTORE_SIGMASK);
746 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
747 }
748
749 return 0;
750}