Import 2.3.12pre1
[davej-history.git] / arch / mips / kernel / signal.c
blobc58f1e7cae9f1d6967c75df196dcef898b57508e
1 /* $Id: signal.c,v 1.19 1999/06/17 13:25:47 ralf Exp $
3 * linux/arch/mips/kernel/signal.c
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
8 * XXX Handle lazy fp context switches correctly.
9 */
10 #include <linux/config.h>
11 #include <linux/sched.h>
12 #include <linux/mm.h>
13 #include <linux/smp.h>
14 #include <linux/smp_lock.h>
15 #include <linux/kernel.h>
16 #include <linux/signal.h>
17 #include <linux/errno.h>
18 #include <linux/wait.h>
19 #include <linux/ptrace.h>
20 #include <linux/unistd.h>
22 #include <asm/asm.h>
23 #include <asm/bitops.h>
24 #include <asm/pgtable.h>
25 #include <asm/stackframe.h>
26 #include <asm/uaccess.h>
28 #define DEBUG_SIG 0
30 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
32 asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
33 int options, unsigned long *ru);
34 asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
35 extern asmlinkage void (*save_fp_context)(struct sigcontext *sc);
36 extern asmlinkage void (*restore_fp_context)(struct sigcontext *sc);
39 * Atomically swap in the new signal mask, and wait for a signal.
41 asmlinkage inline int
42 sys_sigsuspend(struct pt_regs regs)
44 sigset_t *uset, saveset, newset;
46 save_static(&regs);
47 uset = (sigset_t *) regs.regs[4];
48 if (copy_from_user(&newset, uset, sizeof(sigset_t)))
49 return -EFAULT;
50 sigdelsetmask(&newset, ~_BLOCKABLE);
52 spin_lock_irq(&current->sigmask_lock);
53 saveset = current->blocked;
54 current->blocked = newset;
55 spin_unlock_irq(&current->sigmask_lock);
57 regs.regs[2] = EINTR;
58 regs.regs[7] = 1;
59 while (1) {
60 current->state = TASK_INTERRUPTIBLE;
61 schedule();
62 if (do_signal(&saveset, &regs))
63 return -EINTR;
67 asmlinkage int
68 sys_rt_sigsuspend(struct pt_regs regs)
70 sigset_t *uset, saveset, newset;
72 save_static(&regs);
73 uset = (sigset_t *) regs.regs[4];
74 if (copy_from_user(&newset, uset, sizeof(sigset_t)))
75 return -EFAULT;
76 sigdelsetmask(&newset, ~_BLOCKABLE);
78 spin_lock_irq(&current->sigmask_lock);
79 saveset = current->blocked;
80 current->blocked = newset;
81 spin_unlock_irq(&current->sigmask_lock);
83 regs.regs[2] = EINTR;
84 regs.regs[7] = 1;
85 while (1) {
86 current->state = TASK_INTERRUPTIBLE;
87 schedule();
88 if (do_signal(&saveset, &regs))
89 return -EINTR;
93 asmlinkage int
94 sys_sigaction(int sig, const struct sigaction *act,
95 struct sigaction *oact)
97 struct k_sigaction new_ka, old_ka;
98 int ret;
100 if (act) {
101 sigset_t mask;
102 if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
103 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
104 __get_user(new_ka.sa.sa_flags, &act->sa_flags))
105 return -EFAULT;
107 __copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t));
108 new_ka.ka_restorer = NULL;
111 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
113 if (!ret && oact) {
114 if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
115 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
116 __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
117 return -EFAULT;
118 __copy_to_user(&old_ka.sa.sa_mask, &oact->sa_mask,
119 sizeof(sigset_t));
122 return ret;
125 asmlinkage int
126 sys_sigaltstack(const stack_t *uss, stack_t *uoss)
128 struct pt_regs *regs = (struct pt_regs *) &uss;
130 return do_sigaltstack(uss, uoss, regs->regs[29]);
134 * To do: this entire function should be accessed over a function pointer
135 * such that we can handle stack frames for different ABIs.
138 asmlinkage void
139 restore_sigcontext(struct pt_regs *regs, struct sigcontext *context)
141 long long reg;
142 int owned_fp;
144 __get_user(regs->cp0_epc, &context->sc_pc);
146 __get_user(reg, &context->sc_mdhi);
147 regs->hi = (int) reg;
148 __get_user(reg, &context->sc_mdlo);
149 regs->lo = (int) reg;
151 #define restore_gp_reg(i) __get_user(reg, &context->sc_regs[i]); \
152 regs->regs[i] = (int) reg;
153 restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
154 restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
155 restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
156 restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
157 restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
158 restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
159 restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
160 restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
161 restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
162 restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
163 restore_gp_reg(31);
164 #undef restore_gp_reg
166 /* FP depends on what FPU in what mode we have. */
167 __get_user(owned_fp, &context->sc_ownedfp);
168 #if 0
169 if (owned_fp) {
170 restore_fp_context(context);
171 last_task_used_math = current;
173 #endif
174 restore_fp_context(context);
178 * The structure sc describes the stackframe on the userstack. The frames
179 * are identical for normal and realtime signal stackframes with the
180 * exception of the additional struct ucontext for rt frames.
182 struct sigframe {
183 unsigned long ass[4]; /* argument save space for o32 */
184 unsigned int code[4]; /* signal trampoline */
185 struct sigcontext scc;
188 struct rt_sigframe {
189 unsigned long ass[4];
190 unsigned int code[4];
191 struct sigcontext scc;
192 // struct ucontext uc;
195 asmlinkage int sys_sigreturn(struct pt_regs regs)
197 struct sigcontext *context;
198 sigset_t blocked;
200 context = (struct sigcontext *)(long) regs.regs[29];
201 if (!access_ok(VERIFY_READ, context, sizeof(struct sigcontext)) ||
202 (regs.regs[29] & (SZREG - 1)))
203 goto badframe;
205 #if 1
206 if (__get_user(blocked.sig[0], &context->sc_sigset[0]) ||
207 __get_user(blocked.sig[1], &context->sc_sigset[1]) ||
208 __get_user(blocked.sig[2], &context->sc_sigset[2]) ||
209 __get_user(blocked.sig[3], &context->sc_sigset[3]))
210 goto badframe;
211 #else
212 if (__copy_from_user(&blocked, &context->sc_sigset, sizeof(blocked)))
213 goto badframe;
214 #endif
216 sigdelsetmask(&blocked, ~_BLOCKABLE);
217 spin_lock_irq(&current->sigmask_lock);
218 current->blocked = blocked;
219 recalc_sigpending(current);
220 spin_unlock_irq(&current->sigmask_lock);
222 restore_sigcontext(&regs, context);
225 * Don't let your children do this ...
227 __asm__ __volatile__(
228 "move\t$29,%0\n\t"
229 "j\tret_from_sys_call"
230 :/* no outputs */
231 :"r" (&regs));
232 /* Unreached */
234 badframe:
235 lock_kernel();
236 do_exit(SIGSEGV);
237 unlock_kernel();
240 /* same as sys_sigreturn for now */
241 asmlinkage int sys_rt_sigreturn(struct pt_regs regs)
243 return -ENOSYS;
246 #define scc_offset ((size_t)&((struct sigframe *)0)->scc)
249 * Set up the return code ...
251 * .set noreorder
252 * addiu sp,0x20
253 * li v0,__NR_sigreturn
254 * syscall
255 * .set reorder
257 static void inline
258 setup_trampoline(unsigned int *code)
260 __put_user(0x27bd0000 + scc_offset , code + 0);
261 __put_user(0x24020000 + __NR_sigreturn, code + 1);
262 __put_user(0x0000000c , code + 2);
265 * Flush caches so that the instructions will be correctly executed.
267 flush_cache_sigtramp((unsigned long) code);
270 static void inline
271 setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc, sigset_t *set)
273 int owned_fp;
275 __put_user(regs->cp0_epc, &sc->sc_pc);
276 __put_user(regs->cp0_status, &sc->sc_status); /* Status register */
278 #define save_gp_reg(i) __put_user(regs->regs[(i)], &sc->sc_regs[(i)])
279 __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
280 save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
281 save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
282 save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
283 save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
284 save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
285 save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
286 save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
287 save_gp_reg(31);
288 #undef save_gp_reg
290 __put_user(regs->hi, &sc->sc_mdhi);
291 __put_user(regs->lo, &sc->sc_mdlo);
292 __put_user(regs->cp0_cause, &sc->sc_cause);
294 owned_fp = (current == last_task_used_math);
295 __put_user(owned_fp, &sc->sc_ownedfp);
297 #if 0
298 if (current->used_math) { /* fp is active. */
299 set_cp0_status(ST0_CU1, ST0_CU1);
300 save_fp_context(sc); /* CPU-dependent */
301 last_task_used_math = NULL;
302 regs->cp0_status &= ~ST0_CU1;
303 current->used_math = 0;
305 #endif
306 set_cp0_status(ST0_CU1, ST0_CU1);
307 save_fp_context(sc); /* CPU-dependent */
309 __put_user(set->sig[0], &sc->sc_sigset[0]);
310 __put_user(set->sig[1], &sc->sc_sigset[1]);
311 __put_user(set->sig[2], &sc->sc_sigset[2]);
312 __put_user(set->sig[3], &sc->sc_sigset[3]);
315 static void inline
316 setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
317 int signr, sigset_t *oldmask)
319 struct sigframe *frame;
320 struct sigcontext *sc;
322 /* Align the stackframe to an adequate boundary for the architecture. */
323 frame = (struct sigframe *) (long) regs->regs[29];
324 frame--;
325 frame = (struct sigframe *)((unsigned long)frame & ALMASK);
327 if (verify_area(VERIFY_WRITE, frame, sizeof (*frame)))
328 goto segv_and_exit;
329 sc = &frame->scc;
331 setup_trampoline(frame->code);
332 setup_sigcontext(regs, &frame->scc, oldmask);
334 regs->regs[4] = signr; /* arguments */
335 regs->regs[5] = 0; /* should be cause */
336 regs->regs[6] = (long) frame; /* ptr to sigcontext */
337 regs->regs[29] = (unsigned long) frame; /* Stack pointer */
338 regs->regs[31] = (unsigned long) frame->code; /* Return address */
339 regs->cp0_epc = (unsigned long) ka->sa.sa_handler; /* handler address */
340 regs->regs[25] = regs->cp0_epc; /* PIC shit... */
342 #if DEBUG_SIG
343 printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n",
344 current->comm, current->pid, frame, regs->cp0_epc, frame->code);
345 #endif
346 return;
348 segv_and_exit:
349 lock_kernel();
350 do_exit(SIGSEGV);
351 unlock_kernel();
354 static void inline
355 setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
356 int signr, sigset_t *oldmask, siginfo_t *info)
358 printk("Aiee: setup_tr_frame wants to be written");
361 /* ------------------------------------------------------------------------- */
363 static inline void handle_signal(unsigned long sig, struct k_sigaction *ka,
364 siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
366 if (ka->sa.sa_flags & SA_SIGINFO)
367 setup_rt_frame(ka, regs, sig, oldset, info);
368 else
369 setup_frame(ka, regs, sig, oldset);
371 if (ka->sa.sa_flags & SA_ONESHOT)
372 ka->sa.sa_handler = SIG_DFL;
373 if (!(ka->sa.sa_flags & SA_NODEFER)) {
374 spin_lock_irq(&current->sigmask_lock);
375 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
376 sigaddset(&current->blocked,sig);
377 recalc_sigpending(current);
378 spin_unlock_irq(&current->sigmask_lock);
382 static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
384 switch(regs->regs[0]) {
385 case ERESTARTNOHAND:
386 regs->regs[2] = EINTR;
387 break;
388 case ERESTARTSYS:
389 if(!(ka->sa.sa_flags & SA_RESTART)) {
390 regs->regs[2] = EINTR;
391 break;
393 /* fallthrough */
394 case ERESTARTNOINTR: /* Userland will reload $v0. */
395 regs->regs[7] = regs->regs[26];
396 regs->cp0_epc -= 8;
399 regs->regs[0] = 0; /* Don't deal with this again. */
402 extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs);
404 asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
406 struct k_sigaction *ka;
407 siginfo_t info;
409 #ifdef CONFIG_BINFMT_IRIX
410 if (current->personality != PER_LINUX) /* XXX */
411 return do_irix_signal(oldset, regs);
412 #endif
414 if (!oldset)
415 oldset = &current->blocked;
417 for (;;) {
418 unsigned long signr;
420 spin_lock_irq(&current->sigmask_lock);
421 signr = dequeue_signal(&current->blocked, &info);
422 spin_unlock_irq(&current->sigmask_lock);
424 if (!signr)
425 break;
427 if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
428 /* Let the debugger run. */
429 current->exit_code = signr;
430 current->state = TASK_STOPPED;
431 notify_parent(current, SIGCHLD);
432 schedule();
434 /* We're back. Did the debugger cancel the sig? */
435 if (!(signr = current->exit_code))
436 continue;
437 current->exit_code = 0;
439 /* The debugger continued. Ignore SIGSTOP. */
440 if (signr == SIGSTOP)
441 continue;
443 /* Update the siginfo structure. Is this good? */
444 if (signr != info.si_signo) {
445 info.si_signo = signr;
446 info.si_errno = 0;
447 info.si_code = SI_USER;
448 info.si_pid = current->p_pptr->pid;
449 info.si_uid = current->p_pptr->uid;
452 /* If the (new) signal is now blocked, requeue it. */
453 if (sigismember(&current->blocked, signr)) {
454 send_sig_info(signr, &info, current);
455 continue;
459 ka = &current->sig->action[signr-1];
460 if (ka->sa.sa_handler == SIG_IGN) {
461 if (signr != SIGCHLD)
462 continue;
463 /* Check for SIGCHLD: it's special. */
464 while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
465 /* nothing */;
466 continue;
469 if (ka->sa.sa_handler == SIG_DFL) {
470 int exit_code = signr;
472 /* Init gets no signals it doesn't want. */
473 if (current->pid == 1)
474 continue;
476 switch (signr) {
477 case SIGCONT: case SIGCHLD: case SIGWINCH:
478 continue;
480 case SIGTSTP: case SIGTTIN: case SIGTTOU:
481 if (is_orphaned_pgrp(current->pgrp))
482 continue;
483 /* FALLTHRU */
485 case SIGSTOP:
486 current->state = TASK_STOPPED;
487 current->exit_code = signr;
488 if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
489 notify_parent(current, SIGCHLD);
490 schedule();
491 continue;
493 case SIGQUIT: case SIGILL: case SIGTRAP:
494 case SIGABRT: case SIGFPE: case SIGSEGV:
495 case SIGBUS:
496 if (do_coredump(signr, regs))
497 exit_code |= 0x80;
498 /* FALLTHRU */
500 default:
501 lock_kernel();
502 sigaddset(&current->signal, signr);
503 recalc_sigpending(current);
504 current->flags |= PF_SIGNALED;
505 do_exit(exit_code);
506 /* NOTREACHED */
510 if (regs->regs[0])
511 syscall_restart(regs, ka);
512 /* Whee! Actually deliver the signal. */
513 handle_signal(signr, ka, &info, oldset, regs);
514 return 1;
518 * Who's code doesn't conform to the restartable syscall convention
519 * dies here!!! The li instruction, a single machine instruction,
520 * must directly be followed by the syscall instruction.
522 if (regs->regs[0]) {
523 if (regs->regs[2] == ERESTARTNOHAND ||
524 regs->regs[2] == ERESTARTSYS ||
525 regs->regs[2] == ERESTARTNOINTR) {
526 regs->regs[7] = regs->regs[26];
527 regs->cp0_epc -= 8;
530 return 0;
534 * Compatibility syscall. Can be replaced in libc.
536 asmlinkage int sys_pause(void)
538 current->state = TASK_INTERRUPTIBLE;
539 schedule();
540 return -ERESTARTNOHAND;