/*
* irixsig.c: WHEEE, IRIX signals! YOW, am I compatible or what?!?!
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
* Copyright (C) 1997 - 2000 Ralf Baechle (ralf@gnu.org)
* Copyright (C) 2000 Silicon Graphics, Inc.
*/
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/smp.h>
#include <linux/time.h>
#include <linux/ptrace.h>
#include <linux/resource.h>
#include <asm/ptrace.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#undef DEBUG_SIG
#define _S(nr) (1<<((nr)-1))
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
#define _IRIX_NSIG 128
#define _IRIX_NSIG_BPW BITS_PER_LONG
#define _IRIX_NSIG_WORDS (_IRIX_NSIG / _IRIX_NSIG_BPW)
typedef struct {
unsigned long sig[_IRIX_NSIG_WORDS];
} irix_sigset_t;
struct sigctx_irix5 {
u32 rmask, cp0_status;
u64 pc;
u64 regs[32];
u64 fpregs[32];
u32 usedfp, fpcsr, fpeir, sstk_flags;
u64 hi, lo;
u64 cp0_cause, cp0_badvaddr, _unused0;
irix_sigset_t sigset;
u64 weird_fpu_thing;
u64 _unused1[31];
};
#ifdef DEBUG_SIG
/* Debugging */
static inline void dump_irix5_sigctx(struct sigctx_irix5 *c)
{
int i;
printk("misc: rmask[%08lx] status[%08lx] pc[%08lx]\n",
(unsigned long) c->rmask,
(unsigned long) c->cp0_status,
(unsigned long) c->pc);
printk("regs: ");
for(i = 0; i < 16; i++)
printk("[%d]<%08lx> ", i, (unsigned long) c->regs[i]);
printk("\nregs: ");
for(i = 16; i < 32; i++)
printk("[%d]<%08lx> ", i, (unsigned long) c->regs[i]);
printk("\nfpregs: ");
for(i = 0; i < 16; i++)
printk("[%d]<%08lx> ", i, (unsigned long) c->fpregs[i]);
printk("\nfpregs: ");
for(i = 16; i < 32; i++)
printk("[%d]<%08lx> ", i, (unsigned long) c->fpregs[i]);
printk("misc: usedfp[%d] fpcsr[%08lx] fpeir[%08lx] stk_flgs[%08lx]\n",
(int) c->usedfp, (unsigned long) c->fpcsr,
(unsigned long) c->fpeir, (unsigned long) c->sstk_flags);
printk("misc: hi[%08lx] lo[%08lx] cause[%08lx] badvaddr[%08lx]\n",
(unsigned long) c->hi, (unsigned long) c->lo,
(unsigned long) c->cp0_cause, (unsigned long) c->cp0_badvaddr);
printk("misc: sigset<0>[%08lx] sigset<1>[%08lx] sigset<2>[%08lx] "
"sigset<3>[%08lx]\n", (unsigned long) c->sigset.sig[0],
(unsigned long) c->sigset.sig[1],
(unsigned long) c->sigset.sig[2],
(unsigned long) c->sigset.sig[3]);
}
#endif
static int setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs,
int signr, sigset_t *oldmask)
{
struct sigctx_irix5 __user *ctx;
unsigned long sp;
int error, i;
sp = regs->regs[29];
sp -= sizeof(struct sigctx_irix5);
sp &= ~(0xf);
ctx = (struct sigctx_irix5 __user *) sp;
if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx)))
goto segv_and_exit;
error = __put_user(0, &ctx->weird_fpu_thing);
error |= __put_user(~(0x00000001), &ctx->rmask);
error |= __put_user(0, &ctx->regs[0]);
for(i = 1; i < 32; i++)
error |= __put_user((u64) regs->regs[i], &ctx->regs[i]);
error |= __put_user((u64) regs->hi, &ctx->hi);
error |= __put_user((u64) regs->lo, &ctx->lo);
error |= __put_user((u64) regs->cp0_epc, &ctx->pc);
error |= __put_user(!!used_math(), &ctx->usedfp);
error |= __put_user((u64) regs->cp0_cause, &ctx->cp0_cause);
error |= __put_user((u64) regs->cp0_badvaddr, &ctx->cp0_badvaddr);
error |= __put_user(0, &ctx->sstk_flags); /* XXX sigstack unimp... todo... */
error |= __copy_to_user(&ctx->sigset, oldmask, sizeof(irix_sigset_t)) ? -EFAULT : 0;
if (error)
goto segv_and_exit;
#ifdef DEBUG_SIG
dump_irix5_sigctx(ctx);
#endif
regs->regs[4] = (unsigned long)<