437191455ab15346780d26c85543355cf66d42b7
2 * linux/arch/m68k/kernel/signal.c
4 * Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved.
5 * Matt Waddel Matt.Waddel@freescale.com
6 * Jason Jin Jason.Jin@freescale.com
7 * Shrek Wu B16972@freescale.com
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file COPYING in the main directory of this archive
13 * Derived from m68k/kernel/signal.c and the original authors are credited
17 #include <linux/sched.h>
19 #include <linux/kernel.h>
20 #include <linux/signal.h>
21 #include <linux/syscalls.h>
22 #include <linux/errno.h>
23 #include <linux/wait.h>
24 #include <linux/ptrace.h>
25 #include <linux/unistd.h>
26 #include <linux/stddef.h>
27 #include <linux/highuid.h>
28 #include <linux/personality.h>
29 #include <linux/tty.h>
30 #include <linux/binfmts.h>
32 #include <asm/setup.h>
33 #include <asm/cf_uaccess.h>
34 #include <asm/cf_pgtable.h>
35 #include <asm/traps.h>
36 #include <asm/ucontext.h>
37 #include <asm/cacheflush.h>
39 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
41 asmlinkage
int do_signal(sigset_t
*oldset
, struct pt_regs
*regs
);
43 const int frame_extra_sizes
[16] = {
45 [2] = sizeof(((struct frame
*)0)->un
.fmt2
),
46 [3] = sizeof(((struct frame
*)0)->un
.fmt3
),
50 [7] = sizeof(((struct frame
*)0)->un
.fmt7
),
52 [9] = sizeof(((struct frame
*)0)->un
.fmt9
),
53 [10] = sizeof(((struct frame
*)0)->un
.fmta
),
54 [11] = sizeof(((struct frame
*)0)->un
.fmtb
),
62 * Atomically swap in the new signal mask, and wait for a signal.
64 asmlinkage
int do_sigsuspend(struct pt_regs
*regs
)
66 old_sigset_t mask
= regs
->d3
;
70 spin_lock_irq(¤t
->sighand
->siglock
);
71 saveset
= current
->blocked
;
72 siginitset(¤t
->blocked
, mask
);
74 spin_unlock_irq(¤t
->sighand
->siglock
);
78 current
->state
= TASK_INTERRUPTIBLE
;
80 if (do_signal(&saveset
, regs
))
86 do_rt_sigsuspend(struct pt_regs
*regs
)
88 sigset_t __user
*unewset
= (sigset_t __user
*)regs
->d1
;
89 size_t sigsetsize
= (size_t)regs
->d2
;
90 sigset_t saveset
, newset
;
92 /* XXX: Don't preclude handling different sized sigset_t's. */
93 if (sigsetsize
!= sizeof(sigset_t
))
96 if (copy_from_user(&newset
, unewset
, sizeof(newset
)))
98 sigdelsetmask(&newset
, ~_BLOCKABLE
);
100 spin_lock_irq(¤t
->sighand
->siglock
);
101 saveset
= current
->blocked
;
102 current
->blocked
= newset
;
104 spin_unlock_irq(¤t
->sighand
->siglock
);
108 current
->state
= TASK_INTERRUPTIBLE
;
110 if (do_signal(&saveset
, regs
))
116 sys_sigaction(int sig
, const struct old_sigaction __user
*act
,
117 struct old_sigaction __user
*oact
)
119 struct k_sigaction new_ka
, old_ka
;
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
))
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
);
133 ret
= do_sigaction(sig
, act
? &new_ka
: NULL
, oact
? &old_ka
: NULL
);
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
))
140 __put_user(old_ka
.sa
.sa_flags
, &oact
->sa_flags
);
141 __put_user(old_ka
.sa
.sa_mask
.sig
[0], &oact
->sa_mask
);
148 sys_sigaltstack(const stack_t __user
*uss
, stack_t __user
*uoss
)
150 return do_sigaltstack(uss
, uoss
, rdusp());
155 * Do a signal return; undo the signal stack.
157 * Keep the return code on the stack quadword aligned!
158 * That makes the cache flush below easier.
163 char __user
*pretcode
;
166 struct sigcontext __user
*psc
;
168 unsigned long extramask
[_NSIG_WORDS
-1];
169 struct sigcontext sc
;
174 char __user
*pretcode
;
176 struct siginfo __user
*pinfo
;
183 #define FPCONTEXT_SIZE 216
184 #define uc_fpstate uc_filler[0]
185 #define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
186 #define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
189 static unsigned char fpu_version
; /* version num of fpu, set by setup_frame */
191 static inline int restore_fpu_state(struct sigcontext
*sc
)
196 /* restore registers */
197 memcpy(current
->thread
.fpcntl
, sc
->sc_fpcntl
, 12);
198 memcpy(current
->thread
.fp
, sc
->sc_fpregs
, 24);
202 if (CPU_IS_060
? sc
->sc_fpstate
[2] : sc
->sc_fpstate
[0]) {
203 /* Verify the frame format. */
204 if (!CPU_IS_060
&& (sc
->sc_fpstate
[0] != fpu_version
))
206 if (CPU_IS_020_OR_030
) {
207 if (m68k_fputype
& FPU_68881
&&
208 !(sc
->sc_fpstate
[1] == 0x18 || sc
->sc_fpstate
[1] == 0xb4))
210 if (m68k_fputype
& FPU_68882
&&
211 !(sc
->sc_fpstate
[1] == 0x38 || sc
->sc_fpstate
[1] == 0xd4))
213 } else if (CPU_IS_040
) {
214 if (!(sc
->sc_fpstate
[1] == 0x00 ||
215 sc
->sc_fpstate
[1] == 0x28 ||
216 sc
->sc_fpstate
[1] == 0x60))
218 } else if (CPU_IS_060
) {
219 if (!(sc
->sc_fpstate
[3] == 0x00 ||
220 sc
->sc_fpstate
[3] == 0x60 ||
221 sc
->sc_fpstate
[3] == 0xe0))
223 } else if (CPU_IS_CFV4E
) {
224 pr_debug("restore v4e fpu state at %s\n", __func__
);
228 __asm__
volatile ("fmovem %0,%/fp0-%/fp1\n\t"
229 QCHIP_RESTORE_DIRECTIVE
231 : "m" (sc
->sc_fpregs
[0][0])
233 __asm__
volatile ("fmovel %0,%/fpcr"
234 : : "m" (sc
->sc_fpcntl
[0])
236 __asm__
volatile ("fmovel %0,%/fpsr"
237 : : "m" (sc
->sc_fpcntl
[1])
239 __asm__
volatile ("fmovel %0,%/fpiar"
240 : : "m" (sc
->sc_fpcntl
[2])
247 __asm__
volatile ("frestore %0\n\t"
248 QCHIP_RESTORE_DIRECTIVE
: : "m" (*sc
->sc_fpstate
));
256 static inline int rt_restore_fpu_state(struct ucontext __user
*uc
)
258 unsigned char fpstate
[FPCONTEXT_SIZE
];
259 int context_size
= CPU_IS_060
? 8 : 0;
264 /* restore fpu control register */
265 if (__copy_from_user(current
->thread
.fpcntl
,
266 uc
->uc_mcontext
.fpregs
.f_fpcntl
, 12))
268 /* restore all other fpu register */
269 if (__copy_from_user(current
->thread
.fp
,
270 uc
->uc_mcontext
.fpregs
.f_fpregs
, 96))
275 if (__get_user(*(long *)fpstate
, (long __user
*)&uc
->uc_fpstate
))
277 if (CPU_IS_060
? fpstate
[2] : fpstate
[0]) {
279 context_size
= fpstate
[1];
280 /* Verify the frame format. */
281 if (!CPU_IS_060
&& (fpstate
[0] != fpu_version
))
283 if (CPU_IS_020_OR_030
) {
284 if (m68k_fputype
& FPU_68881
&&
285 !(context_size
== 0x18 || context_size
== 0xb4))
287 if (m68k_fputype
& FPU_68882
&&
288 !(context_size
== 0x38 || context_size
== 0xd4))
290 } else if (CPU_IS_040
) {
291 if (!(context_size
== 0x00 ||
292 context_size
== 0x28 ||
293 context_size
== 0x60))
295 } else if (CPU_IS_060
) {
296 if (!(fpstate
[3] == 0x00 ||
297 fpstate
[3] == 0x60 ||
300 } else if (CPU_IS_CFV4E
) {
301 pr_debug("restore coldfire rt v4e fpu"
302 " state at %s\n", __func__
);
305 if (__copy_from_user(&fpregs
, &uc
->uc_mcontext
.fpregs
,
309 __asm__
volatile ("fmovem %0,%/fp0-%/fp7\n\t"
310 QCHIP_RESTORE_DIRECTIVE
312 : "m" (fpregs
.f_fpregs
[0][0])
314 __asm__
volatile ("fmovel %0,%/fpcr"
315 : : "m" (fpregs
.f_fpcntl
[0])
317 __asm__
volatile ("fmovel %0,%/fpsr"
318 : : "m" (fpregs
.f_fpcntl
[1])
320 __asm__
volatile ("fmovel %0,%/fpiar"
321 : : "m" (fpregs
.f_fpcntl
[2])
326 __copy_from_user(fpstate
+ 4, (long __user
*)&uc
->uc_fpstate
+ 1,
330 __asm__
volatile ("frestore %0\n\t"
331 QCHIP_RESTORE_DIRECTIVE
: : "m" (*fpstate
));
341 restore_sigcontext(struct pt_regs
*regs
, struct sigcontext __user
*usc
,
342 void __user
*fp
, int *pd0
)
344 int fsize
, formatvec
;
345 struct sigcontext context
;
348 /* get previous context */
349 if (copy_from_user(&context
, usc
, sizeof(context
)))
352 /* restore passed registers */
353 regs
->d1
= context
.sc_d1
;
354 regs
->a0
= context
.sc_a0
;
355 regs
->a1
= context
.sc_a1
;
356 regs
->sr
= (regs
->sr
& 0xff00) | (context
.sc_sr
& 0xff);
357 regs
->pc
= context
.sc_pc
;
358 regs
->orig_d0
= -1; /* disable syscall checks */
359 wrusp(context
.sc_usp
);
360 formatvec
= context
.sc_formatvec
;
361 regs
->format
= formatvec
>> 12;
362 regs
->vector
= formatvec
& 0xfff;
365 err
= restore_fpu_state(&context
);
368 fsize
= frame_extra_sizes
[regs
->format
];
371 * user process trying to return with weird frame format
374 printk(KERN_DEBUG
"user process returning with weird \
380 /* OK. Make room on the supervisor stack for the extra junk,
385 struct switch_stack
*sw
= (struct switch_stack
*)regs
- 1;
386 regs
->d0
= context
.sc_d0
;
387 #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
389 (" movel %0,%/sp\n\t"
390 " bra ret_from_signal\n"
392 ".section __ex_table,\"a\"\n"
396 : /* no outputs, it doesn't ever return */
397 : "a" (sw
), "d" (fsize
), "d" (frame_offset
/4-1),
398 "n" (frame_offset
), "a" (fp
)
402 * If we ever get here an exception occurred while
403 * building the above stack-frame.
408 *pd0
= context
.sc_d0
;
416 rt_restore_ucontext(struct pt_regs
*regs
, struct switch_stack
*sw
,
417 struct ucontext __user
*uc
, int *pd0
)
420 greg_t __user
*gregs
= uc
->uc_mcontext
.gregs
;
424 err
= __get_user(temp
, &uc
->uc_mcontext
.version
);
425 if (temp
!= MCONTEXT_VERSION
)
427 /* restore passed registers */
428 err
|= __get_user(regs
->d0
, &gregs
[0]);
429 err
|= __get_user(regs
->d1
, &gregs
[1]);
430 err
|= __get_user(regs
->d2
, &gregs
[2]);
431 err
|= __get_user(regs
->d3
, &gregs
[3]);
432 err
|= __get_user(regs
->d4
, &gregs
[4]);
433 err
|= __get_user(regs
->d5
, &gregs
[5]);
434 err
|= __get_user(sw
->d6
, &gregs
[6]);
435 err
|= __get_user(sw
->d7
, &gregs
[7]);
436 err
|= __get_user(regs
->a0
, &gregs
[8]);
437 err
|= __get_user(regs
->a1
, &gregs
[9]);
438 err
|= __get_user(regs
->a2
, &gregs
[10]);
439 err
|= __get_user(sw
->a3
, &gregs
[11]);
440 err
|= __get_user(sw
->a4
, &gregs
[12]);
441 err
|= __get_user(sw
->a5
, &gregs
[13]);
442 err
|= __get_user(sw
->a6
, &gregs
[14]);
443 err
|= __get_user(usp
, &gregs
[15]);
445 err
|= __get_user(regs
->pc
, &gregs
[16]);
446 err
|= __get_user(temp
, &gregs
[17]);
447 regs
->sr
= (regs
->sr
& 0xff00) | (temp
& 0xff);
448 regs
->orig_d0
= -1; /* disable syscall checks */
449 err
|= __get_user(temp
, &uc
->uc_formatvec
);
450 regs
->format
= temp
>> 12;
451 regs
->vector
= temp
& 0xfff;
454 err
|= rt_restore_fpu_state(uc
);
457 if (do_sigaltstack(&uc
->uc_stack
, NULL
, usp
) == -EFAULT
)
460 fsize
= frame_extra_sizes
[regs
->format
];
463 * user process trying to return with weird frame format
466 printk(KERN_DEBUG
"user process returning with weird \
472 /* OK. Make room on the supervisor stack for the extra junk,
477 #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
479 (" movel %0,%/sp\n\t"
480 " bra ret_from_signal\n"
482 ".section __ex_table,\"a\"\n"
486 : /* no outputs, it doesn't ever return */
487 : "a" (sw
), "d" (fsize
), "d" (frame_offset
/4-1),
488 "n" (frame_offset
), "a" (&uc
->uc_extra
)
492 * If we ever get here an exception occurred while
493 * building the above stack-frame.
505 asmlinkage
int do_sigreturn(unsigned long __unused
)
507 struct switch_stack
*sw
= (struct switch_stack
*) &__unused
;
508 struct pt_regs
*regs
= (struct pt_regs
*) (sw
+ 1);
509 unsigned long usp
= rdusp();
510 struct sigframe __user
*frame
= (struct sigframe __user
*)(usp
- 4);
514 if (!access_ok(VERIFY_READ
, frame
, sizeof(*frame
)))
516 if (__get_user(set
.sig
[0], &frame
->sc
.sc_mask
) ||
518 __copy_from_user(&set
.sig
[1], &frame
->extramask
,
519 sizeof(frame
->extramask
))))
522 sigdelsetmask(&set
, ~_BLOCKABLE
);
523 spin_lock_irq(¤t
->sighand
->siglock
);
524 current
->blocked
= set
;
526 spin_unlock_irq(¤t
->sighand
->siglock
);
528 if (restore_sigcontext(regs
, &frame
->sc
, frame
+ 1, &d0
))
533 force_sig(SIGSEGV
, current
);
537 asmlinkage
int do_rt_sigreturn(unsigned long __unused
)
539 struct switch_stack
*sw
= (struct switch_stack
*) &__unused
;
540 struct pt_regs
*regs
= (struct pt_regs
*) (sw
+ 1);
541 unsigned long usp
= rdusp();
542 struct rt_sigframe __user
*frame
=
543 (struct rt_sigframe __user
*)(usp
- 4);
547 if (!access_ok(VERIFY_READ
, frame
, sizeof(*frame
)))
549 if (__copy_from_user(&set
, &frame
->uc
.uc_sigmask
, sizeof(set
)))
552 sigdelsetmask(&set
, ~_BLOCKABLE
);
553 spin_lock_irq(¤t
->sighand
->siglock
);
554 current
->blocked
= set
;
556 spin_unlock_irq(¤t
->sighand
->siglock
);
558 if (rt_restore_ucontext(regs
, sw
, &frame
->uc
, &d0
))
563 force_sig(SIGSEGV
, current
);
569 * Set up a signal frame.
572 static inline void save_fpu_state(struct sigcontext
*sc
, struct pt_regs
*regs
)
576 memcpy(sc
->sc_fpcntl
, current
->thread
.fpcntl
, 12);
577 memcpy(sc
->sc_fpregs
, current
->thread
.fp
, 24);
582 __asm__
volatile ("fsave %0\n\t"
583 QCHIP_RESTORE_DIRECTIVE
584 : : "m" (*sc
->sc_fpstate
) : "memory");
587 if (CPU_IS_060
? sc
->sc_fpstate
[2] : sc
->sc_fpstate
[0]) {
588 fpu_version
= sc
->sc_fpstate
[0];
589 if (CPU_IS_020_OR_030
&&
590 regs
->vector
>= (VEC_FPBRUC
* 4) &&
591 regs
->vector
<= (VEC_FPNAN
* 4)) {
592 /* Clear pending exception in 68882 idle frame */
593 if (*(unsigned short *) sc
->sc_fpstate
== 0x1f38)
594 sc
->sc_fpstate
[0x38] |= 1 << 3;
597 __asm__
volatile ("fmovemd %/fp0-%/fp1,%0"
598 : : "m" (sc
->sc_fpregs
[0][0])
600 __asm__
volatile ("fmovel %/fpcr,%0"
601 : : "m" (sc
->sc_fpcntl
[0])
603 __asm__
volatile ("fmovel %/fpsr,%0"
604 : : "m" (sc
->sc_fpcntl
[1])
606 __asm__
volatile ("fmovel %/fpiar,%0"
607 : : "m" (sc
->sc_fpcntl
[2])
614 static inline int rt_save_fpu_state(struct ucontext __user
*uc
,
615 struct pt_regs
*regs
)
617 unsigned char fpstate
[FPCONTEXT_SIZE
];
618 int context_size
= CPU_IS_060
? 8 : 0;
622 /* save fpu control register */
623 err
|= copy_to_user(uc
->uc_mcontext
.fpregs
.f_fpcntl
,
624 current
->thread
.fpcntl
, 12);
625 /* save all other fpu register */
626 err
|= copy_to_user(uc
->uc_mcontext
.fpregs
.f_fpregs
,
627 current
->thread
.fp
, 96);
632 __asm__
volatile ("fsave %0\n\t"
633 QCHIP_RESTORE_DIRECTIVE
634 : : "m" (*fpstate
) : "memory");
636 err
|= __put_user(*(long *)fpstate
, (long *)&uc
->uc_fpstate
);
637 if (CPU_IS_060
? fpstate
[2] : fpstate
[0]) {
640 context_size
= fpstate
[1];
641 fpu_version
= fpstate
[0];
643 __asm__
volatile ("fmovemd %/fp0-%/fp7,%0"
644 : : "m" (fpregs
.f_fpregs
[0][0])
646 __asm__
volatile ("fmovel %/fpcr,%0"
647 : : "m" (fpregs
.f_fpcntl
[0])
649 __asm__
volatile ("fmovel %/fpsr,%0"
650 : : "m" (fpregs
.f_fpcntl
[1])
652 __asm__
volatile ("fmovel %/fpiar,%0"
653 : : "m" (fpregs
.f_fpcntl
[2])
656 err
|= copy_to_user(&uc
->uc_mcontext
.fpregs
, &fpregs
,
660 err
|= copy_to_user((long *)&uc
->uc_fpstate
+ 1, fpstate
+ 4,
669 static void setup_sigcontext(struct sigcontext
*sc
, struct pt_regs
*regs
,
673 sc
->sc_usp
= rdusp();
674 sc
->sc_d0
= regs
->d0
;
675 sc
->sc_d1
= regs
->d1
;
676 sc
->sc_a0
= regs
->a0
;
677 sc
->sc_a1
= regs
->a1
;
678 sc
->sc_sr
= regs
->sr
;
679 sc
->sc_pc
= regs
->pc
;
680 sc
->sc_formatvec
= regs
->format
<< 12 | regs
->vector
;
682 save_fpu_state(sc
, regs
);
686 static inline int rt_setup_ucontext(struct ucontext __user
*uc
,
687 struct pt_regs
*regs
)
689 struct switch_stack
*sw
= (struct switch_stack
*)regs
- 1;
690 greg_t __user
*gregs
= uc
->uc_mcontext
.gregs
;
693 err
|= __put_user(MCONTEXT_VERSION
, &uc
->uc_mcontext
.version
);
694 err
|= __put_user(regs
->d0
, &gregs
[0]);
695 err
|= __put_user(regs
->d1
, &gregs
[1]);
696 err
|= __put_user(regs
->d2
, &gregs
[2]);
697 err
|= __put_user(regs
->d3
, &gregs
[3]);
698 err
|= __put_user(regs
->d4
, &gregs
[4]);
699 err
|= __put_user(regs
->d5
, &gregs
[5]);
700 err
|= __put_user(sw
->d6
, &gregs
[6]);
701 err
|= __put_user(sw
->d7
, &gregs
[7]);
702 err
|= __put_user(regs
->a0
, &gregs
[8]);
703 err
|= __put_user(regs
->a1
, &gregs
[9]);
704 err
|= __put_user(regs
->a2
, &gregs
[10]);
705 err
|= __put_user(sw
->a3
, &gregs
[11]);
706 err
|= __put_user(sw
->a4
, &gregs
[12]);
707 err
|= __put_user(sw
->a5
, &gregs
[13]);
708 err
|= __put_user(sw
->a6
, &gregs
[14]);
709 err
|= __put_user(rdusp(), &gregs
[15]);
710 err
|= __put_user(regs
->pc
, &gregs
[16]);
711 err
|= __put_user(regs
->sr
, &gregs
[17]);
712 err
|= __put_user((regs
->format
<< 12) | regs
->vector
,
715 err
|= rt_save_fpu_state(uc
, regs
);
720 static inline void push_cache(unsigned long vaddr
)
728 pdir
= pgd_offset(current
->mm
, vaddr
);
729 pmdp
= pmd_offset(pdir
, vaddr
);
730 ptep
= pte_offset_map(pmdp
, vaddr
);
731 paddr
= ((pte_val(*ptep
) & PAGE_MASK
) | (vaddr
& ~PAGE_MASK
));
732 cf_icache_flush_range(paddr
, paddr
+ 8);
733 #elif CONFIG_M547X_8X
734 flush_icache_range(vaddr
, vaddr
+ 8);
738 static inline void __user
*
739 get_sigframe(struct k_sigaction
*ka
, struct pt_regs
*regs
, size_t frame_size
)
743 /* Default to using normal stack. */
746 /* This is the X/Open sanctioned signal stack switching. */
747 if (ka
->sa
.sa_flags
& SA_ONSTACK
) {
748 if (!sas_ss_flags(usp
))
749 usp
= current
->sas_ss_sp
+ current
->sas_ss_size
;
751 return (void __user
*)((usp
- frame_size
) & -8UL);
754 static void setup_frame(int sig
, struct k_sigaction
*ka
,
755 sigset_t
*set
, struct pt_regs
*regs
)
757 struct sigframe __user
*frame
;
758 int fsize
= frame_extra_sizes
[regs
->format
];
759 struct sigcontext context
;
764 printk(KERN_DEBUG
"setup_frame: Unknown frame format %#x\n",
770 frame
= get_sigframe(ka
, regs
, sizeof(*frame
));
772 err
|= __put_user((current_thread_info()->exec_domain
773 && current_thread_info()->exec_domain
->signal_invmap
775 ? current_thread_info()->exec_domain
->signal_invmap
[sig
]
779 err
|= __put_user(regs
->vector
, &frame
->code
);
780 err
|= __put_user(&frame
->sc
, &frame
->psc
);
783 err
|= copy_to_user(frame
->extramask
, &set
->sig
[1],
784 sizeof(frame
->extramask
));
786 setup_sigcontext(&context
, regs
, set
->sig
[0]);
787 err
|= copy_to_user(&frame
->sc
, &context
, sizeof(context
));
789 /* Set up to return from userspace. */
790 err
|= __put_user(frame
->retcode
, &frame
->pretcode
);
791 /* moveq #,d0; trap #0 */
792 err
|= __put_user(0x70004e40 + (__NR_sigreturn
<< 16),
793 (long __user
*)(frame
->retcode
));
798 push_cache((unsigned long) &frame
->retcode
);
800 /* Set up registers for signal handler */
801 wrusp((unsigned long) frame
);
802 regs
->pc
= (unsigned long) ka
->sa
.sa_handler
;
805 /* Prepare to skip over the extra stuff in the exception frame. */
807 struct pt_regs
*tregs
=
808 (struct pt_regs
*)((ulong
)regs
+ regs
->stkadj
);
810 printk(KERN_DEBUG
"Performing stackadjust=%04x\n",
813 /* This must be copied with decreasing addresses to
817 tregs
->pc
= regs
->pc
;
818 tregs
->sr
= regs
->sr
;
823 force_sigsegv(sig
, current
);
827 static void setup_rt_frame(int sig
, struct k_sigaction
*ka
, siginfo_t
*info
,
828 sigset_t
*set
, struct pt_regs
*regs
)
830 struct rt_sigframe __user
*frame
;
831 int fsize
= frame_extra_sizes
[regs
->format
];
836 printk(KERN_DEBUG
"setup_frame: Unknown frame format %#x\n",
842 frame
= get_sigframe(ka
, regs
, sizeof(*frame
));
845 err
|= copy_to_user(&frame
->uc
.uc_extra
, regs
+ 1, fsize
);
846 regs
->stkadj
= fsize
;
849 err
|= __put_user((current_thread_info()->exec_domain
850 && current_thread_info()->exec_domain
->signal_invmap
852 ? current_thread_info()->exec_domain
->signal_invmap
[sig
]
855 err
|= __put_user(&frame
->info
, &frame
->pinfo
);
856 err
|= __put_user(&frame
->uc
, &frame
->puc
);
857 err
|= copy_siginfo_to_user(&frame
->info
, info
);
859 /* Create the ucontext. */
860 err
|= __put_user(0, &frame
->uc
.uc_flags
);
861 err
|= __put_user(NULL
, &frame
->uc
.uc_link
);
862 err
|= __put_user((void __user
*)current
->sas_ss_sp
,
863 &frame
->uc
.uc_stack
.ss_sp
);
864 err
|= __put_user(sas_ss_flags(rdusp()),
865 &frame
->uc
.uc_stack
.ss_flags
);
866 err
|= __put_user(current
->sas_ss_size
, &frame
->uc
.uc_stack
.ss_size
);
867 err
|= rt_setup_ucontext(&frame
->uc
, regs
);
868 err
|= copy_to_user(&frame
->uc
.uc_sigmask
, set
, sizeof(*set
));
870 /* Set up to return from userspace. */
871 err
|= __put_user(frame
->retcode
, &frame
->pretcode
);
873 /* movel #__NR_rt_sigreturn(0xAD),d0; trap #0 */
874 err
|= __put_user(0x203c0000, (long *)(frame
->retcode
+ 0));
875 err
|= __put_user(0x00ad4e40, (long *)(frame
->retcode
+ 4));
880 push_cache((unsigned long) &frame
->retcode
);
882 /* Set up registers for signal handler */
883 wrusp((unsigned long) frame
);
884 regs
->pc
= (unsigned long) ka
->sa
.sa_handler
;
887 /* Prepare to skip over the extra stuff in the exception frame. */
889 struct pt_regs
*tregs
=
890 (struct pt_regs
*)((ulong
)regs
+ regs
->stkadj
);
892 printk(KERN_DEBUG
"Performing stackadjust=%04x\n",
895 /* This must be copied with decreasing addresses to
899 tregs
->pc
= regs
->pc
;
900 tregs
->sr
= regs
->sr
;
905 force_sigsegv(sig
, current
);
910 handle_restart(struct pt_regs
*regs
, struct k_sigaction
*ka
, int has_handler
)
913 case -ERESTARTNOHAND
:
920 if (has_handler
&& !(ka
->sa
.sa_flags
& SA_RESTART
)) {
925 case -ERESTARTNOINTR
:
927 regs
->d0
= regs
->orig_d0
;
934 * OK, we're invoking a handler
937 handle_signal(int sig
, struct k_sigaction
*ka
, siginfo_t
*info
,
938 sigset_t
*oldset
, struct pt_regs
*regs
)
940 /* are we from a system call? */
941 if (regs
->orig_d0
>= 0)
942 /* If so, check system call restarting.. */
943 handle_restart(regs
, ka
, 1);
945 /* set up the stack frame */
946 if (ka
->sa
.sa_flags
& SA_SIGINFO
)
947 setup_rt_frame(sig
, ka
, info
, oldset
, regs
);
949 setup_frame(sig
, ka
, oldset
, regs
);
951 if (ka
->sa
.sa_flags
& SA_ONESHOT
)
952 ka
->sa
.sa_handler
= SIG_DFL
;
954 spin_lock_irq(¤t
->sighand
->siglock
);
955 sigorsets(¤t
->blocked
, ¤t
->blocked
, &ka
->sa
.sa_mask
);
956 if (!(ka
->sa
.sa_flags
& SA_NODEFER
))
957 sigaddset(¤t
->blocked
, sig
);
959 spin_unlock_irq(¤t
->sighand
->siglock
);
963 * Note that 'init' is a special process: it doesn't get signals it doesn't
964 * want to handle. Thus you cannot kill init even with a SIGKILL even by
967 asmlinkage
int do_signal(sigset_t
*oldset
, struct pt_regs
*regs
)
970 struct k_sigaction ka
;
973 current
->thread
.esp0
= (unsigned long) regs
;
976 oldset
= ¤t
->blocked
;
978 signr
= get_signal_to_deliver(&info
, &ka
, regs
, NULL
);
980 /* Whee! Actually deliver the signal. */
981 handle_signal(signr
, &ka
, &info
, oldset
, regs
);
985 /* Did we come from a system call? */
986 if (regs
->orig_d0
>= 0)
987 /* Restart the system call - no handlers present */
988 handle_restart(regs
, NULL
, 0);