- pre3:
[davej-history.git] / arch / m68k / kernel / signal.c
blobfa13dc39037d04edd2d24a4c5451280c5b16a0f0
1 /*
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
8 * for more details.
9 */
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
18 * mathemu support by Roman Zippel
19 * (Note: fpstate in the signal context is completly ignored for the emulator
20 * and the internal floating point format is put on stack)
24 * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
25 * Atari :-) Current limitation: Only one sigstack can be active at one time.
26 * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
27 * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
28 * signal handlers!
31 #include <linux/sched.h>
32 #include <linux/mm.h>
33 #include <linux/kernel.h>
34 #include <linux/signal.h>
35 #include <linux/errno.h>
36 #include <linux/wait.h>
37 #include <linux/ptrace.h>
38 #include <linux/unistd.h>
39 #include <linux/stddef.h>
40 #include <linux/highuid.h>
42 #include <asm/setup.h>
43 #include <asm/uaccess.h>
44 #include <asm/pgtable.h>
45 #include <asm/traps.h>
46 #include <asm/ucontext.h>
48 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
50 asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
51 int options, unsigned long *ru);
52 asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
54 const int frame_extra_sizes[16] = {
56 -1, /* sizeof(((struct frame *)0)->un.fmt1), */
57 sizeof(((struct frame *)0)->un.fmt2),
58 sizeof(((struct frame *)0)->un.fmt3),
59 sizeof(((struct frame *)0)->un.fmt4),
60 -1, /* sizeof(((struct frame *)0)->un.fmt5), */
61 -1, /* sizeof(((struct frame *)0)->un.fmt6), */
62 sizeof(((struct frame *)0)->un.fmt7),
63 -1, /* sizeof(((struct frame *)0)->un.fmt8), */
64 sizeof(((struct frame *)0)->un.fmt9),
65 sizeof(((struct frame *)0)->un.fmta),
66 sizeof(((struct frame *)0)->un.fmtb),
67 -1, /* sizeof(((struct frame *)0)->un.fmtc), */
68 -1, /* sizeof(((struct frame *)0)->un.fmtd), */
69 -1, /* sizeof(((struct frame *)0)->un.fmte), */
70 -1, /* sizeof(((struct frame *)0)->un.fmtf), */
74 * Atomically swap in the new signal mask, and wait for a signal.
76 asmlinkage int do_sigsuspend(struct pt_regs *regs)
78 old_sigset_t mask = regs->d3;
79 sigset_t saveset;
81 mask &= _BLOCKABLE;
82 saveset = current->blocked;
83 siginitset(&current->blocked, mask);
84 recalc_sigpending(current);
86 regs->d0 = -EINTR;
87 while (1) {
88 current->state = TASK_INTERRUPTIBLE;
89 schedule();
90 if (do_signal(&saveset, regs))
91 return -EINTR;
95 asmlinkage int
96 do_rt_sigsuspend(struct pt_regs *regs)
98 sigset_t *unewset = (sigset_t *)regs->d1;
99 size_t sigsetsize = (size_t)regs->d2;
100 sigset_t saveset, newset;
102 /* XXX: Don't preclude handling different sized sigset_t's. */
103 if (sigsetsize != sizeof(sigset_t))
104 return -EINVAL;
106 if (copy_from_user(&newset, unewset, sizeof(newset)))
107 return -EFAULT;
108 sigdelsetmask(&newset, ~_BLOCKABLE);
110 saveset = current->blocked;
111 current->blocked = newset;
112 recalc_sigpending(current);
114 regs->d0 = -EINTR;
115 while (1) {
116 current->state = TASK_INTERRUPTIBLE;
117 schedule();
118 if (do_signal(&saveset, regs))
119 return -EINTR;
123 asmlinkage int
124 sys_sigaction(int sig, const struct old_sigaction *act,
125 struct old_sigaction *oact)
127 struct k_sigaction new_ka, old_ka;
128 int ret;
130 if (act) {
131 old_sigset_t mask;
132 if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
133 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
134 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
135 return -EFAULT;
136 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
137 __get_user(mask, &act->sa_mask);
138 siginitset(&new_ka.sa.sa_mask, mask);
141 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
143 if (!ret && oact) {
144 if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
145 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
146 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
147 return -EFAULT;
148 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
149 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
152 return ret;
155 asmlinkage int
156 sys_sigaltstack(const stack_t *uss, stack_t *uoss)
158 return do_sigaltstack(uss, uoss, rdusp());
163 * Do a signal return; undo the signal stack.
165 * Keep the return code on the stack quadword aligned!
166 * That makes the cache flush below easier.
169 struct sigframe
171 char *pretcode;
172 int sig;
173 int code;
174 struct sigcontext *psc;
175 char retcode[8];
176 unsigned long extramask[_NSIG_WORDS-1];
177 struct sigcontext sc;
180 struct rt_sigframe
182 char *pretcode;
183 int sig;
184 struct siginfo *pinfo;
185 void *puc;
186 char retcode[8];
187 struct siginfo info;
188 struct ucontext uc;
192 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
194 if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
195 return -EFAULT;
196 if (from->si_code < 0)
197 return __copy_to_user(to, from, sizeof(siginfo_t));
198 else {
199 int err;
201 /* If you change siginfo_t structure, please be sure
202 this code is fixed accordingly.
203 It should never copy any pad contained in the structure
204 to avoid security leaks, but must copy the generic
205 3 ints plus the relevant union member. */
206 err = __put_user(from->si_signo, &to->si_signo);
207 err |= __put_user(from->si_errno, &to->si_errno);
208 err |= __put_user((short)from->si_code, &to->si_code);
209 /* First 32bits of unions are always present. */
210 err |= __put_user(from->si_pid, &to->si_pid);
211 switch (from->si_code >> 16) {
212 case __SI_FAULT >> 16:
213 break;
214 case __SI_CHLD >> 16:
215 err |= __put_user(from->si_utime, &to->si_utime);
216 err |= __put_user(from->si_stime, &to->si_stime);
217 err |= __put_user(from->si_status, &to->si_status);
218 default:
219 err |= __put_user(from->si_uid, &to->si_uid);
220 break;
221 /* case __SI_RT: This is not generated by the kernel as of now. */
223 return err;
227 static unsigned char fpu_version = 0; /* version number of fpu, set by setup_frame */
229 static inline int restore_fpu_state(struct sigcontext *sc)
231 int err = 1;
233 if (FPU_IS_EMU) {
234 /* restore registers */
235 memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
236 memcpy(current->thread.fp, sc->sc_fpregs, 24);
237 return 0;
240 if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
241 /* Verify the frame format. */
242 if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version))
243 goto out;
244 if (CPU_IS_020_OR_030) {
245 if (m68k_fputype & FPU_68881 &&
246 !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4))
247 goto out;
248 if (m68k_fputype & FPU_68882 &&
249 !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4))
250 goto out;
251 } else if (CPU_IS_040) {
252 if (!(sc->sc_fpstate[1] == 0x00 ||
253 sc->sc_fpstate[1] == 0x28 ||
254 sc->sc_fpstate[1] == 0x60))
255 goto out;
256 } else if (CPU_IS_060) {
257 if (!(sc->sc_fpstate[3] == 0x00 ||
258 sc->sc_fpstate[3] == 0x60 ||
259 sc->sc_fpstate[3] == 0xe0))
260 goto out;
261 } else
262 goto out;
264 __asm__ volatile (".chip 68k/68881\n\t"
265 "fmovemx %0,%/fp0-%/fp1\n\t"
266 "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
267 ".chip 68k"
268 : /* no outputs */
269 : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
271 __asm__ volatile (".chip 68k/68881\n\t"
272 "frestore %0\n\t"
273 ".chip 68k" : : "m" (*sc->sc_fpstate));
274 err = 0;
276 out:
277 return err;
280 #define FPCONTEXT_SIZE 216
281 #define uc_fpstate uc_filler[0]
282 #define uc_formatvec uc_filler[FPCONTEXT_SIZE/4]
283 #define uc_extra uc_filler[FPCONTEXT_SIZE/4+1]
285 static inline int rt_restore_fpu_state(struct ucontext *uc)
287 unsigned char fpstate[FPCONTEXT_SIZE];
288 int context_size = CPU_IS_060 ? 8 : 0;
289 fpregset_t fpregs;
290 int err = 1;
292 if (FPU_IS_EMU) {
293 /* restore fpu control register */
294 if (__copy_from_user(current->thread.fpcntl,
295 &uc->uc_mcontext.fpregs.f_pcr, 12))
296 goto out;
297 /* restore all other fpu register */
298 if (__copy_from_user(current->thread.fp,
299 uc->uc_mcontext.fpregs.f_fpregs, 96))
300 goto out;
301 return 0;
304 if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate))
305 goto out;
306 if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
307 if (!CPU_IS_060)
308 context_size = fpstate[1];
309 /* Verify the frame format. */
310 if (!CPU_IS_060 && (fpstate[0] != fpu_version))
311 goto out;
312 if (CPU_IS_020_OR_030) {
313 if (m68k_fputype & FPU_68881 &&
314 !(context_size == 0x18 || context_size == 0xb4))
315 goto out;
316 if (m68k_fputype & FPU_68882 &&
317 !(context_size == 0x38 || context_size == 0xd4))
318 goto out;
319 } else if (CPU_IS_040) {
320 if (!(context_size == 0x00 ||
321 context_size == 0x28 ||
322 context_size == 0x60))
323 goto out;
324 } else if (CPU_IS_060) {
325 if (!(fpstate[3] == 0x00 ||
326 fpstate[3] == 0x60 ||
327 fpstate[3] == 0xe0))
328 goto out;
329 } else
330 goto out;
331 if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
332 sizeof(fpregs)))
333 goto out;
334 __asm__ volatile (".chip 68k/68881\n\t"
335 "fmovemx %0,%/fp0-%/fp7\n\t"
336 "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
337 ".chip 68k"
338 : /* no outputs */
339 : "m" (*fpregs.f_fpregs),
340 "m" (fpregs.f_pcr));
342 if (context_size &&
343 __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1,
344 context_size))
345 goto out;
346 __asm__ volatile (".chip 68k/68881\n\t"
347 "frestore %0\n\t"
348 ".chip 68k" : : "m" (*fpstate));
349 err = 0;
351 out:
352 return err;
355 static inline int
356 restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
357 int *pd0)
359 int fsize, formatvec;
360 struct sigcontext context;
361 int err;
363 /* get previous context */
364 if (copy_from_user(&context, usc, sizeof(context)))
365 goto badframe;
367 /* restore passed registers */
368 regs->d1 = context.sc_d1;
369 regs->a0 = context.sc_a0;
370 regs->a1 = context.sc_a1;
371 regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
372 regs->pc = context.sc_pc;
373 regs->orig_d0 = -1; /* disable syscall checks */
374 wrusp(context.sc_usp);
375 formatvec = context.sc_formatvec;
376 regs->format = formatvec >> 12;
377 regs->vector = formatvec & 0xfff;
379 err = restore_fpu_state(&context);
381 fsize = frame_extra_sizes[regs->format];
382 if (fsize < 0) {
384 * user process trying to return with weird frame format
386 #if DEBUG
387 printk("user process returning with weird frame format\n");
388 #endif
389 goto badframe;
392 /* OK. Make room on the supervisor stack for the extra junk,
393 * if necessary.
396 if (fsize) {
397 struct switch_stack *sw = (struct switch_stack *)regs - 1;
398 regs->d0 = context.sc_d0;
399 #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
400 __asm__ __volatile__
401 (" movel %0,%/a0\n\t"
402 " subl %1,%/a0\n\t" /* make room on stack */
403 " movel %/a0,%/sp\n\t" /* set stack pointer */
404 /* move switch_stack and pt_regs */
405 "1: movel %0@+,%/a0@+\n\t"
406 " dbra %2,1b\n\t"
407 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
408 " lsrl #2,%1\n\t"
409 " subql #1,%1\n\t"
410 "2: movesl %4@+,%2\n\t"
411 "3: movel %2,%/a0@+\n\t"
412 " dbra %1,2b\n\t"
413 " bral " SYMBOL_NAME_STR(ret_from_signal) "\n"
414 "4:\n"
415 ".section __ex_table,\"a\"\n"
416 " .align 4\n"
417 " .long 2b,4b\n"
418 " .long 3b,4b\n"
419 ".previous"
420 : /* no outputs, it doesn't ever return */
421 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
422 "n" (frame_offset), "a" (fp)
423 : "a0");
424 #undef frame_offset
426 * If we ever get here an exception occurred while
427 * building the above stack-frame.
429 goto badframe;
432 *pd0 = context.sc_d0;
433 return err;
435 badframe:
436 return 1;
439 static inline int
440 rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
441 struct ucontext *uc, int *pd0)
443 int fsize, temp;
444 greg_t *gregs = uc->uc_mcontext.gregs;
445 unsigned long usp;
446 int err;
448 err = __get_user(temp, &uc->uc_mcontext.version);
449 if (temp != MCONTEXT_VERSION)
450 goto badframe;
451 /* restore passed registers */
452 err |= __get_user(regs->d0, &gregs[0]);
453 err |= __get_user(regs->d1, &gregs[1]);
454 err |= __get_user(regs->d2, &gregs[2]);
455 err |= __get_user(regs->d3, &gregs[3]);
456 err |= __get_user(regs->d4, &gregs[4]);
457 err |= __get_user(regs->d5, &gregs[5]);
458 err |= __get_user(sw->d6, &gregs[6]);
459 err |= __get_user(sw->d7, &gregs[7]);
460 err |= __get_user(regs->a0, &gregs[8]);
461 err |= __get_user(regs->a1, &gregs[9]);
462 err |= __get_user(regs->a2, &gregs[10]);
463 err |= __get_user(sw->a3, &gregs[11]);
464 err |= __get_user(sw->a4, &gregs[12]);
465 err |= __get_user(sw->a5, &gregs[13]);
466 err |= __get_user(sw->a6, &gregs[14]);
467 err |= __get_user(usp, &gregs[15]);
468 wrusp(usp);
469 err |= __get_user(regs->pc, &gregs[16]);
470 err |= __get_user(temp, &gregs[17]);
471 regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
472 regs->orig_d0 = -1; /* disable syscall checks */
473 err |= __get_user(temp, &uc->uc_formatvec);
474 regs->format = temp >> 12;
475 regs->vector = temp & 0xfff;
477 err |= rt_restore_fpu_state(uc);
479 if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
480 goto badframe;
482 fsize = frame_extra_sizes[regs->format];
483 if (fsize < 0) {
485 * user process trying to return with weird frame format
487 #if DEBUG
488 printk("user process returning with weird frame format\n");
489 #endif
490 goto badframe;
493 /* OK. Make room on the supervisor stack for the extra junk,
494 * if necessary.
497 if (fsize) {
498 #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
499 __asm__ __volatile__
500 (" movel %0,%/a0\n\t"
501 " subl %1,%/a0\n\t" /* make room on stack */
502 " movel %/a0,%/sp\n\t" /* set stack pointer */
503 /* move switch_stack and pt_regs */
504 "1: movel %0@+,%/a0@+\n\t"
505 " dbra %2,1b\n\t"
506 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
507 " lsrl #2,%1\n\t"
508 " subql #1,%1\n\t"
509 "2: movesl %4@+,%2\n\t"
510 "3: movel %2,%/a0@+\n\t"
511 " dbra %1,2b\n\t"
512 " bral " SYMBOL_NAME_STR(ret_from_signal) "\n"
513 "4:\n"
514 ".section __ex_table,\"a\"\n"
515 " .align 4\n"
516 " .long 2b,4b\n"
517 " .long 3b,4b\n"
518 ".previous"
519 : /* no outputs, it doesn't ever return */
520 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
521 "n" (frame_offset), "a" (&uc->uc_extra)
522 : "a0");
523 #undef frame_offset
525 * If we ever get here an exception occurred while
526 * building the above stack-frame.
528 goto badframe;
531 *pd0 = regs->d0;
532 return err;
534 badframe:
535 return 1;
538 asmlinkage int do_sigreturn(unsigned long __unused)
540 struct switch_stack *sw = (struct switch_stack *) &__unused;
541 struct pt_regs *regs = (struct pt_regs *) (sw + 1);
542 unsigned long usp = rdusp();
543 struct sigframe *frame = (struct sigframe *)(usp - 4);
544 sigset_t set;
545 int d0;
547 if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
548 goto badframe;
549 if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
550 (_NSIG_WORDS > 1 &&
551 __copy_from_user(&set.sig[1], &frame->extramask,
552 sizeof(frame->extramask))))
553 goto badframe;
555 sigdelsetmask(&set, ~_BLOCKABLE);
556 current->blocked = set;
557 recalc_sigpending(current);
559 if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0))
560 goto badframe;
561 return d0;
563 badframe:
564 force_sig(SIGSEGV, current);
565 return 0;
568 asmlinkage int do_rt_sigreturn(unsigned long __unused)
570 struct switch_stack *sw = (struct switch_stack *) &__unused;
571 struct pt_regs *regs = (struct pt_regs *) (sw + 1);
572 unsigned long usp = rdusp();
573 struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4);
574 sigset_t set;
575 int d0;
577 if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
578 goto badframe;
579 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
580 goto badframe;
582 sigdelsetmask(&set, ~_BLOCKABLE);
583 current->blocked = set;
584 recalc_sigpending(current);
586 if (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
587 goto badframe;
588 return d0;
590 badframe:
591 force_sig(SIGSEGV, current);
592 return 0;
596 * Set up a signal frame.
599 static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
601 if (FPU_IS_EMU) {
602 /* save registers */
603 memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
604 memcpy(sc->sc_fpregs, current->thread.fp, 24);
605 return;
608 __asm__ volatile (".chip 68k/68881\n\t"
609 "fsave %0\n\t"
610 ".chip 68k"
611 : : "m" (*sc->sc_fpstate) : "memory");
613 if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
614 fpu_version = sc->sc_fpstate[0];
615 if (CPU_IS_020_OR_030 &&
616 regs->vector >= (VEC_FPBRUC * 4) &&
617 regs->vector <= (VEC_FPNAN * 4)) {
618 /* Clear pending exception in 68882 idle frame */
619 if (*(unsigned short *) sc->sc_fpstate == 0x1f38)
620 sc->sc_fpstate[0x38] |= 1 << 3;
622 __asm__ volatile (".chip 68k/68881\n\t"
623 "fmovemx %/fp0-%/fp1,%0\n\t"
624 "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
625 ".chip 68k"
626 : /* no outputs */
627 : "m" (*sc->sc_fpregs),
628 "m" (*sc->sc_fpcntl)
629 : "memory");
633 static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs)
635 unsigned char fpstate[FPCONTEXT_SIZE];
636 int context_size = CPU_IS_060 ? 8 : 0;
637 int err = 0;
639 if (FPU_IS_EMU) {
640 /* save fpu control register */
641 err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr,
642 current->thread.fpcntl, 12);
643 /* save all other fpu register */
644 err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
645 current->thread.fp, 96);
646 return err;
649 __asm__ volatile (".chip 68k/68881\n\t"
650 "fsave %0\n\t"
651 ".chip 68k"
652 : : "m" (*fpstate) : "memory");
654 err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate);
655 if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
656 fpregset_t fpregs;
657 if (!CPU_IS_060)
658 context_size = fpstate[1];
659 fpu_version = fpstate[0];
660 if (CPU_IS_020_OR_030 &&
661 regs->vector >= (VEC_FPBRUC * 4) &&
662 regs->vector <= (VEC_FPNAN * 4)) {
663 /* Clear pending exception in 68882 idle frame */
664 if (*(unsigned short *) fpstate == 0x1f38)
665 fpstate[0x38] |= 1 << 3;
667 __asm__ volatile (".chip 68k/68881\n\t"
668 "fmovemx %/fp0-%/fp7,%0\n\t"
669 "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
670 ".chip 68k"
671 : /* no outputs */
672 : "m" (*fpregs.f_fpregs),
673 "m" (fpregs.f_pcr)
674 : "memory");
675 err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
676 sizeof(fpregs));
678 if (context_size)
679 err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4,
680 context_size);
681 return err;
684 static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
685 unsigned long mask)
687 sc->sc_mask = mask;
688 sc->sc_usp = rdusp();
689 sc->sc_d0 = regs->d0;
690 sc->sc_d1 = regs->d1;
691 sc->sc_a0 = regs->a0;
692 sc->sc_a1 = regs->a1;
693 sc->sc_sr = regs->sr;
694 sc->sc_pc = regs->pc;
695 sc->sc_formatvec = regs->format << 12 | regs->vector;
696 save_fpu_state(sc, regs);
699 static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
701 struct switch_stack *sw = (struct switch_stack *)regs - 1;
702 greg_t *gregs = uc->uc_mcontext.gregs;
703 int err = 0;
705 err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
706 err |= __put_user(regs->d0, &gregs[0]);
707 err |= __put_user(regs->d1, &gregs[1]);
708 err |= __put_user(regs->d2, &gregs[2]);
709 err |= __put_user(regs->d3, &gregs[3]);
710 err |= __put_user(regs->d4, &gregs[4]);
711 err |= __put_user(regs->d5, &gregs[5]);
712 err |= __put_user(sw->d6, &gregs[6]);
713 err |= __put_user(sw->d7, &gregs[7]);
714 err |= __put_user(regs->a0, &gregs[8]);
715 err |= __put_user(regs->a1, &gregs[9]);
716 err |= __put_user(regs->a2, &gregs[10]);
717 err |= __put_user(sw->a3, &gregs[11]);
718 err |= __put_user(sw->a4, &gregs[12]);
719 err |= __put_user(sw->a5, &gregs[13]);
720 err |= __put_user(sw->a6, &gregs[14]);
721 err |= __put_user(rdusp(), &gregs[15]);
722 err |= __put_user(regs->pc, &gregs[16]);
723 err |= __put_user(regs->sr, &gregs[17]);
724 err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);
725 err |= rt_save_fpu_state(uc, regs);
726 return err;
729 static inline void push_cache (unsigned long vaddr)
732 * Using the old cache_push_v() was really a big waste.
734 * What we are trying to do is to flush 8 bytes to ram.
735 * Flushing 2 cache lines of 16 bytes is much cheaper than
736 * flushing 1 or 2 pages, as previously done in
737 * cache_push_v().
738 * Jes
740 if (CPU_IS_040) {
741 unsigned long temp;
743 __asm__ __volatile__ (".chip 68040\n\t"
744 "nop\n\t"
745 "ptestr (%1)\n\t"
746 "movec %%mmusr,%0\n\t"
747 ".chip 68k"
748 : "=r" (temp)
749 : "a" (vaddr));
751 temp &= PAGE_MASK;
752 temp |= vaddr & ~PAGE_MASK;
754 __asm__ __volatile__ (".chip 68040\n\t"
755 "nop\n\t"
756 "cpushl %%bc,(%0)\n\t"
757 ".chip 68k"
758 : : "a" (temp));
760 else if (CPU_IS_060) {
761 unsigned long temp;
762 __asm__ __volatile__ (".chip 68060\n\t"
763 "plpar (%0)\n\t"
764 ".chip 68k"
765 : "=a" (temp)
766 : "0" (vaddr));
767 __asm__ __volatile__ (".chip 68060\n\t"
768 "cpushl %%bc,(%0)\n\t"
769 ".chip 68k"
770 : : "a" (temp));
772 else {
774 * 68030/68020 have no writeback cache;
775 * still need to clear icache.
776 * Note that vaddr is guaranteed to be long word aligned.
778 unsigned long temp;
779 asm volatile ("movec %%cacr,%0" : "=r" (temp));
780 temp += 4;
781 asm volatile ("movec %0,%%caar\n\t"
782 "movec %1,%%cacr"
783 : : "r" (vaddr), "r" (temp));
784 asm volatile ("movec %0,%%caar\n\t"
785 "movec %1,%%cacr"
786 : : "r" (vaddr + 4), "r" (temp));
790 static inline void *
791 get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
793 unsigned long usp;
795 /* Default to using normal stack. */
796 usp = rdusp();
798 /* This is the X/Open sanctioned signal stack switching. */
799 if (ka->sa.sa_flags & SA_ONSTACK) {
800 if (!on_sig_stack(usp))
801 usp = current->sas_ss_sp + current->sas_ss_size;
803 return (void *)((usp - frame_size) & -8UL);
806 static void setup_frame (int sig, struct k_sigaction *ka,
807 sigset_t *set, struct pt_regs *regs)
809 struct sigframe *frame;
810 int fsize = frame_extra_sizes[regs->format];
811 struct sigcontext context;
812 int err = 0;
814 if (fsize < 0) {
815 #ifdef DEBUG
816 printk ("setup_frame: Unknown frame format %#x\n",
817 regs->format);
818 #endif
819 goto give_sigsegv;
822 frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
824 if (fsize) {
825 err |= copy_to_user (frame + 1, regs + 1, fsize);
826 regs->stkadj = fsize;
829 err |= __put_user((current->exec_domain
830 && current->exec_domain->signal_invmap
831 && sig < 32
832 ? current->exec_domain->signal_invmap[sig]
833 : sig),
834 &frame->sig);
836 err |= __put_user(regs->vector, &frame->code);
837 err |= __put_user(&frame->sc, &frame->psc);
839 if (_NSIG_WORDS > 1)
840 err |= copy_to_user(frame->extramask, &set->sig[1],
841 sizeof(frame->extramask));
843 setup_sigcontext(&context, regs, set->sig[0]);
844 err |= copy_to_user (&frame->sc, &context, sizeof(context));
846 /* Set up to return from userspace. */
847 err |= __put_user(frame->retcode, &frame->pretcode);
848 /* moveq #,d0; trap #0 */
849 err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
850 (long *)(frame->retcode));
852 if (err)
853 goto give_sigsegv;
855 push_cache ((unsigned long) &frame->retcode);
857 /* Set up registers for signal handler */
858 wrusp ((unsigned long) frame);
859 regs->pc = (unsigned long) ka->sa.sa_handler;
861 adjust_stack:
862 /* Prepare to skip over the extra stuff in the exception frame. */
863 if (regs->stkadj) {
864 struct pt_regs *tregs =
865 (struct pt_regs *)((ulong)regs + regs->stkadj);
866 #if DEBUG
867 printk("Performing stackadjust=%04x\n", regs->stkadj);
868 #endif
869 /* This must be copied with decreasing addresses to
870 handle overlaps. */
871 tregs->vector = 0;
872 tregs->format = 0;
873 tregs->pc = regs->pc;
874 tregs->sr = regs->sr;
876 return;
878 give_sigsegv:
879 if (sig == SIGSEGV)
880 ka->sa.sa_handler = SIG_DFL;
881 force_sig(SIGSEGV, current);
882 goto adjust_stack;
885 static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
886 sigset_t *set, struct pt_regs *regs)
888 struct rt_sigframe *frame;
889 int fsize = frame_extra_sizes[regs->format];
890 int err = 0;
892 if (fsize < 0) {
893 #ifdef DEBUG
894 printk ("setup_frame: Unknown frame format %#x\n",
895 regs->format);
896 #endif
897 goto give_sigsegv;
900 frame = get_sigframe(ka, regs, sizeof(*frame));
902 if (fsize) {
903 err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
904 regs->stkadj = fsize;
907 err |= __put_user((current->exec_domain
908 && current->exec_domain->signal_invmap
909 && sig < 32
910 ? current->exec_domain->signal_invmap[sig]
911 : sig),
912 &frame->sig);
913 err |= __put_user(&frame->info, &frame->pinfo);
914 err |= __put_user(&frame->uc, &frame->puc);
915 err |= copy_siginfo_to_user(&frame->info, info);
917 /* Create the ucontext. */
918 err |= __put_user(0, &frame->uc.uc_flags);
919 err |= __put_user(0, &frame->uc.uc_link);
920 err |= __put_user((void *)current->sas_ss_sp,
921 &frame->uc.uc_stack.ss_sp);
922 err |= __put_user(sas_ss_flags(rdusp()),
923 &frame->uc.uc_stack.ss_flags);
924 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
925 err |= rt_setup_ucontext(&frame->uc, regs);
926 err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
928 /* Set up to return from userspace. */
929 err |= __put_user(frame->retcode, &frame->pretcode);
930 /* moveq #,d0; notb d0; trap #0 */
931 err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
932 (long *)(frame->retcode + 0));
933 err |= __put_user(0x4e40, (short *)(frame->retcode + 4));
935 if (err)
936 goto give_sigsegv;
938 push_cache ((unsigned long) &frame->retcode);
940 /* Set up registers for signal handler */
941 wrusp ((unsigned long) frame);
942 regs->pc = (unsigned long) ka->sa.sa_handler;
944 adjust_stack:
945 /* Prepare to skip over the extra stuff in the exception frame. */
946 if (regs->stkadj) {
947 struct pt_regs *tregs =
948 (struct pt_regs *)((ulong)regs + regs->stkadj);
949 #if DEBUG
950 printk("Performing stackadjust=%04x\n", regs->stkadj);
951 #endif
952 /* This must be copied with decreasing addresses to
953 handle overlaps. */
954 tregs->vector = 0;
955 tregs->format = 0;
956 tregs->pc = regs->pc;
957 tregs->sr = regs->sr;
959 return;
961 give_sigsegv:
962 if (sig == SIGSEGV)
963 ka->sa.sa_handler = SIG_DFL;
964 force_sig(SIGSEGV, current);
965 goto adjust_stack;
968 static inline void
969 handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
971 switch (regs->d0) {
972 case -ERESTARTNOHAND:
973 if (!has_handler)
974 goto do_restart;
975 regs->d0 = -EINTR;
976 break;
978 case -ERESTARTSYS:
979 if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
980 regs->d0 = -EINTR;
981 break;
983 /* fallthrough */
984 case -ERESTARTNOINTR:
985 do_restart:
986 regs->d0 = regs->orig_d0;
987 regs->pc -= 2;
988 break;
993 * OK, we're invoking a handler
995 static void
996 handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
997 sigset_t *oldset, struct pt_regs *regs)
999 /* are we from a system call? */
1000 if (regs->orig_d0 >= 0)
1001 /* If so, check system call restarting.. */
1002 handle_restart(regs, ka, 1);
1004 /* set up the stack frame */
1005 if (ka->sa.sa_flags & SA_SIGINFO)
1006 setup_rt_frame(sig, ka, info, oldset, regs);
1007 else
1008 setup_frame(sig, ka, oldset, regs);
1010 if (ka->sa.sa_flags & SA_ONESHOT)
1011 ka->sa.sa_handler = SIG_DFL;
1013 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
1014 if (!(ka->sa.sa_flags & SA_NODEFER))
1015 sigaddset(&current->blocked,sig);
1016 recalc_sigpending(current);
1020 * Note that 'init' is a special process: it doesn't get signals it doesn't
1021 * want to handle. Thus you cannot kill init even with a SIGKILL even by
1022 * mistake.
1024 * Note that we go through the signals twice: once to check the signals
1025 * that the kernel can handle, and then we build all the user-level signal
1026 * handling stack-frames in one go after that.
1028 asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
1030 siginfo_t info;
1031 struct k_sigaction *ka;
1033 current->thread.esp0 = (unsigned long) regs;
1035 if (!oldset)
1036 oldset = &current->blocked;
1038 for (;;) {
1039 int signr;
1041 signr = dequeue_signal(&current->blocked, &info);
1043 if (!signr)
1044 break;
1046 if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
1047 current->exit_code = signr;
1048 current->state = TASK_STOPPED;
1049 regs->sr &= ~PS_T;
1051 /* Did we come from a system call? */
1052 if (regs->orig_d0 >= 0) {
1053 /* Restart the system call the same way as
1054 if the process were not traced. */
1055 struct k_sigaction *ka =
1056 &current->sig->action[signr-1];
1057 int has_handler =
1058 (ka->sa.sa_handler != SIG_IGN &&
1059 ka->sa.sa_handler != SIG_DFL);
1060 handle_restart(regs, ka, has_handler);
1062 notify_parent(current, SIGCHLD);
1063 schedule();
1065 /* We're back. Did the debugger cancel the sig? */
1066 if (!(signr = current->exit_code)) {
1067 discard_frame:
1068 /* Make sure that a faulted bus cycle isn't
1069 restarted (only needed on the 680[23]0). */
1070 if (regs->format == 10 || regs->format == 11)
1071 regs->stkadj = frame_extra_sizes[regs->format];
1072 continue;
1074 current->exit_code = 0;
1076 /* The debugger continued. Ignore SIGSTOP. */
1077 if (signr == SIGSTOP)
1078 goto discard_frame;
1080 /* Update the siginfo structure. Is this good? */
1081 if (signr != info.si_signo) {
1082 info.si_signo = signr;
1083 info.si_errno = 0;
1084 info.si_code = SI_USER;
1085 info.si_pid = current->p_pptr->pid;
1086 info.si_uid = current->p_pptr->uid;
1087 info.si_uid16 = high2lowuid(current->p_pptr->uid);
1090 /* If the (new) signal is now blocked, requeue it. */
1091 if (sigismember(&current->blocked, signr)) {
1092 send_sig_info(signr, &info, current);
1093 continue;
1097 ka = &current->sig->action[signr-1];
1098 if (ka->sa.sa_handler == SIG_IGN) {
1099 if (signr != SIGCHLD)
1100 continue;
1101 /* Check for SIGCHLD: it's special. */
1102 while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
1103 /* nothing */;
1104 continue;
1107 if (ka->sa.sa_handler == SIG_DFL) {
1108 int exit_code = signr;
1110 if (current->pid == 1)
1111 continue;
1113 switch (signr) {
1114 case SIGCONT: case SIGCHLD:
1115 case SIGWINCH: case SIGURG:
1116 continue;
1118 case SIGTSTP: case SIGTTIN: case SIGTTOU:
1119 if (is_orphaned_pgrp(current->pgrp))
1120 continue;
1121 /* FALLTHRU */
1123 case SIGSTOP:
1124 current->state = TASK_STOPPED;
1125 current->exit_code = signr;
1126 if (!(current->p_pptr->sig->action[SIGCHLD-1]
1127 .sa.sa_flags & SA_NOCLDSTOP))
1128 notify_parent(current, SIGCHLD);
1129 schedule();
1130 continue;
1132 case SIGQUIT: case SIGILL: case SIGTRAP:
1133 case SIGIOT: case SIGFPE: case SIGSEGV:
1134 case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
1135 if (do_coredump(signr, regs))
1136 exit_code |= 0x80;
1137 /* FALLTHRU */
1139 default:
1140 sigaddset(&current->pending.signal, signr);
1141 recalc_sigpending(current);
1142 current->flags |= PF_SIGNALED;
1143 do_exit(exit_code);
1144 /* NOTREACHED */
1148 /* Whee! Actually deliver the signal. */
1149 handle_signal(signr, ka, &info, oldset, regs);
1150 return 1;
1153 /* Did we come from a system call? */
1154 if (regs->orig_d0 >= 0)
1155 /* Restart the system call - no handlers present */
1156 handle_restart(regs, NULL, 0);
1158 /* If we are about to discard some frame stuff we must copy
1159 over the remaining frame. */
1160 if (regs->stkadj) {
1161 struct pt_regs *tregs =
1162 (struct pt_regs *) ((ulong) regs + regs->stkadj);
1164 /* This must be copied with decreasing addresses to
1165 handle overlaps. */
1166 tregs->vector = 0;
1167 tregs->format = 0;
1168 tregs->pc = regs->pc;
1169 tregs->sr = regs->sr;
1171 return 0;