- pre3:
[davej-history.git] / arch / mips / kernel / irixsig.c
blob6f6556da484f1d62330581792b89a2b2db380a74
1 /*
2 * irixsig.c: WHEEE, IRIX signals! YOW, am I compatable or what?!?!
4 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
5 * Copyright (C) 1997 - 2000 Ralf Baechle (ralf@gnu.org)
6 * Copyright (C) 2000 Silicon Graphics, Inc.
7 */
8 #include <linux/kernel.h>
9 #include <linux/sched.h>
10 #include <linux/mm.h>
11 #include <linux/errno.h>
12 #include <linux/smp.h>
13 #include <linux/smp_lock.h>
14 #include <linux/time.h>
16 #include <asm/ptrace.h>
17 #include <asm/uaccess.h>
19 asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
20 int options, unsigned long *ru);
21 extern asmlinkage void syscall_trace(void);
23 #undef DEBUG_SIG
25 #define _S(nr) (1<<((nr)-1))
27 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
29 typedef struct {
30 unsigned long sig[4];
31 } irix_sigset_t;
33 struct sigctx_irix5 {
34 u32 rmask, cp0_status;
35 u64 pc;
36 u64 regs[32];
37 u64 fpregs[32];
38 u32 usedfp, fpcsr, fpeir, sstk_flags;
39 u64 hi, lo;
40 u64 cp0_cause, cp0_badvaddr, _unused0;
41 irix_sigset_t sigset;
42 u64 weird_fpu_thing;
43 u64 _unused1[31];
46 #ifdef DEBUG_SIG
47 /* Debugging */
48 static inline void dump_irix5_sigctx(struct sigctx_irix5 *c)
50 int i;
52 printk("misc: rmask[%08lx] status[%08lx] pc[%08lx]\n",
53 (unsigned long) c->rmask,
54 (unsigned long) c->cp0_status,
55 (unsigned long) c->pc);
56 printk("regs: ");
57 for(i = 0; i < 16; i++)
58 printk("[%d]<%08lx> ", i, (unsigned long) c->regs[i]);
59 printk("\nregs: ");
60 for(i = 16; i < 32; i++)
61 printk("[%d]<%08lx> ", i, (unsigned long) c->regs[i]);
62 printk("\nfpregs: ");
63 for(i = 0; i < 16; i++)
64 printk("[%d]<%08lx> ", i, (unsigned long) c->fpregs[i]);
65 printk("\nfpregs: ");
66 for(i = 16; i < 32; i++)
67 printk("[%d]<%08lx> ", i, (unsigned long) c->fpregs[i]);
68 printk("misc: usedfp[%d] fpcsr[%08lx] fpeir[%08lx] stk_flgs[%08lx]\n",
69 (int) c->usedfp, (unsigned long) c->fpcsr,
70 (unsigned long) c->fpeir, (unsigned long) c->sstk_flags);
71 printk("misc: hi[%08lx] lo[%08lx] cause[%08lx] badvaddr[%08lx]\n",
72 (unsigned long) c->hi, (unsigned long) c->lo,
73 (unsigned long) c->cp0_cause, (unsigned long) c->cp0_badvaddr);
74 printk("misc: sigset<0>[%08lx] sigset<1>[%08lx] sigset<2>[%08lx] "
75 "sigset<3>[%08lx]\n", (unsigned long) c->sigset.sig[0],
76 (unsigned long) c->sigset.sig[1],
77 (unsigned long) c->sigset.sig[2],
78 (unsigned long) c->sigset.sig[3]);
80 #endif
82 static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs,
83 int signr, sigset_t *oldmask)
85 unsigned long sp;
86 struct sigctx_irix5 *ctx;
87 int i;
89 sp = regs->regs[29];
90 sp -= sizeof(struct sigctx_irix5);
91 sp &= ~(0xf);
92 ctx = (struct sigctx_irix5 *) sp;
93 if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx)))
94 goto segv_and_exit;
96 __put_user(0, &ctx->weird_fpu_thing);
97 __put_user(~(0x00000001), &ctx->rmask);
98 __put_user(0, &ctx->regs[0]);
99 for(i = 1; i < 32; i++)
100 __put_user((u64) regs->regs[i], &ctx->regs[i]);
102 __put_user((u64) regs->hi, &ctx->hi);
103 __put_user((u64) regs->lo, &ctx->lo);
104 __put_user((u64) regs->cp0_epc, &ctx->pc);
105 __put_user(current->used_math, &ctx->usedfp);
106 __put_user((u64) regs->cp0_cause, &ctx->cp0_cause);
107 __put_user((u64) regs->cp0_badvaddr, &ctx->cp0_badvaddr);
109 __put_user(0, &ctx->sstk_flags); /* XXX sigstack unimp... todo... */
111 __copy_to_user(&ctx->sigset, oldmask, sizeof(irix_sigset_t));
113 #ifdef DEBUG_SIG
114 dump_irix5_sigctx(ctx);
115 #endif
117 regs->regs[4] = (unsigned long) signr;
118 regs->regs[5] = 0; /* XXX sigcode XXX */
119 regs->regs[6] = regs->regs[29] = sp;
120 regs->regs[7] = (unsigned long) ka->sa.sa_handler;
121 regs->regs[25] = regs->cp0_epc = (unsigned long) ka->sa.sa_restorer;
122 return;
124 segv_and_exit:
125 if (signr == SIGSEGV)
126 ka->sa.sa_handler = SIG_DFL;
127 force_sig(SIGSEGV, current);
130 static void inline
131 setup_irix_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
132 int signr, sigset_t *oldmask, siginfo_t *info)
134 printk("Aiee: setup_tr_frame wants to be written");
135 do_exit(SIGSEGV);
138 static inline void handle_signal(unsigned long sig, struct k_sigaction *ka,
139 siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
141 if (ka->sa.sa_flags & SA_SIGINFO)
142 setup_irix_rt_frame(ka, regs, sig, oldset, info);
143 else
144 setup_irix_frame(ka, regs, sig, oldset);
146 if (ka->sa.sa_flags & SA_ONESHOT)
147 ka->sa.sa_handler = SIG_DFL;
148 if (!(ka->sa.sa_flags & SA_NODEFER)) {
149 spin_lock_irq(&current->sigmask_lock);
150 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
151 sigaddset(&current->blocked,sig);
152 recalc_sigpending(current);
153 spin_unlock_irq(&current->sigmask_lock);
157 static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
159 switch(regs->regs[0]) {
160 case ERESTARTNOHAND:
161 regs->regs[2] = EINTR;
162 break;
163 case ERESTARTSYS:
164 if(!(ka->sa.sa_flags & SA_RESTART)) {
165 regs->regs[2] = EINTR;
166 break;
168 /* fallthrough */
169 case ERESTARTNOINTR: /* Userland will reload $v0. */
170 regs->cp0_epc -= 8;
173 regs->regs[0] = 0; /* Don't deal with this again. */
176 asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
178 struct k_sigaction *ka;
179 siginfo_t info;
181 if (!oldset)
182 oldset = &current->blocked;
184 for (;;) {
185 unsigned long signr;
187 spin_lock_irq(&current->sigmask_lock);
188 signr = dequeue_signal(&current->blocked, &info);
189 spin_unlock_irq(&current->sigmask_lock);
191 if (!signr)
192 break;
194 if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
195 /* Let the debugger run. */
196 current->exit_code = signr;
197 current->state = TASK_STOPPED;
198 notify_parent(current, SIGCHLD);
199 schedule();
201 /* We're back. Did the debugger cancel the sig? */
202 if (!(signr = current->exit_code))
203 continue;
204 current->exit_code = 0;
206 /* The debugger continued. Ignore SIGSTOP. */
207 if (signr == SIGSTOP)
208 continue;
210 /* Update the siginfo structure. Is this good? */
211 if (signr != info.si_signo) {
212 info.si_signo = signr;
213 info.si_errno = 0;
214 info.si_code = SI_USER;
215 info.si_pid = current->p_pptr->pid;
216 info.si_uid = current->p_pptr->uid;
219 /* If the (new) signal is now blocked, requeue it. */
220 if (sigismember(&current->blocked, signr)) {
221 send_sig_info(signr, &info, current);
222 continue;
226 ka = &current->sig->action[signr-1];
227 if (ka->sa.sa_handler == SIG_IGN) {
228 if (signr != SIGCHLD)
229 continue;
230 /* Check for SIGCHLD: it's special. */
231 while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
232 /* nothing */;
233 continue;
236 if (ka->sa.sa_handler == SIG_DFL) {
237 int exit_code = signr;
239 /* Init gets no signals it doesn't want. */
240 if (current->pid == 1)
241 continue;
243 switch (signr) {
244 case SIGCONT: case SIGCHLD: case SIGWINCH:
245 continue;
247 case SIGTSTP: case SIGTTIN: case SIGTTOU:
248 if (is_orphaned_pgrp(current->pgrp))
249 continue;
250 /* FALLTHRU */
252 case SIGSTOP:
253 current->state = TASK_STOPPED;
254 current->exit_code = signr;
255 if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
256 notify_parent(current, SIGCHLD);
257 schedule();
258 continue;
260 case SIGQUIT: case SIGILL: case SIGTRAP:
261 case SIGABRT: case SIGFPE: case SIGSEGV:
262 if (do_coredump(signr, regs))
263 exit_code |= 0x80;
264 /* FALLTHRU */
266 default:
267 sigaddset(&current->pending.signal, signr);
268 recalc_sigpending(current);
269 current->flags |= PF_SIGNALED;
270 do_exit(exit_code);
271 /* NOTREACHED */
275 if (regs->regs[0])
276 syscall_restart(regs, ka);
277 /* Whee! Actually deliver the signal. */
278 handle_signal(signr, ka, &info, oldset, regs);
279 return 1;
283 * Who's code doesn't conform to the restartable syscall convention
284 * dies here!!! The li instruction, a single machine instruction,
285 * must directly be followed by the syscall instruction.
287 if (regs->regs[0]) {
288 if (regs->regs[2] == ERESTARTNOHAND ||
289 regs->regs[2] == ERESTARTSYS ||
290 regs->regs[2] == ERESTARTNOINTR) {
291 regs->cp0_epc -= 8;
294 return 0;
297 asmlinkage void
298 irix_sigreturn(struct pt_regs *regs)
300 struct sigctx_irix5 *context, *magic;
301 unsigned long umask, mask;
302 u64 *fregs;
303 int sig, i, base = 0;
304 sigset_t blocked;
306 if(regs->regs[2] == 1000)
307 base = 1;
309 context = (struct sigctx_irix5 *) regs->regs[base + 4];
310 magic = (struct sigctx_irix5 *) regs->regs[base + 5];
311 sig = (int) regs->regs[base + 6];
312 #ifdef DEBUG_SIG
313 printk("[%s:%d] IRIX sigreturn(scp[%p],ucp[%p],sig[%d])\n",
314 current->comm, current->pid, context, magic, sig);
315 #endif
316 if (!context)
317 context = magic;
318 if (!access_ok(VERIFY_READ, context, sizeof(struct sigctx_irix5)))
319 goto badframe;
321 #ifdef DEBUG_SIG
322 dump_irix5_sigctx(context);
323 #endif
325 __get_user(regs->cp0_epc, &context->pc);
326 umask = context->rmask; mask = 2;
327 for (i = 1; i < 32; i++, mask <<= 1) {
328 if(umask & mask)
329 __get_user(regs->regs[i], &context->regs[i]);
331 __get_user(regs->hi, &context->hi);
332 __get_user(regs->lo, &context->lo);
334 if ((umask & 1) && context->usedfp) {
335 fregs = (u64 *) &current->thread.fpu;
336 for(i = 0; i < 32; i++)
337 fregs[i] = (u64) context->fpregs[i];
338 __get_user(current->thread.fpu.hard.control, &context->fpcsr);
341 /* XXX do sigstack crapola here... XXX */
343 if (__copy_from_user(&blocked, &context->sigset, sizeof(blocked)))
344 goto badframe;
346 sigdelsetmask(&blocked, ~_BLOCKABLE);
347 spin_lock_irq(&current->sigmask_lock);
348 current->blocked = blocked;
349 recalc_sigpending(current);
350 spin_unlock_irq(&current->sigmask_lock);
353 * Don't let your children do this ...
355 if (current->ptrace & PT_TRACESYS)
356 syscall_trace();
357 __asm__ __volatile__(
358 "move\t$29,%0\n\t"
359 "j\tret_from_sys_call"
360 :/* no outputs */
361 :"r" (&regs));
362 /* Unreached */
364 badframe:
365 force_sig(SIGSEGV, current);
368 struct sigact_irix5 {
369 int flags;
370 void (*handler)(int);
371 u32 sigset[4];
372 int _unused0[2];
375 #ifdef DEBUG_SIG
376 static inline void dump_sigact_irix5(struct sigact_irix5 *p)
378 printk("<f[%d] hndlr[%08lx] msk[%08lx]>", p->flags,
379 (unsigned long) p->handler,
380 (unsigned long) p->sigset[0]);
382 #endif
384 asmlinkage int
385 irix_sigaction(int sig, const struct sigaction *act,
386 struct sigaction *oact, void *trampoline)
388 struct k_sigaction new_ka, old_ka;
389 int ret;
391 #ifdef DEBUG_SIG
392 printk(" (%d,%s,%s,%08lx) ", sig, (!new ? "0" : "NEW"),
393 (!old ? "0" : "OLD"), trampoline);
394 if(new) {
395 dump_sigact_irix5(new); printk(" ");
397 #endif
398 if (act) {
399 sigset_t mask;
400 if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
401 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
402 __get_user(new_ka.sa.sa_flags, &act->sa_flags))
403 return -EFAULT;
405 __copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t));
408 * Hmmm... methinks IRIX libc always passes a valid trampoline
409 * value for all invocations of sigaction. Will have to
410 * investigate. POSIX POSIX, die die die...
412 new_ka.sa.sa_restorer = trampoline;
415 /* XXX Implement SIG_SETMASK32 for IRIX compatibility */
416 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
418 if (!ret && oact) {
419 if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
420 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
421 __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
422 return -EFAULT;
423 __copy_to_user(&old_ka.sa.sa_mask, &oact->sa_mask,
424 sizeof(sigset_t));
427 return ret;
430 asmlinkage int irix_sigpending(irix_sigset_t *set)
432 return do_sigpending(set, sizeof(*set));
435 asmlinkage int irix_sigprocmask(int how, irix_sigset_t *new, irix_sigset_t *old)
437 sigset_t oldbits, newbits;
438 int error;
440 if (new) {
441 error = verify_area(VERIFY_READ, new, sizeof(*new));
442 if (error)
443 return error;
444 __copy_from_user(&newbits, new, sizeof(unsigned long)*4);
445 sigdelsetmask(&newbits, ~_BLOCKABLE);
447 spin_lock_irq(&current->sigmask_lock);
448 oldbits = current->blocked;
450 switch(how) {
451 case 1:
452 sigorsets(&newbits, &oldbits, &newbits);
453 break;
455 case 2:
456 sigandsets(&newbits, &oldbits, &newbits);
457 break;
459 case 3:
460 break;
462 case 256:
463 siginitset(&newbits, newbits.sig[0]);
464 break;
466 default:
467 return -EINVAL;
469 recalc_sigpending(current);
470 spin_unlock_irq(&current->sigmask_lock);
472 if(old) {
473 error = verify_area(VERIFY_WRITE, old, sizeof(*old));
474 if(error)
475 return error;
476 __copy_to_user(old, &current->blocked, sizeof(unsigned long)*4);
479 return 0;
482 asmlinkage int irix_sigsuspend(struct pt_regs *regs)
484 sigset_t *uset, saveset, newset;
486 uset = (sigset_t *) regs->regs[4];
487 if (copy_from_user(&newset, uset, sizeof(sigset_t)))
488 return -EFAULT;
489 sigdelsetmask(&newset, ~_BLOCKABLE);
491 spin_lock_irq(&current->sigmask_lock);
492 saveset = current->blocked;
493 current->blocked = newset;
494 recalc_sigpending(current);
495 spin_unlock_irq(&current->sigmask_lock);
497 regs->regs[2] = -EINTR;
498 while (1) {
499 current->state = TASK_INTERRUPTIBLE;
500 schedule();
501 if (do_irix_signal(&saveset, regs))
502 return -EINTR;
506 /* hate hate hate... */
507 struct irix5_siginfo {
508 int sig, code, error;
509 union {
510 char unused[128 - (3 * 4)]; /* Safety net. */
511 struct {
512 int pid;
513 union {
514 int uid;
515 struct {
516 int utime, status, stime;
517 } child;
518 } procdata;
519 } procinfo;
521 unsigned long fault_addr;
523 struct {
524 int fd;
525 long band;
526 } fileinfo;
528 unsigned long sigval;
529 } stuff;
532 static inline unsigned long timespectojiffies(struct timespec *value)
534 unsigned long sec = (unsigned) value->tv_sec;
535 long nsec = value->tv_nsec;
537 if (sec > (LONG_MAX / HZ))
538 return LONG_MAX;
539 nsec += 1000000000L / HZ - 1;
540 nsec /= 1000000000L / HZ;
541 return HZ * sec + nsec;
544 asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
545 struct timespec *tp)
547 long expire = MAX_SCHEDULE_TIMEOUT;
548 sigset_t kset;
549 int i, sig, error, timeo = 0;
551 #ifdef DEBUG_SIG
552 printk("[%s:%d] irix_sigpoll_sys(%p,%p,%p)\n",
553 current->comm, current->pid, set, info, tp);
554 #endif
556 /* Must always specify the signal set. */
557 if(!set)
558 return -EINVAL;
560 error = verify_area(VERIFY_READ, set, sizeof(kset));
561 if (error)
562 goto out;
564 __copy_from_user(&kset, set, sizeof(set));
565 if (error)
566 goto out;
568 if (info && clear_user(info, sizeof(*info))) {
569 error = -EFAULT;
570 goto out;
573 if(tp) {
574 error = verify_area(VERIFY_READ, tp, sizeof(*tp));
575 if(error)
576 return error;
577 if(!tp->tv_sec && !tp->tv_nsec) {
578 error = -EINVAL;
579 goto out;
581 expire = timespectojiffies(tp)+(tp->tv_sec||tp->tv_nsec);
584 while(1) {
585 long tmp = 0;
587 current->state = TASK_INTERRUPTIBLE;
588 expire = schedule_timeout(expire);
590 for (i=0; i<=4; i++)
591 tmp |= (current->pending.signal.sig[i] & kset.sig[i]);
593 if (tmp)
594 break;
595 if (!expire) {
596 timeo = 1;
597 break;
599 if (signal_pending(current))
600 return -EINTR;
602 if (timeo)
603 return -EAGAIN;
605 for(sig = 1; i <= 65 /* IRIX_NSIG */; sig++) {
606 if (sigismember (&kset, sig))
607 continue;
608 if (sigismember (&current->pending.signal, sig)) {
609 /* XXX need more than this... */
610 if (info)
611 info->sig = sig;
612 error = 0;
613 goto out;
617 /* Should not get here, but do something sane if we do. */
618 error = -EINTR;
620 out:
621 return error;
624 /* This is here because of irix5_siginfo definition. */
625 #define P_PID 0
626 #define P_PGID 2
627 #define P_ALL 7
629 extern int getrusage(struct task_struct *, int, struct rusage *);
631 #define W_EXITED 1
632 #define W_TRAPPED 2
633 #define W_STOPPED 4
634 #define W_CONT 8
635 #define W_NOHANG 64
637 #define W_MASK (W_EXITED | W_TRAPPED | W_STOPPED | W_CONT | W_NOHANG)
639 asmlinkage int irix_waitsys(int type, int pid, struct irix5_siginfo *info,
640 int options, struct rusage *ru)
642 int flag, retval;
643 DECLARE_WAITQUEUE(wait, current);
644 struct task_struct *p;
646 if (!info) {
647 retval = -EINVAL;
648 goto out;
650 retval = verify_area(VERIFY_WRITE, info, sizeof(*info));
651 if(retval)
652 goto out;
653 if (ru) {
654 retval = verify_area(VERIFY_WRITE, ru, sizeof(*ru));
655 if(retval)
656 goto out;
658 if (options & ~(W_MASK)) {
659 retval = -EINVAL;
660 goto out;
662 if (type != P_PID && type != P_PGID && type != P_ALL) {
663 retval = -EINVAL;
664 goto out;
666 add_wait_queue(&current->wait_chldexit, &wait);
667 repeat:
668 flag = 0;
669 current->state = TASK_INTERRUPTIBLE;
670 read_lock(&tasklist_lock);
671 for (p = current->p_cptr; p; p = p->p_osptr) {
672 if ((type == P_PID) && p->pid != pid)
673 continue;
674 if ((type == P_PGID) && p->pgrp != pid)
675 continue;
676 if ((p->exit_signal != SIGCHLD))
677 continue;
678 flag = 1;
679 switch (p->state) {
680 case TASK_STOPPED:
681 if (!p->exit_code)
682 continue;
683 if (!(options & (W_TRAPPED|W_STOPPED)) &&
684 !(p->ptrace & PT_PTRACED))
685 continue;
686 if (ru != NULL)
687 getrusage(p, RUSAGE_BOTH, ru);
688 __put_user(SIGCHLD, &info->sig);
689 __put_user(0, &info->code);
690 __put_user(p->pid, &info->stuff.procinfo.pid);
691 __put_user((p->exit_code >> 8) & 0xff,
692 &info->stuff.procinfo.procdata.child.status);
693 __put_user(p->times.tms_utime, &info->stuff.procinfo.procdata.child.utime);
694 __put_user(p->times.tms_stime, &info->stuff.procinfo.procdata.child.stime);
695 p->exit_code = 0;
696 retval = 0;
697 goto end_waitsys;
698 case TASK_ZOMBIE:
699 current->times.tms_cutime += p->times.tms_utime + p->times.tms_cutime;
700 current->times.tms_cstime += p->times.tms_stime + p->times.tms_cstime;
701 if (ru != NULL)
702 getrusage(p, RUSAGE_BOTH, ru);
703 __put_user(SIGCHLD, &info->sig);
704 __put_user(1, &info->code); /* CLD_EXITED */
705 __put_user(p->pid, &info->stuff.procinfo.pid);
706 __put_user((p->exit_code >> 8) & 0xff,
707 &info->stuff.procinfo.procdata.child.status);
708 __put_user(p->times.tms_utime,
709 &info->stuff.procinfo.procdata.child.utime);
710 __put_user(p->times.tms_stime,
711 &info->stuff.procinfo.procdata.child.stime);
712 retval = 0;
713 if (p->p_opptr != p->p_pptr) {
714 REMOVE_LINKS(p);
715 p->p_pptr = p->p_opptr;
716 SET_LINKS(p);
717 notify_parent(p, SIGCHLD);
718 } else
719 release(p);
720 goto end_waitsys;
721 default:
722 continue;
725 read_unlock(&tasklist_lock);
726 if (flag) {
727 retval = 0;
728 if (options & W_NOHANG)
729 goto end_waitsys;
730 retval = -ERESTARTSYS;
731 if (signal_pending(current))
732 goto end_waitsys;
733 current->state = TASK_INTERRUPTIBLE;
734 schedule();
735 goto repeat;
737 retval = -ECHILD;
738 end_waitsys:
739 current->state = TASK_RUNNING;
740 remove_wait_queue(&current->wait_chldexit, &wait);
742 out:
743 return retval;
746 struct irix5_context {
747 u32 flags;
748 u32 link;
749 u32 sigmask[4];
750 struct { u32 sp, size, flags; } stack;
751 int regs[36];
752 u32 fpregs[32];
753 u32 fpcsr;
754 u32 _unused0;
755 u32 _unused1[47];
756 u32 weird_graphics_thing;
759 asmlinkage int irix_getcontext(struct pt_regs *regs)
761 int error, i, base = 0;
762 struct irix5_context *ctx;
763 unsigned long flags;
765 if (regs->regs[2] == 1000)
766 base = 1;
767 ctx = (struct irix5_context *) regs->regs[base + 4];
769 #ifdef DEBUG_SIG
770 printk("[%s:%d] irix_getcontext(%p)\n",
771 current->comm, current->pid, ctx);
772 #endif
774 error = verify_area(VERIFY_WRITE, ctx, sizeof(*ctx));
775 if(error)
776 goto out;
777 __put_user(current->thread.irix_oldctx, &ctx->link);
779 __copy_to_user(&ctx->sigmask, &current->blocked, sizeof(irix_sigset_t));
781 /* XXX Do sigstack stuff someday... */
782 __put_user(0, &ctx->stack.sp);
783 __put_user(0, &ctx->stack.size);
784 __put_user(0, &ctx->stack.flags);
786 __put_user(0, &ctx->weird_graphics_thing);
787 __put_user(0, &ctx->regs[0]);
788 for (i = 1; i < 32; i++)
789 __put_user(regs->regs[i], &ctx->regs[i]);
790 __put_user(regs->lo, &ctx->regs[32]);
791 __put_user(regs->hi, &ctx->regs[33]);
792 __put_user(regs->cp0_cause, &ctx->regs[34]);
793 __put_user(regs->cp0_epc, &ctx->regs[35]);
795 flags = 0x0f;
796 if(!current->used_math) {
797 flags &= ~(0x08);
798 } else {
799 /* XXX wheee... */
800 printk("Wheee, no code for saving IRIX FPU context yet.\n");
802 __put_user(flags, &ctx->flags);
803 error = 0;
805 out:
806 return error;
809 asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
811 int error, base = 0;
812 struct irix5_context *ctx;
814 if(regs->regs[2] == 1000)
815 base = 1;
816 ctx = (struct irix5_context *) regs->regs[base + 4];
818 #ifdef DEBUG_SIG
819 printk("[%s:%d] irix_setcontext(%p)\n",
820 current->comm, current->pid, ctx);
821 #endif
823 error = verify_area(VERIFY_READ, ctx, sizeof(*ctx));
824 if (error)
825 goto out;
827 if (ctx->flags & 0x02) {
828 /* XXX sigstack garbage, todo... */
829 printk("Wheee, cannot do sigstack stuff in setcontext\n");
832 if (ctx->flags & 0x04) {
833 int i;
835 /* XXX extra control block stuff... todo... */
836 for(i = 1; i < 32; i++)
837 regs->regs[i] = ctx->regs[i];
838 regs->lo = ctx->regs[32];
839 regs->hi = ctx->regs[33];
840 regs->cp0_epc = ctx->regs[35];
843 if (ctx->flags & 0x08) {
844 /* XXX fpu context, blah... */
845 printk("Wheee, cannot restore FPU context yet...\n");
847 current->thread.irix_oldctx = ctx->link;
848 error = regs->regs[2];
850 out:
851 return error;
854 struct irix_sigstack { unsigned long sp; int status; };
856 asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *old)
858 int error;
860 #ifdef DEBUG_SIG
861 printk("[%s:%d] irix_sigstack(%p,%p)\n",
862 current->comm, current->pid, new, old);
863 #endif
864 if(new) {
865 error = verify_area(VERIFY_READ, new, sizeof(*new));
866 if(error)
867 goto out;
870 if(old) {
871 error = verify_area(VERIFY_WRITE, old, sizeof(*old));
872 if(error)
873 goto out;
875 error = 0;
877 out:
878 return error;
881 struct irix_sigaltstack { unsigned long sp; int size; int status; };
883 asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new,
884 struct irix_sigaltstack *old)
886 int error;
888 #ifdef DEBUG_SIG
889 printk("[%s:%d] irix_sigaltstack(%p,%p)\n",
890 current->comm, current->pid, new, old);
891 #endif
892 if (new) {
893 error = verify_area(VERIFY_READ, new, sizeof(*new));
894 if(error)
895 goto out;
898 if (old) {
899 error = verify_area(VERIFY_WRITE, old, sizeof(*old));
900 if(error)
901 goto out;
903 error = 0;
905 out:
906 error = 0;
908 return error;
911 struct irix_procset {
912 int cmd, ltype, lid, rtype, rid;
915 asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig)
917 int error;
919 error = verify_area(VERIFY_READ, pset, sizeof(*pset));
920 if(error)
921 goto out;
922 #ifdef DEBUG_SIG
923 printk("[%s:%d] irix_sigsendset([%d,%d,%d,%d,%d],%d)\n",
924 current->comm, current->pid,
925 pset->cmd, pset->ltype, pset->lid, pset->rtype, pset->rid,
926 sig);
927 #endif
928 error = -EINVAL;
930 out:
931 return error;