⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 irixsig.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * irixsig.c: WHEEE, IRIX signals!  YOW, am I compatable 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/smp_lock.h>#include <linux/time.h>#include <asm/ptrace.h>#include <asm/uaccess.h>asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,                         int options, unsigned long *ru);extern asmlinkage void syscall_trace(void);#undef DEBUG_SIG#define _S(nr) (1<<((nr)-1))#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))typedef struct {	unsigned long sig[4];} 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]);}#endifstatic void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs,			     int signr, sigset_t *oldmask){	unsigned long sp;	struct sigctx_irix5 *ctx;	int i;	sp = regs->regs[29];	sp -= sizeof(struct sigctx_irix5);	sp &= ~(0xf);	ctx = (struct sigctx_irix5 *) sp;	if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx)))		goto segv_and_exit;	__put_user(0, &ctx->weird_fpu_thing);	__put_user(~(0x00000001), &ctx->rmask);	__put_user(0, &ctx->regs[0]);	for(i = 1; i < 32; i++)		__put_user((u64) regs->regs[i], &ctx->regs[i]);	__put_user((u64) regs->hi, &ctx->hi);	__put_user((u64) regs->lo, &ctx->lo);	__put_user((u64) regs->cp0_epc, &ctx->pc);	__put_user(current->used_math, &ctx->usedfp);	__put_user((u64) regs->cp0_cause, &ctx->cp0_cause);	__put_user((u64) regs->cp0_badvaddr, &ctx->cp0_badvaddr);	__put_user(0, &ctx->sstk_flags); /* XXX sigstack unimp... todo... */	__copy_to_user(&ctx->sigset, oldmask, sizeof(irix_sigset_t));#ifdef DEBUG_SIG	dump_irix5_sigctx(ctx);#endif	regs->regs[4] = (unsigned long) signr;	regs->regs[5] = 0; /* XXX sigcode XXX */	regs->regs[6] = regs->regs[29] = sp;	regs->regs[7] = (unsigned long) ka->sa.sa_handler;	regs->regs[25] = regs->cp0_epc = (unsigned long) ka->sa.sa_restorer;	return;segv_and_exit:	if (signr == SIGSEGV)		ka->sa.sa_handler = SIG_DFL;	force_sig(SIGSEGV, current);}static void inlinesetup_irix_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,               int signr, sigset_t *oldmask, siginfo_t *info){	printk("Aiee: setup_tr_frame wants to be written");	do_exit(SIGSEGV);}static inline void handle_signal(unsigned long sig, struct k_sigaction *ka,        siginfo_t *info, sigset_t *oldset, struct pt_regs * regs){	if (ka->sa.sa_flags & SA_SIGINFO)		setup_irix_rt_frame(ka, regs, sig, oldset, info);	else		setup_irix_frame(ka, regs, sig, oldset);	if (ka->sa.sa_flags & SA_ONESHOT)		ka->sa.sa_handler = SIG_DFL;	if (!(ka->sa.sa_flags & SA_NODEFER)) {		spin_lock_irq(&current->sigmask_lock);		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);	sigaddset(&current->blocked,sig);	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);	}}static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka){	switch(regs->regs[0]) {	case ERESTARTNOHAND:		regs->regs[2] = EINTR;		break;	case ERESTARTSYS:		if(!(ka->sa.sa_flags & SA_RESTART)) {			regs->regs[2] = EINTR;			break;		}	/* fallthrough */	case ERESTARTNOINTR:		/* Userland will reload $v0.  */		regs->cp0_epc -= 8;	}	regs->regs[0] = 0;		/* Don't deal with this again.  */}asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs){	struct k_sigaction *ka;	siginfo_t info;	if (!oldset)		oldset = &current->blocked;	for (;;) {		unsigned long signr;		spin_lock_irq(&current->sigmask_lock);		signr = dequeue_signal(&current->blocked, &info);		spin_unlock_irq(&current->sigmask_lock);		if (!signr)			break;		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {			/* Let the debugger run.  */			current->exit_code = signr;			current->state = TASK_STOPPED;			notify_parent(current, SIGCHLD);			schedule();			/* We're back.  Did the debugger cancel the sig?  */			if (!(signr = current->exit_code))				continue;			current->exit_code = 0;			/* The debugger continued.  Ignore SIGSTOP.  */			if (signr == SIGSTOP)				continue;			/* Update the siginfo structure.  Is this good?  */			if (signr != info.si_signo) {				info.si_signo = signr;				info.si_errno = 0;				info.si_code = SI_USER;				info.si_pid = current->p_pptr->pid;				info.si_uid = current->p_pptr->uid;			}			/* If the (new) signal is now blocked, requeue it.  */			if (sigismember(&current->blocked, signr)) {				send_sig_info(signr, &info, current);				continue;			}		}		ka = &current->sig->action[signr-1];		if (ka->sa.sa_handler == SIG_IGN) {			if (signr != SIGCHLD)				continue;			/* Check for SIGCHLD: it's special.  */			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)				/* nothing */;			continue;		}		if (ka->sa.sa_handler == SIG_DFL) {			int exit_code = signr;			/* Init gets no signals it doesn't want.  */			if (current->pid == 1)				continue;			switch (signr) {			case SIGCONT: case SIGCHLD: case SIGWINCH:				continue;			case SIGTSTP: case SIGTTIN: case SIGTTOU:				if (is_orphaned_pgrp(current->pgrp))					continue;				/* FALLTHRU */			case SIGSTOP:				current->state = TASK_STOPPED;				current->exit_code = signr;				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))					notify_parent(current, SIGCHLD);				schedule();				continue;			case SIGQUIT: case SIGILL: case SIGTRAP:			case SIGABRT: case SIGFPE: case SIGSEGV:				if (do_coredump(signr, regs))					exit_code |= 0x80;				/* FALLTHRU */			default:				sigaddset(&current->pending.signal, signr);				recalc_sigpending(current);				current->flags |= PF_SIGNALED;				do_exit(exit_code);				/* NOTREACHED */			}		}		if (regs->regs[0])			syscall_restart(regs, ka);		/* Whee!  Actually deliver the signal.  */		handle_signal(signr, ka, &info, oldset, regs);		return 1;	}	/*	 * Who's code doesn't conform to the restartable syscall convention	 * dies here!!!  The li instruction, a single machine instruction,	 * must directly be followed by the syscall instruction.	 */	if (regs->regs[0]) {		if (regs->regs[2] == ERESTARTNOHAND ||		    regs->regs[2] == ERESTARTSYS ||		    regs->regs[2] == ERESTARTNOINTR) {			regs->cp0_epc -= 8;		}	}	return 0;}asmlinkage voidirix_sigreturn(struct pt_regs *regs){	struct sigctx_irix5 *context, *magic;	unsigned long umask, mask;	u64 *fregs;	int sig, i, base = 0;	sigset_t blocked;	if(regs->regs[2] == 1000)		base = 1;	context = (struct sigctx_irix5 *) regs->regs[base + 4];	magic = (struct sigctx_irix5 *) regs->regs[base + 5];	sig = (int) regs->regs[base + 6];#ifdef DEBUG_SIG	printk("[%s:%d] IRIX sigreturn(scp[%p],ucp[%p],sig[%d])\n",	       current->comm, current->pid, context, magic, sig);#endif	if (!context)		context = magic;	if (!access_ok(VERIFY_READ, context, sizeof(struct sigctx_irix5)))		goto badframe;#ifdef DEBUG_SIG	dump_irix5_sigctx(context);#endif	__get_user(regs->cp0_epc, &context->pc);	umask = context->rmask; mask = 2;	for (i = 1; i < 32; i++, mask <<= 1) {		if(umask & mask)			__get_user(regs->regs[i], &context->regs[i]);	}	__get_user(regs->hi, &context->hi);	__get_user(regs->lo, &context->lo);	if ((umask & 1) && context->usedfp) {		fregs = (u64 *) &current->thread.fpu;		for(i = 0; i < 32; i++)			fregs[i] = (u64) context->fpregs[i];		__get_user(current->thread.fpu.hard.control, &context->fpcsr);	}	/* XXX do sigstack crapola here... XXX */	if (__copy_from_user(&blocked, &context->sigset, sizeof(blocked)))		goto badframe;	sigdelsetmask(&blocked, ~_BLOCKABLE);	spin_lock_irq(&current->sigmask_lock);	current->blocked = blocked;	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);	/*	 * Don't let your children do this ...	 */	if (current->ptrace & PT_TRACESYS)		syscall_trace();	__asm__ __volatile__(		"move\t$29,%0\n\t"		"j\tret_from_sys_call"		:/* no outputs */		:"r" (&regs));		/* Unreached */badframe:	force_sig(SIGSEGV, current);}struct sigact_irix5 {	int flags;	void (*handler)(int);	u32 sigset[4];	int _unused0[2];};#ifdef DEBUG_SIGstatic inline void dump_sigact_irix5(struct sigact_irix5 *p){	printk("<f[%d] hndlr[%08lx] msk[%08lx]>", p->flags,	       (unsigned long) p->handler,	       (unsigned long) p->sigset[0]);}#endifasmlinkage int irix_sigaction(int sig, const struct sigaction *act,	      struct sigaction *oact, void *trampoline){	struct k_sigaction new_ka, old_ka;	int ret;#ifdef DEBUG_SIG	printk(" (%d,%s,%s,%08lx) ", sig, (!new ? "0" : "NEW"),	       (!old ? "0" : "OLD"), trampoline);	if(new) {		dump_sigact_irix5(new); printk(" ");	}#endif	if (act) {		sigset_t mask;		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||		    __get_user(new_ka.sa.sa_flags, &act->sa_flags))			return -EFAULT;		__copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t));		/*		 * Hmmm... methinks IRIX libc always passes a valid trampoline		 * value for all invocations of sigaction.  Will have to		 * investigate.  POSIX POSIX, die die die...		 */		new_ka.sa.sa_restorer = trampoline;	}/* XXX Implement SIG_SETMASK32 for IRIX compatibility */	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);	if (!ret && oact) {		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags))			return -EFAULT;		__copy_to_user(&old_ka.sa.sa_mask, &oact->sa_mask,		               sizeof(sigset_t));	}	return ret;}asmlinkage int irix_sigpending(irix_sigset_t *set){	return do_sigpending(set, sizeof(*set));}asmlinkage int irix_sigprocmask(int how, irix_sigset_t *new, irix_sigset_t *old){	sigset_t oldbits, newbits;	int error;	if (new) {		error = verify_area(VERIFY_READ, new, sizeof(*new));		if (error)			return error;		__copy_from_user(&newbits, new, sizeof(unsigned long)*4);		sigdelsetmask(&newbits, ~_BLOCKABLE);		spin_lock_irq(&current->sigmask_lock);		oldbits = current->blocked;		switch(how) {		case 1:			sigorsets(&newbits, &oldbits, &newbits);			break;		case 2:			sigandsets(&newbits, &oldbits, &newbits);			break;		case 3:			break;		case 256:			siginitset(&newbits, newbits.sig[0]);			break;		default:			return -EINVAL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -