2 * linux/arch/m68k/kernel/signal.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
12 * Linux/m68k support by Hamish Macdonald
14 * 68060 fixes by Jesper Skov
16 * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
20 * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
21 * Atari :-) Current limitation: Only one sigstack can be active at one time.
22 * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
23 * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
27 #include <linux/sched.h>
29 #include <linux/kernel.h>
30 #include <linux/signal.h>
31 #include <linux/errno.h>
32 #include <linux/wait.h>
33 #include <linux/ptrace.h>
34 #include <linux/unistd.h>
35 #include <linux/stddef.h>
37 #include <asm/setup.h>
38 #include <asm/uaccess.h>
39 #include <asm/pgtable.h>
40 #include <asm/traps.h>
41 #include <asm/ucontext.h>
43 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
45 asmlinkage
int sys_wait4(pid_t pid
, unsigned long *stat_addr
,
46 int options
, unsigned long *ru
);
47 asmlinkage
int do_signal(sigset_t
*oldset
, struct pt_regs
*regs
);
49 const int frame_extra_sizes
[16] = {
51 -1, /* sizeof(((struct frame *)0)->un.fmt1), */
52 sizeof(((struct frame
*)0)->un
.fmt2
),
53 sizeof(((struct frame
*)0)->un
.fmt3
),
54 sizeof(((struct frame
*)0)->un
.fmt4
),
55 -1, /* sizeof(((struct frame *)0)->un.fmt5), */
56 -1, /* sizeof(((struct frame *)0)->un.fmt6), */
57 sizeof(((struct frame
*)0)->un
.fmt7
),
58 -1, /* sizeof(((struct frame *)0)->un.fmt8), */
59 sizeof(((struct frame
*)0)->un
.fmt9
),
60 sizeof(((struct frame
*)0)->un
.fmta
),
61 sizeof(((struct frame
*)0)->un
.fmtb
),
62 -1, /* sizeof(((struct frame *)0)->un.fmtc), */
63 -1, /* sizeof(((struct frame *)0)->un.fmtd), */
64 -1, /* sizeof(((struct frame *)0)->un.fmte), */
65 -1, /* sizeof(((struct frame *)0)->un.fmtf), */
69 * Atomically swap in the new signal mask, and wait for a signal.
71 asmlinkage
int do_sigsuspend(struct pt_regs
*regs
)
73 old_sigset_t mask
= regs
->d3
;
77 saveset
= current
->blocked
;
78 siginitset(¤t
->blocked
, mask
);
79 recalc_sigpending(current
);
83 current
->state
= TASK_INTERRUPTIBLE
;
85 if (do_signal(&saveset
, regs
))
91 do_rt_sigsuspend(struct pt_regs
*regs
)
93 sigset_t
*unewset
= (sigset_t
*)regs
->d1
;
94 size_t sigsetsize
= (size_t)regs
->d2
;
95 sigset_t saveset
, newset
;
97 /* XXX: Don't preclude handling different sized sigset_t's. */
98 if (sigsetsize
!= sizeof(sigset_t
))
101 if (copy_from_user(&newset
, unewset
, sizeof(newset
)))
103 sigdelsetmask(&newset
, ~_BLOCKABLE
);
105 saveset
= current
->blocked
;
106 current
->blocked
= newset
;
107 recalc_sigpending(current
);
111 current
->state
= TASK_INTERRUPTIBLE
;
113 if (do_signal(&saveset
, regs
))
119 sys_sigaction(int sig
, const struct old_sigaction
*act
,
120 struct old_sigaction
*oact
)
122 struct k_sigaction new_ka
, old_ka
;
127 if (verify_area(VERIFY_READ
, act
, sizeof(*act
)) ||
128 __get_user(new_ka
.sa
.sa_handler
, &act
->sa_handler
) ||
129 __get_user(new_ka
.sa
.sa_restorer
, &act
->sa_restorer
))
131 __get_user(new_ka
.sa
.sa_flags
, &act
->sa_flags
);
132 __get_user(mask
, &act
->sa_mask
);
133 siginitset(&new_ka
.sa
.sa_mask
, mask
);
136 ret
= do_sigaction(sig
, act
? &new_ka
: NULL
, oact
? &old_ka
: NULL
);
139 if (verify_area(VERIFY_WRITE
, oact
, sizeof(*oact
)) ||
140 __put_user(old_ka
.sa
.sa_handler
, &oact
->sa_handler
) ||
141 __put_user(old_ka
.sa
.sa_restorer
, &oact
->sa_restorer
))
143 __put_user(old_ka
.sa
.sa_flags
, &oact
->sa_flags
);
144 __put_user(old_ka
.sa
.sa_mask
.sig
[0], &oact
->sa_mask
);
151 sys_sigaltstack(const stack_t
*uss
, stack_t
*uoss
)
153 return do_sigaltstack(uss
, uoss
, rdusp());
158 * Do a signal return; undo the signal stack.
160 * Keep the return code on the stack quadword aligned!
161 * That makes the cache flush below easier.
169 struct sigcontext
*psc
;
171 unsigned long extramask
[_NSIG_WORDS
-1];
172 struct sigcontext sc
;
179 struct siginfo
*pinfo
;
187 static unsigned char fpu_version
= 0; /* version number of fpu, set by setup_frame */
189 static inline int restore_fpu_state(struct sigcontext
*sc
)
193 if (CPU_IS_060
? sc
->sc_fpstate
[2] : sc
->sc_fpstate
[0]) {
194 /* Verify the frame format. */
195 if (!CPU_IS_060
&& (sc
->sc_fpstate
[0] != fpu_version
))
197 if (CPU_IS_020_OR_030
) {
198 if (m68k_fputype
& FPU_68881
&&
199 !(sc
->sc_fpstate
[1] == 0x18 || sc
->sc_fpstate
[1] == 0xb4))
201 if (m68k_fputype
& FPU_68882
&&
202 !(sc
->sc_fpstate
[1] == 0x38 || sc
->sc_fpstate
[1] == 0xd4))
204 } else if (CPU_IS_040
) {
205 if (!(sc
->sc_fpstate
[1] == 0x00 ||
206 sc
->sc_fpstate
[1] == 0x28 ||
207 sc
->sc_fpstate
[1] == 0x60))
209 } else if (CPU_IS_060
) {
210 if (!(sc
->sc_fpstate
[3] == 0x00 ||
211 sc
->sc_fpstate
[3] == 0x60 ||
212 sc
->sc_fpstate
[3] == 0xe0))
217 __asm__
volatile (".chip 68k/68881\n\t"
218 "fmovemx %0,%/fp0-%/fp1\n\t"
219 "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
222 : "m" (*sc
->sc_fpregs
), "m" (*sc
->sc_fpcntl
));
224 __asm__
volatile (".chip 68k/68881\n\t"
226 ".chip 68k" : : "m" (*sc
->sc_fpstate
));
233 #define FPCONTEXT_SIZE 216
234 #define uc_fpstate uc_filler[0]
235 #define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
236 #define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
238 static inline int rt_restore_fpu_state(struct ucontext
*uc
)
240 unsigned char fpstate
[FPCONTEXT_SIZE
];
241 int context_size
= CPU_IS_060
? 8 : 0;
245 if (__get_user(*(long *)fpstate
, (long *)&uc
->uc_fpstate
))
247 if (CPU_IS_060
? fpstate
[2] : fpstate
[0]) {
249 context_size
= fpstate
[1];
250 /* Verify the frame format. */
251 if (!CPU_IS_060
&& (fpstate
[0] != fpu_version
))
253 if (CPU_IS_020_OR_030
) {
254 if (m68k_fputype
& FPU_68881
&&
255 !(context_size
== 0x18 || context_size
== 0xb4))
257 if (m68k_fputype
& FPU_68882
&&
258 !(context_size
== 0x38 || context_size
== 0xd4))
260 } else if (CPU_IS_040
) {
261 if (!(context_size
== 0x00 ||
262 context_size
== 0x28 ||
263 context_size
== 0x60))
265 } else if (CPU_IS_060
) {
266 if (!(fpstate
[3] == 0x00 ||
267 fpstate
[3] == 0x60 ||
272 if (__copy_from_user(&fpregs
, &uc
->uc_mcontext
.fpregs
,
275 __asm__
volatile (".chip 68k/68881\n\t"
276 "fmovemx %0,%/fp0-%/fp7\n\t"
277 "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
280 : "m" (*fpregs
.f_fpregs
),
284 __copy_from_user(fpstate
+ 4, (long *)&uc
->uc_fpstate
+ 1,
287 __asm__
volatile (".chip 68k/68881\n\t"
289 ".chip 68k" : : "m" (*fpstate
));
297 restore_sigcontext(struct pt_regs
*regs
, struct sigcontext
*usc
, void *fp
,
300 int fsize
, formatvec
;
301 struct sigcontext context
;
304 /* get previous context */
305 if (copy_from_user(&context
, usc
, sizeof(context
)))
308 /* restore passed registers */
309 regs
->d1
= context
.sc_d1
;
310 regs
->a0
= context
.sc_a0
;
311 regs
->a1
= context
.sc_a1
;
312 regs
->sr
= (regs
->sr
& 0xff00) | (context
.sc_sr
& 0xff);
313 regs
->pc
= context
.sc_pc
;
314 regs
->orig_d0
= -1; /* disable syscall checks */
315 wrusp(context
.sc_usp
);
316 formatvec
= context
.sc_formatvec
;
317 regs
->format
= formatvec
>> 12;
318 regs
->vector
= formatvec
& 0xfff;
320 err
= restore_fpu_state(&context
);
322 fsize
= frame_extra_sizes
[regs
->format
];
325 * user process trying to return with weird frame format
328 printk("user process returning with weird frame format\n");
333 /* OK. Make room on the supervisor stack for the extra junk,
338 struct switch_stack
*sw
= (struct switch_stack
*)regs
- 1;
339 regs
->d0
= context
.sc_d0
;
340 #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
342 (" movel %0,%/a0\n\t"
343 " subl %1,%/a0\n\t" /* make room on stack */
344 " movel %/a0,%/sp\n\t" /* set stack pointer */
345 /* move switch_stack and pt_regs */
346 "1: movel %0@+,%/a0@+\n\t"
348 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
351 "2: movesl %4@+,%2\n\t"
352 "3: movel %2,%/a0@+\n\t"
354 " bral " SYMBOL_NAME_STR(ret_from_signal
) "\n"
356 ".section __ex_table,\"a\"\n"
361 : /* no outputs, it doesn't ever return */
362 : "a" (sw
), "d" (fsize
), "d" (frame_offset
/4-1),
363 "n" (frame_offset
), "a" (fp
)
367 * If we ever get here an exception occurred while
368 * building the above stack-frame.
373 *pd0
= context
.sc_d0
;
381 rt_restore_ucontext(struct pt_regs
*regs
, struct switch_stack
*sw
,
382 struct ucontext
*uc
, int *pd0
)
385 greg_t
*gregs
= uc
->uc_mcontext
.gregs
;
389 err
= __get_user(temp
, &uc
->uc_mcontext
.version
);
390 if (temp
!= MCONTEXT_VERSION
)
392 /* restore passed registers */
393 err
|= __get_user(regs
->d0
, &gregs
[0]);
394 err
|= __get_user(regs
->d1
, &gregs
[1]);
395 err
|= __get_user(regs
->d2
, &gregs
[2]);
396 err
|= __get_user(regs
->d3
, &gregs
[3]);
397 err
|= __get_user(regs
->d4
, &gregs
[4]);
398 err
|= __get_user(regs
->d5
, &gregs
[5]);
399 err
|= __get_user(sw
->d6
, &gregs
[6]);
400 err
|= __get_user(sw
->d7
, &gregs
[7]);
401 err
|= __get_user(regs
->a0
, &gregs
[8]);
402 err
|= __get_user(regs
->a1
, &gregs
[9]);
403 err
|= __get_user(regs
->a2
, &gregs
[10]);
404 err
|= __get_user(sw
->a3
, &gregs
[11]);
405 err
|= __get_user(sw
->a4
, &gregs
[12]);
406 err
|= __get_user(sw
->a5
, &gregs
[13]);
407 err
|= __get_user(sw
->a6
, &gregs
[14]);
408 err
|= __get_user(usp
, &gregs
[15]);
410 err
|= __get_user(regs
->pc
, &gregs
[16]);
411 err
|= __get_user(temp
, &gregs
[17]);
412 regs
->sr
= (regs
->sr
& 0xff00) | (temp
& 0xff);
413 regs
->orig_d0
= -1; /* disable syscall checks */
414 err
|= __get_user(temp
, &uc
->uc_formatvec
);
415 regs
->format
= temp
>> 12;
416 regs
->vector
= temp
& 0xfff;
418 err
|= rt_restore_fpu_state(uc
);
420 if (do_sigaltstack(&uc
->uc_stack
, NULL
, usp
) == -EFAULT
)
423 fsize
= frame_extra_sizes
[regs
->format
];
426 * user process trying to return with weird frame format
429 printk("user process returning with weird frame format\n");
434 /* OK. Make room on the supervisor stack for the extra junk,
439 #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
441 (" movel %0,%/a0\n\t"
442 " subl %1,%/a0\n\t" /* make room on stack */
443 " movel %/a0,%/sp\n\t" /* set stack pointer */
444 /* move switch_stack and pt_regs */
445 "1: movel %0@+,%/a0@+\n\t"
447 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
450 "2: movesl %4@+,%2\n\t"
451 "3: movel %2,%/a0@+\n\t"
453 " bral " SYMBOL_NAME_STR(ret_from_signal
) "\n"
455 ".section __ex_table,\"a\"\n"
460 : /* no outputs, it doesn't ever return */
461 : "a" (sw
), "d" (fsize
), "d" (frame_offset
/4-1),
462 "n" (frame_offset
), "a" (&uc
->uc_extra
)
466 * If we ever get here an exception occurred while
467 * building the above stack-frame.
479 asmlinkage
int do_sigreturn(unsigned long __unused
)
481 struct switch_stack
*sw
= (struct switch_stack
*) &__unused
;
482 struct pt_regs
*regs
= (struct pt_regs
*) (sw
+ 1);
483 unsigned long usp
= rdusp();
484 struct sigframe
*frame
= (struct sigframe
*)(usp
- 4);
488 if (verify_area(VERIFY_READ
, frame
, sizeof(*frame
)))
490 if (__get_user(set
.sig
[0], &frame
->sc
.sc_mask
) ||
492 __copy_from_user(&set
.sig
[1], &frame
->extramask
,
493 sizeof(frame
->extramask
))))
496 sigdelsetmask(&set
, ~_BLOCKABLE
);
497 current
->blocked
= set
;
498 recalc_sigpending(current
);
500 if (restore_sigcontext(regs
, &frame
->sc
, frame
+ 1, &d0
))
505 force_sig(SIGSEGV
, current
);
509 asmlinkage
int do_rt_sigreturn(unsigned long __unused
)
511 struct switch_stack
*sw
= (struct switch_stack
*) &__unused
;
512 struct pt_regs
*regs
= (struct pt_regs
*) (sw
+ 1);
513 unsigned long usp
= rdusp();
514 struct rt_sigframe
*frame
= (struct rt_sigframe
*)(usp
- 4);
518 if (verify_area(VERIFY_READ
, frame
, sizeof(*frame
)))
520 if (__copy_from_user(&set
, &frame
->uc
.uc_sigmask
, sizeof(set
)))
523 sigdelsetmask(&set
, ~_BLOCKABLE
);
524 current
->blocked
= set
;
525 recalc_sigpending(current
);
527 if (rt_restore_ucontext(regs
, sw
, &frame
->uc
, &d0
))
532 force_sig(SIGSEGV
, current
);
537 * Set up a signal frame.
540 static inline void save_fpu_state(struct sigcontext
*sc
, struct pt_regs
*regs
)
542 __asm__
volatile (".chip 68k/68881\n\t"
545 : : "m" (*sc
->sc_fpstate
) : "memory");
547 if (CPU_IS_060
? sc
->sc_fpstate
[2] : sc
->sc_fpstate
[0]) {
548 fpu_version
= sc
->sc_fpstate
[0];
549 if (CPU_IS_020_OR_030
&&
550 regs
->vector
>= (VEC_FPBRUC
* 4) &&
551 regs
->vector
<= (VEC_FPNAN
* 4)) {
552 /* Clear pending exception in 68882 idle frame */
553 if (*(unsigned short *) sc
->sc_fpstate
== 0x1f38)
554 sc
->sc_fpstate
[0x38] |= 1 << 3;
556 __asm__
volatile (".chip 68k/68881\n\t"
557 "fmovemx %/fp0-%/fp1,%0\n\t"
558 "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
561 : "m" (*sc
->sc_fpregs
),
567 static inline int rt_save_fpu_state(struct ucontext
*uc
, struct pt_regs
*regs
)
569 unsigned char fpstate
[FPCONTEXT_SIZE
];
570 int context_size
= CPU_IS_060
? 8 : 0;
573 __asm__
volatile (".chip 68k/68881\n\t"
576 : : "m" (*fpstate
) : "memory");
578 err
|= __put_user(*(long *)fpstate
, (long *)&uc
->uc_fpstate
);
579 if (CPU_IS_060
? fpstate
[2] : fpstate
[0]) {
582 context_size
= fpstate
[1];
583 fpu_version
= fpstate
[0];
584 if (CPU_IS_020_OR_030
&&
585 regs
->vector
>= (VEC_FPBRUC
* 4) &&
586 regs
->vector
<= (VEC_FPNAN
* 4)) {
587 /* Clear pending exception in 68882 idle frame */
588 if (*(unsigned short *) fpstate
== 0x1f38)
589 fpstate
[0x38] |= 1 << 3;
591 __asm__
volatile (".chip 68k/68881\n\t"
592 "fmovemx %/fp0-%/fp7,%0\n\t"
593 "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
596 : "m" (*fpregs
.f_fpregs
),
599 err
|= copy_to_user(&uc
->uc_mcontext
.fpregs
, &fpregs
,
603 err
|= copy_to_user((long *)&uc
->uc_fpstate
+ 1, fpstate
+ 4,
608 static void setup_sigcontext(struct sigcontext
*sc
, struct pt_regs
*regs
,
612 sc
->sc_usp
= rdusp();
613 sc
->sc_d0
= regs
->d0
;
614 sc
->sc_d1
= regs
->d1
;
615 sc
->sc_a0
= regs
->a0
;
616 sc
->sc_a1
= regs
->a1
;
617 sc
->sc_sr
= regs
->sr
;
618 sc
->sc_pc
= regs
->pc
;
619 sc
->sc_formatvec
= regs
->format
<< 12 | regs
->vector
;
620 save_fpu_state(sc
, regs
);
623 static inline int rt_setup_ucontext(struct ucontext
*uc
, struct pt_regs
*regs
)
625 struct switch_stack
*sw
= (struct switch_stack
*)regs
- 1;
626 greg_t
*gregs
= uc
->uc_mcontext
.gregs
;
629 err
|= __put_user(MCONTEXT_VERSION
, &uc
->uc_mcontext
.version
);
630 err
|= __put_user(regs
->d0
, &gregs
[0]);
631 err
|= __put_user(regs
->d1
, &gregs
[1]);
632 err
|= __put_user(regs
->d2
, &gregs
[2]);
633 err
|= __put_user(regs
->d3
, &gregs
[3]);
634 err
|= __put_user(regs
->d4
, &gregs
[4]);
635 err
|= __put_user(regs
->d5
, &gregs
[5]);
636 err
|= __put_user(sw
->d6
, &gregs
[6]);
637 err
|= __put_user(sw
->d7
, &gregs
[7]);
638 err
|= __put_user(regs
->a0
, &gregs
[8]);
639 err
|= __put_user(regs
->a1
, &gregs
[9]);
640 err
|= __put_user(regs
->a2
, &gregs
[10]);
641 err
|= __put_user(sw
->a3
, &gregs
[11]);
642 err
|= __put_user(sw
->a4
, &gregs
[12]);
643 err
|= __put_user(sw
->a5
, &gregs
[13]);
644 err
|= __put_user(sw
->a6
, &gregs
[14]);
645 err
|= __put_user(rdusp(), &gregs
[15]);
646 err
|= __put_user(regs
->pc
, &gregs
[16]);
647 err
|= __put_user(regs
->sr
, &gregs
[17]);
648 err
|= __put_user((regs
->format
<< 12) | regs
->vector
, &uc
->uc_formatvec
);
649 err
|= rt_save_fpu_state(uc
, regs
);
653 static inline void push_cache (unsigned long vaddr
)
656 * Using the old cache_push_v() was really a big waste.
658 * What we are trying to do is to flush 8 bytes to ram.
659 * Flushing 2 cache lines of 16 bytes is much cheaper than
660 * flushing 1 or 2 pages, as previously done in
667 __asm__
__volatile__ (".chip 68040\n\t"
670 "movec %%mmusr,%0\n\t"
676 temp
|= vaddr
& ~PAGE_MASK
;
678 __asm__
__volatile__ (".chip 68040\n\t"
680 "cpushl %%bc,(%0)\n\t"
684 else if (CPU_IS_060
) {
686 __asm__
__volatile__ (".chip 68060\n\t"
691 __asm__
__volatile__ (".chip 68060\n\t"
692 "cpushl %%bc,(%0)\n\t"
698 * 68030/68020 have no writeback cache;
699 * still need to clear icache.
700 * Note that vaddr is guaranteed to be long word aligned.
703 asm volatile ("movec %%cacr,%0" : "=r" (temp
));
705 asm volatile ("movec %0,%%caar\n\t"
707 : : "r" (vaddr
), "r" (temp
));
708 asm volatile ("movec %0,%%caar\n\t"
710 : : "r" (vaddr
+ 4), "r" (temp
));
715 get_sigframe(struct k_sigaction
*ka
, struct pt_regs
*regs
, size_t frame_size
)
719 /* Default to using normal stack. */
722 /* This is the X/Open sanctioned signal stack switching. */
723 if (ka
->sa
.sa_flags
& SA_ONSTACK
) {
724 if (!on_sig_stack(usp
))
725 usp
= current
->sas_ss_sp
+ current
->sas_ss_size
;
727 return (void *)((usp
- frame_size
) & -8UL);
730 static void setup_frame (int sig
, struct k_sigaction
*ka
,
731 sigset_t
*set
, struct pt_regs
*regs
)
733 struct sigframe
*frame
;
734 int fsize
= frame_extra_sizes
[regs
->format
];
735 struct sigcontext context
;
740 printk ("setup_frame: Unknown frame format %#x\n",
746 frame
= get_sigframe(ka
, regs
, sizeof(*frame
) + fsize
);
749 err
|= copy_to_user (frame
+ 1, regs
+ 1, fsize
);
750 regs
->stkadj
= fsize
;
753 err
|= __put_user((current
->exec_domain
754 && current
->exec_domain
->signal_invmap
756 ? current
->exec_domain
->signal_invmap
[sig
]
760 err
|= __put_user(regs
->vector
, &frame
->code
);
761 err
|= __put_user(&frame
->sc
, &frame
->psc
);
764 err
|= copy_to_user(frame
->extramask
, &set
->sig
[1],
765 sizeof(frame
->extramask
));
767 setup_sigcontext(&context
, regs
, set
->sig
[0]);
768 err
|= copy_to_user (&frame
->sc
, &context
, sizeof(context
));
770 /* Set up to return from userspace. */
771 err
|= __put_user(frame
->retcode
, &frame
->pretcode
);
772 /* moveq #,d0; trap #0 */
773 err
|= __put_user(0x70004e40 + (__NR_sigreturn
<< 16),
774 (long *)(frame
->retcode
));
779 push_cache ((unsigned long) &frame
->retcode
);
781 /* Set up registers for signal handler */
782 wrusp ((unsigned long) frame
);
783 regs
->pc
= (unsigned long) ka
->sa
.sa_handler
;
786 /* Prepare to skip over the extra stuff in the exception frame. */
788 struct pt_regs
*tregs
=
789 (struct pt_regs
*)((ulong
)regs
+ regs
->stkadj
);
791 printk("Performing stackadjust=%04x\n", regs
->stkadj
);
793 /* This must be copied with decreasing addresses to
797 tregs
->pc
= regs
->pc
;
798 tregs
->sr
= regs
->sr
;
804 ka
->sa
.sa_handler
= SIG_DFL
;
805 force_sig(SIGSEGV
, current
);
809 static void setup_rt_frame (int sig
, struct k_sigaction
*ka
, siginfo_t
*info
,
810 sigset_t
*set
, struct pt_regs
*regs
)
812 struct rt_sigframe
*frame
;
813 int fsize
= frame_extra_sizes
[regs
->format
];
818 printk ("setup_frame: Unknown frame format %#x\n",
824 frame
= get_sigframe(ka
, regs
, sizeof(*frame
));
827 err
|= copy_to_user (&frame
->uc
.uc_extra
, regs
+ 1, fsize
);
828 regs
->stkadj
= fsize
;
831 err
|= __put_user((current
->exec_domain
832 && current
->exec_domain
->signal_invmap
834 ? current
->exec_domain
->signal_invmap
[sig
]
837 err
|= __put_user(&frame
->info
, &frame
->pinfo
);
838 err
|= __put_user(&frame
->uc
, &frame
->puc
);
839 err
|= __copy_to_user(&frame
->info
, info
, sizeof(*info
));
841 /* Create the ucontext. */
842 err
|= __put_user(0, &frame
->uc
.uc_flags
);
843 err
|= __put_user(0, &frame
->uc
.uc_link
);
844 err
|= __put_user((void *)current
->sas_ss_sp
,
845 &frame
->uc
.uc_stack
.ss_sp
);
846 err
|= __put_user(sas_ss_flags(rdusp()),
847 &frame
->uc
.uc_stack
.ss_flags
);
848 err
|= __put_user(current
->sas_ss_size
, &frame
->uc
.uc_stack
.ss_size
);
849 err
|= rt_setup_ucontext(&frame
->uc
, regs
);
850 err
|= copy_to_user (&frame
->uc
.uc_sigmask
, set
, sizeof(*set
));
852 /* Set up to return from userspace. */
853 err
|= __put_user(frame
->retcode
, &frame
->pretcode
);
854 /* moveq #,d0; notb d0; trap #0 */
855 err
|= __put_user(0x70004600 + ((__NR_rt_sigreturn
^ 0xff) << 16),
856 (long *)(frame
->retcode
+ 0));
857 err
|= __put_user(0x4e40, (short *)(frame
->retcode
+ 4));
862 push_cache ((unsigned long) &frame
->retcode
);
864 /* Set up registers for signal handler */
865 wrusp ((unsigned long) frame
);
866 regs
->pc
= (unsigned long) ka
->sa
.sa_handler
;
869 /* Prepare to skip over the extra stuff in the exception frame. */
871 struct pt_regs
*tregs
=
872 (struct pt_regs
*)((ulong
)regs
+ regs
->stkadj
);
874 printk("Performing stackadjust=%04x\n", regs
->stkadj
);
876 /* This must be copied with decreasing addresses to
880 tregs
->pc
= regs
->pc
;
881 tregs
->sr
= regs
->sr
;
887 ka
->sa
.sa_handler
= SIG_DFL
;
888 force_sig(SIGSEGV
, current
);
893 handle_restart(struct pt_regs
*regs
, struct k_sigaction
*ka
, int has_handler
)
896 case -ERESTARTNOHAND
:
903 if (has_handler
&& !(ka
->sa
.sa_flags
& SA_RESTART
)) {
908 case -ERESTARTNOINTR
:
910 regs
->d0
= regs
->orig_d0
;
917 * OK, we're invoking a handler
920 handle_signal(int sig
, struct k_sigaction
*ka
, siginfo_t
*info
,
921 sigset_t
*oldset
, struct pt_regs
*regs
)
923 /* are we from a system call? */
924 if (regs
->orig_d0
>= 0)
925 /* If so, check system call restarting.. */
926 handle_restart(regs
, ka
, 1);
928 /* set up the stack frame */
929 if (ka
->sa
.sa_flags
& SA_SIGINFO
)
930 setup_rt_frame(sig
, ka
, info
, oldset
, regs
);
932 setup_frame(sig
, ka
, oldset
, regs
);
934 if (ka
->sa
.sa_flags
& SA_ONESHOT
)
935 ka
->sa
.sa_handler
= SIG_DFL
;
937 sigorsets(¤t
->blocked
,¤t
->blocked
,&ka
->sa
.sa_mask
);
938 if (!(ka
->sa
.sa_flags
& SA_NODEFER
))
939 sigaddset(¤t
->blocked
,sig
);
940 recalc_sigpending(current
);
944 * Note that 'init' is a special process: it doesn't get signals it doesn't
945 * want to handle. Thus you cannot kill init even with a SIGKILL even by
948 * Note that we go through the signals twice: once to check the signals
949 * that the kernel can handle, and then we build all the user-level signal
950 * handling stack-frames in one go after that.
952 asmlinkage
int do_signal(sigset_t
*oldset
, struct pt_regs
*regs
)
955 struct k_sigaction
*ka
;
957 current
->thread
.esp0
= (unsigned long) regs
;
960 oldset
= ¤t
->blocked
;
965 signr
= dequeue_signal(¤t
->blocked
, &info
);
970 if ((current
->flags
& PF_PTRACED
) && signr
!= SIGKILL
) {
971 current
->exit_code
= signr
;
972 current
->state
= TASK_STOPPED
;
975 /* Did we come from a system call? */
976 if (regs
->orig_d0
>= 0) {
977 /* Restart the system call the same way as
978 if the process were not traced. */
979 struct k_sigaction
*ka
=
980 ¤t
->sig
->action
[signr
-1];
982 (ka
->sa
.sa_handler
!= SIG_IGN
&&
983 ka
->sa
.sa_handler
!= SIG_DFL
);
984 handle_restart(regs
, ka
, has_handler
);
986 notify_parent(current
, SIGCHLD
);
989 /* We're back. Did the debugger cancel the sig? */
990 if (!(signr
= current
->exit_code
)) {
992 /* Make sure that a faulted bus cycle isn't
993 restarted (only needed on the 680[23]0). */
994 if (regs
->format
== 10 || regs
->format
== 11)
995 regs
->stkadj
= frame_extra_sizes
[regs
->format
];
998 current
->exit_code
= 0;
1000 /* The debugger continued. Ignore SIGSTOP. */
1001 if (signr
== SIGSTOP
)
1004 /* Update the siginfo structure. Is this good? */
1005 if (signr
!= info
.si_signo
) {
1006 info
.si_signo
= signr
;
1008 info
.si_code
= SI_USER
;
1009 info
.si_pid
= current
->p_pptr
->pid
;
1010 info
.si_uid
= current
->p_pptr
->uid
;
1013 /* If the (new) signal is now blocked, requeue it. */
1014 if (sigismember(¤t
->blocked
, signr
)) {
1015 send_sig_info(signr
, &info
, current
);
1020 ka
= ¤t
->sig
->action
[signr
-1];
1021 if (ka
->sa
.sa_handler
== SIG_IGN
) {
1022 if (signr
!= SIGCHLD
)
1024 /* Check for SIGCHLD: it's special. */
1025 while (sys_wait4(-1, NULL
, WNOHANG
, NULL
) > 0)
1030 if (ka
->sa
.sa_handler
== SIG_DFL
) {
1031 int exit_code
= signr
;
1033 if (current
->pid
== 1)
1037 case SIGCONT
: case SIGCHLD
: case SIGWINCH
:
1040 case SIGTSTP
: case SIGTTIN
: case SIGTTOU
:
1041 if (is_orphaned_pgrp(current
->pgrp
))
1046 current
->state
= TASK_STOPPED
;
1047 current
->exit_code
= signr
;
1048 if (!(current
->p_pptr
->sig
->action
[SIGCHLD
-1]
1049 .sa
.sa_flags
& SA_NOCLDSTOP
))
1050 notify_parent(current
, SIGCHLD
);
1054 case SIGQUIT
: case SIGILL
: case SIGTRAP
:
1055 case SIGIOT
: case SIGFPE
: case SIGSEGV
:
1056 if (do_coredump(signr
, regs
))
1061 sigaddset(¤t
->signal
, signr
);
1062 recalc_sigpending(current
);
1063 current
->flags
|= PF_SIGNALED
;
1069 /* Whee! Actually deliver the signal. */
1070 handle_signal(signr
, ka
, &info
, oldset
, regs
);
1074 /* Did we come from a system call? */
1075 if (regs
->orig_d0
>= 0)
1076 /* Restart the system call - no handlers present */
1077 handle_restart(regs
, NULL
, 0);
1079 /* If we are about to discard some frame stuff we must copy
1080 over the remaining frame. */
1082 struct pt_regs
*tregs
=
1083 (struct pt_regs
*) ((ulong
) regs
+ regs
->stkadj
);
1085 /* This must be copied with decreasing addresses to
1089 tregs
->pc
= regs
->pc
;
1090 tregs
->sr
= regs
->sr
;