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