Import 2.3.13
[davej-history.git] / arch / m68k / kernel / signal.c
blobd6302cb28c73c08e6a3461354542cd15e61b3700
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
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
24 * signal handlers!
27 #include <linux/sched.h>
28 #include <linux/mm.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;
74 sigset_t saveset;
76 mask &= _BLOCKABLE;
77 saveset = current->blocked;
78 siginitset(&current->blocked, mask);
79 recalc_sigpending(current);
81 regs->d0 = -EINTR;
82 while (1) {
83 current->state = TASK_INTERRUPTIBLE;
84 schedule();
85 if (do_signal(&saveset, regs))
86 return -EINTR;
90 asmlinkage int
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))
99 return -EINVAL;
101 if (copy_from_user(&newset, unewset, sizeof(newset)))
102 return -EFAULT;
103 sigdelsetmask(&newset, ~_BLOCKABLE);
105 saveset = current->blocked;
106 current->blocked = newset;
107 recalc_sigpending(current);
109 regs->d0 = -EINTR;
110 while (1) {
111 current->state = TASK_INTERRUPTIBLE;
112 schedule();
113 if (do_signal(&saveset, regs))
114 return -EINTR;
118 asmlinkage int
119 sys_sigaction(int sig, const struct old_sigaction *act,
120 struct old_sigaction *oact)
122 struct k_sigaction new_ka, old_ka;
123 int ret;
125 if (act) {
126 old_sigset_t mask;
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))
130 return -EFAULT;
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);
138 if (!ret && oact) {
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))
142 return -EFAULT;
143 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
144 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
147 return ret;
150 asmlinkage int
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.
164 struct sigframe
166 char *pretcode;
167 int sig;
168 int code;
169 struct sigcontext *psc;
170 char retcode[8];
171 unsigned long extramask[_NSIG_WORDS-1];
172 struct sigcontext sc;
175 struct rt_sigframe
177 char *pretcode;
178 int sig;
179 struct siginfo *pinfo;
180 void *puc;
181 char retcode[8];
182 struct siginfo info;
183 struct ucontext uc;
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)
191 int err = 1;
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))
196 goto out;
197 if (CPU_IS_020_OR_030) {
198 if (m68k_fputype & FPU_68881 &&
199 !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4))
200 goto out;
201 if (m68k_fputype & FPU_68882 &&
202 !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4))
203 goto out;
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))
208 goto out;
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))
213 goto out;
214 } else
215 goto out;
217 __asm__ volatile (".chip 68k/68881\n\t"
218 "fmovemx %0,%/fp0-%/fp1\n\t"
219 "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
220 ".chip 68k"
221 : /* no outputs */
222 : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
224 __asm__ volatile (".chip 68k/68881\n\t"
225 "frestore %0\n\t"
226 ".chip 68k" : : "m" (*sc->sc_fpstate));
227 err = 0;
229 out:
230 return err;
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;
242 fpregset_t fpregs;
243 int err = 1;
245 if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate))
246 goto out;
247 if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
248 if (!CPU_IS_060)
249 context_size = fpstate[1];
250 /* Verify the frame format. */
251 if (!CPU_IS_060 && (fpstate[0] != fpu_version))
252 goto out;
253 if (CPU_IS_020_OR_030) {
254 if (m68k_fputype & FPU_68881 &&
255 !(context_size == 0x18 || context_size == 0xb4))
256 goto out;
257 if (m68k_fputype & FPU_68882 &&
258 !(context_size == 0x38 || context_size == 0xd4))
259 goto out;
260 } else if (CPU_IS_040) {
261 if (!(context_size == 0x00 ||
262 context_size == 0x28 ||
263 context_size == 0x60))
264 goto out;
265 } else if (CPU_IS_060) {
266 if (!(fpstate[3] == 0x00 ||
267 fpstate[3] == 0x60 ||
268 fpstate[3] == 0xe0))
269 goto out;
270 } else
271 goto out;
272 if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
273 sizeof(fpregs)))
274 goto out;
275 __asm__ volatile (".chip 68k/68881\n\t"
276 "fmovemx %0,%/fp0-%/fp7\n\t"
277 "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t"
278 ".chip 68k"
279 : /* no outputs */
280 : "m" (*fpregs.f_fpregs),
281 "m" (fpregs.f_pcr));
283 if (context_size &&
284 __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1,
285 context_size))
286 goto out;
287 __asm__ volatile (".chip 68k/68881\n\t"
288 "frestore %0\n\t"
289 ".chip 68k" : : "m" (*fpstate));
290 err = 0;
292 out:
293 return err;
296 static inline int
297 restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp,
298 int *pd0)
300 int fsize, formatvec;
301 struct sigcontext context;
302 int err;
304 /* get previous context */
305 if (copy_from_user(&context, usc, sizeof(context)))
306 goto badframe;
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];
323 if (fsize < 0) {
325 * user process trying to return with weird frame format
327 #if DEBUG
328 printk("user process returning with weird frame format\n");
329 #endif
330 goto badframe;
333 /* OK. Make room on the supervisor stack for the extra junk,
334 * if necessary.
337 if (fsize) {
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))
341 __asm__ __volatile__
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"
347 " dbra %2,1b\n\t"
348 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
349 " lsrl #2,%1\n\t"
350 " subql #1,%1\n\t"
351 "2: movesl %4@+,%2\n\t"
352 "3: movel %2,%/a0@+\n\t"
353 " dbra %1,2b\n\t"
354 " bral " SYMBOL_NAME_STR(ret_from_signal) "\n"
355 "4:\n"
356 ".section __ex_table,\"a\"\n"
357 " .align 4\n"
358 " .long 2b,4b\n"
359 " .long 3b,4b\n"
360 ".previous"
361 : /* no outputs, it doesn't ever return */
362 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
363 "n" (frame_offset), "a" (fp)
364 : "a0");
365 #undef frame_offset
367 * If we ever get here an exception occurred while
368 * building the above stack-frame.
370 goto badframe;
373 *pd0 = context.sc_d0;
374 return err;
376 badframe:
377 return 1;
380 static inline int
381 rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
382 struct ucontext *uc, int *pd0)
384 int fsize, temp;
385 greg_t *gregs = uc->uc_mcontext.gregs;
386 unsigned long usp;
387 int err;
389 err = __get_user(temp, &uc->uc_mcontext.version);
390 if (temp != MCONTEXT_VERSION)
391 goto badframe;
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]);
409 wrusp(usp);
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)
421 goto badframe;
423 fsize = frame_extra_sizes[regs->format];
424 if (fsize < 0) {
426 * user process trying to return with weird frame format
428 #if DEBUG
429 printk("user process returning with weird frame format\n");
430 #endif
431 goto badframe;
434 /* OK. Make room on the supervisor stack for the extra junk,
435 * if necessary.
438 if (fsize) {
439 #define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
440 __asm__ __volatile__
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"
446 " dbra %2,1b\n\t"
447 " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
448 " lsrl #2,%1\n\t"
449 " subql #1,%1\n\t"
450 "2: movesl %4@+,%2\n\t"
451 "3: movel %2,%/a0@+\n\t"
452 " dbra %1,2b\n\t"
453 " bral " SYMBOL_NAME_STR(ret_from_signal) "\n"
454 "4:\n"
455 ".section __ex_table,\"a\"\n"
456 " .align 4\n"
457 " .long 2b,4b\n"
458 " .long 3b,4b\n"
459 ".previous"
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)
463 : "a0");
464 #undef frame_offset
466 * If we ever get here an exception occurred while
467 * building the above stack-frame.
469 goto badframe;
472 *pd0 = regs->d0;
473 return err;
475 badframe:
476 return 1;
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);
485 sigset_t set;
486 int d0;
488 if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
489 goto badframe;
490 if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
491 (_NSIG_WORDS > 1 &&
492 __copy_from_user(&set.sig[1], &frame->extramask,
493 sizeof(frame->extramask))))
494 goto badframe;
496 sigdelsetmask(&set, ~_BLOCKABLE);
497 current->blocked = set;
498 recalc_sigpending(current);
500 if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0))
501 goto badframe;
502 return d0;
504 badframe:
505 force_sig(SIGSEGV, current);
506 return 0;
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);
515 sigset_t set;
516 int d0;
518 if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
519 goto badframe;
520 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
521 goto badframe;
523 sigdelsetmask(&set, ~_BLOCKABLE);
524 current->blocked = set;
525 recalc_sigpending(current);
527 if (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
528 goto badframe;
529 return d0;
531 badframe:
532 force_sig(SIGSEGV, current);
533 return 0;
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"
543 "fsave %0\n\t"
544 ".chip 68k"
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"
559 ".chip 68k"
560 : /* no outputs */
561 : "m" (*sc->sc_fpregs),
562 "m" (*sc->sc_fpcntl)
563 : "memory");
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;
571 int err = 0;
573 __asm__ volatile (".chip 68k/68881\n\t"
574 "fsave %0\n\t"
575 ".chip 68k"
576 : : "m" (*fpstate) : "memory");
578 err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate);
579 if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
580 fpregset_t fpregs;
581 if (!CPU_IS_060)
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"
594 ".chip 68k"
595 : /* no outputs */
596 : "m" (*fpregs.f_fpregs),
597 "m" (fpregs.f_pcr)
598 : "memory");
599 err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
600 sizeof(fpregs));
602 if (context_size)
603 err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4,
604 context_size);
605 return err;
608 static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
609 unsigned long mask)
611 sc->sc_mask = mask;
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;
627 int err = 0;
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);
650 return err;
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
661 * cache_push_v().
662 * Jes
664 if (CPU_IS_040) {
665 unsigned long temp;
667 __asm__ __volatile__ (".chip 68040\n\t"
668 "nop\n\t"
669 "ptestr (%1)\n\t"
670 "movec %%mmusr,%0\n\t"
671 ".chip 68k"
672 : "=r" (temp)
673 : "a" (vaddr));
675 temp &= PAGE_MASK;
676 temp |= vaddr & ~PAGE_MASK;
678 __asm__ __volatile__ (".chip 68040\n\t"
679 "nop\n\t"
680 "cpushl %%bc,(%0)\n\t"
681 ".chip 68k"
682 : : "a" (temp));
684 else if (CPU_IS_060) {
685 unsigned long temp;
686 __asm__ __volatile__ (".chip 68060\n\t"
687 "plpar (%0)\n\t"
688 ".chip 68k"
689 : "=a" (temp)
690 : "0" (vaddr));
691 __asm__ __volatile__ (".chip 68060\n\t"
692 "cpushl %%bc,(%0)\n\t"
693 ".chip 68k"
694 : : "a" (temp));
696 else {
698 * 68030/68020 have no writeback cache;
699 * still need to clear icache.
700 * Note that vaddr is guaranteed to be long word aligned.
702 unsigned long temp;
703 asm volatile ("movec %%cacr,%0" : "=r" (temp));
704 temp += 4;
705 asm volatile ("movec %0,%%caar\n\t"
706 "movec %1,%%cacr"
707 : : "r" (vaddr), "r" (temp));
708 asm volatile ("movec %0,%%caar\n\t"
709 "movec %1,%%cacr"
710 : : "r" (vaddr + 4), "r" (temp));
714 static inline void *
715 get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
717 unsigned long usp;
719 /* Default to using normal stack. */
720 usp = rdusp();
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;
736 int err = 0;
738 if (fsize < 0) {
739 #ifdef DEBUG
740 printk ("setup_frame: Unknown frame format %#x\n",
741 regs->format);
742 #endif
743 goto give_sigsegv;
746 frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
748 if (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
755 && sig < 32
756 ? current->exec_domain->signal_invmap[sig]
757 : sig),
758 &frame->sig);
760 err |= __put_user(regs->vector, &frame->code);
761 err |= __put_user(&frame->sc, &frame->psc);
763 if (_NSIG_WORDS > 1)
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));
776 if (err)
777 goto give_sigsegv;
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;
785 adjust_stack:
786 /* Prepare to skip over the extra stuff in the exception frame. */
787 if (regs->stkadj) {
788 struct pt_regs *tregs =
789 (struct pt_regs *)((ulong)regs + regs->stkadj);
790 #if DEBUG
791 printk("Performing stackadjust=%04x\n", regs->stkadj);
792 #endif
793 /* This must be copied with decreasing addresses to
794 handle overlaps. */
795 tregs->vector = 0;
796 tregs->format = 0;
797 tregs->pc = regs->pc;
798 tregs->sr = regs->sr;
800 return;
802 give_sigsegv:
803 if (sig == SIGSEGV)
804 ka->sa.sa_handler = SIG_DFL;
805 force_sig(SIGSEGV, current);
806 goto adjust_stack;
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];
814 int err = 0;
816 if (fsize < 0) {
817 #ifdef DEBUG
818 printk ("setup_frame: Unknown frame format %#x\n",
819 regs->format);
820 #endif
821 goto give_sigsegv;
824 frame = get_sigframe(ka, regs, sizeof(*frame));
826 if (fsize) {
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
833 && sig < 32
834 ? current->exec_domain->signal_invmap[sig]
835 : sig),
836 &frame->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));
859 if (err)
860 goto give_sigsegv;
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;
868 adjust_stack:
869 /* Prepare to skip over the extra stuff in the exception frame. */
870 if (regs->stkadj) {
871 struct pt_regs *tregs =
872 (struct pt_regs *)((ulong)regs + regs->stkadj);
873 #if DEBUG
874 printk("Performing stackadjust=%04x\n", regs->stkadj);
875 #endif
876 /* This must be copied with decreasing addresses to
877 handle overlaps. */
878 tregs->vector = 0;
879 tregs->format = 0;
880 tregs->pc = regs->pc;
881 tregs->sr = regs->sr;
883 return;
885 give_sigsegv:
886 if (sig == SIGSEGV)
887 ka->sa.sa_handler = SIG_DFL;
888 force_sig(SIGSEGV, current);
889 goto adjust_stack;
892 static inline void
893 handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
895 switch (regs->d0) {
896 case -ERESTARTNOHAND:
897 if (!has_handler)
898 goto do_restart;
899 regs->d0 = -EINTR;
900 break;
902 case -ERESTARTSYS:
903 if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
904 regs->d0 = -EINTR;
905 break;
907 /* fallthrough */
908 case -ERESTARTNOINTR:
909 do_restart:
910 regs->d0 = regs->orig_d0;
911 regs->pc -= 2;
912 break;
917 * OK, we're invoking a handler
919 static void
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);
931 else
932 setup_frame(sig, ka, oldset, regs);
934 if (ka->sa.sa_flags & SA_ONESHOT)
935 ka->sa.sa_handler = SIG_DFL;
937 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
938 if (!(ka->sa.sa_flags & SA_NODEFER))
939 sigaddset(&current->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
946 * mistake.
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)
954 siginfo_t info;
955 struct k_sigaction *ka;
957 current->thread.esp0 = (unsigned long) regs;
959 if (!oldset)
960 oldset = &current->blocked;
962 for (;;) {
963 int signr;
965 signr = dequeue_signal(&current->blocked, &info);
967 if (!signr)
968 break;
970 if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
971 current->exit_code = signr;
972 current->state = TASK_STOPPED;
973 regs->sr &= ~PS_T;
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 &current->sig->action[signr-1];
981 int has_handler =
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);
987 schedule();
989 /* We're back. Did the debugger cancel the sig? */
990 if (!(signr = current->exit_code)) {
991 discard_frame:
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];
996 continue;
998 current->exit_code = 0;
1000 /* The debugger continued. Ignore SIGSTOP. */
1001 if (signr == SIGSTOP)
1002 goto discard_frame;
1004 /* Update the siginfo structure. Is this good? */
1005 if (signr != info.si_signo) {
1006 info.si_signo = signr;
1007 info.si_errno = 0;
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(&current->blocked, signr)) {
1015 send_sig_info(signr, &info, current);
1016 continue;
1020 ka = &current->sig->action[signr-1];
1021 if (ka->sa.sa_handler == SIG_IGN) {
1022 if (signr != SIGCHLD)
1023 continue;
1024 /* Check for SIGCHLD: it's special. */
1025 while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
1026 /* nothing */;
1027 continue;
1030 if (ka->sa.sa_handler == SIG_DFL) {
1031 int exit_code = signr;
1033 if (current->pid == 1)
1034 continue;
1036 switch (signr) {
1037 case SIGCONT: case SIGCHLD: case SIGWINCH:
1038 continue;
1040 case SIGTSTP: case SIGTTIN: case SIGTTOU:
1041 if (is_orphaned_pgrp(current->pgrp))
1042 continue;
1043 /* FALLTHRU */
1045 case SIGSTOP:
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);
1051 schedule();
1052 continue;
1054 case SIGQUIT: case SIGILL: case SIGTRAP:
1055 case SIGIOT: case SIGFPE: case SIGSEGV:
1056 if (do_coredump(signr, regs))
1057 exit_code |= 0x80;
1058 /* FALLTHRU */
1060 default:
1061 sigaddset(&current->signal, signr);
1062 recalc_sigpending(current);
1063 current->flags |= PF_SIGNALED;
1064 do_exit(exit_code);
1065 /* NOTREACHED */
1069 /* Whee! Actually deliver the signal. */
1070 handle_signal(signr, ka, &info, oldset, regs);
1071 return 1;
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. */
1081 if (regs->stkadj) {
1082 struct pt_regs *tregs =
1083 (struct pt_regs *) ((ulong) regs + regs->stkadj);
1085 /* This must be copied with decreasing addresses to
1086 handle overlaps. */
1087 tregs->vector = 0;
1088 tregs->format = 0;
1089 tregs->pc = regs->pc;
1090 tregs->sr = regs->sr;
1092 return 0;