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

📄 signal32.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*  $Id: signal32.c,v 1.1.1.1 2004/02/04 12:55:51 laputa Exp $ *  arch/sparc64/kernel/signal32.c * *  Copyright (C) 1991, 1992  Linus Torvalds *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) *  Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) *  Copyright (C) 1997 Eddie C. Dost   (ecd@skynet.be) *  Copyright (C) 1997,1998 Jakub Jelinek   (jj@sunsite.mff.cuni.cz) */#include <linux/sched.h>#include <linux/kernel.h>#include <linux/signal.h>#include <linux/errno.h>#include <linux/wait.h>#include <linux/ptrace.h>#include <linux/unistd.h>#include <linux/mm.h>#include <linux/smp_lock.h>#include <asm/uaccess.h>#include <asm/bitops.h>#include <asm/ptrace.h>#include <asm/svr4.h>#include <asm/pgtable.h>#include <asm/psrcompat.h>#include <asm/fpumacro.h>#include <asm/visasm.h>#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs,			 unsigned long orig_o0, int ret_from_syscall);/* This turned off for production... *//* #define DEBUG_SIGNALS 1 *//* #define DEBUG_SIGNALS_TRACE 1 *//* #define DEBUG_SIGNALS_MAPS 1 *//* #define DEBUG_SIGNALS_TLB 1 *//* Signal frames: the original one (compatible with SunOS): * * Set up a signal frame... Make the stack look the way SunOS * expects it to look which is basically: * * ---------------------------------- <-- %sp at signal time * Struct sigcontext * Signal address * Ptr to sigcontext area above * Signal code * The signal number itself * One register window * ---------------------------------- <-- New %sp */struct signal_sframe32 {	struct reg_window32 sig_window;	int sig_num;	int sig_code;	/* struct sigcontext32 * */ u32 sig_scptr;	int sig_address;	struct sigcontext32 sig_context;	unsigned extramask[_NSIG_WORDS32 - 1];};/*  * And the new one, intended to be used for Linux applications only * (we have enough in there to work with clone). * All the interesting bits are in the info field. */struct new_signal_frame32 {	struct sparc_stackf32	ss;	__siginfo32_t		info;	/* __siginfo_fpu32_t * */ u32 fpu_save;	unsigned int		insns [2];	unsigned		extramask[_NSIG_WORDS32 - 1];	unsigned		extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */	/* Only valid if (info.si_regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */	siginfo_extra_v8plus_t	v8plus;	__siginfo_fpu_t		fpu_state;};struct rt_signal_frame32 {	struct sparc_stackf32	ss;	siginfo_t32		info;	struct pt_regs32	regs;	sigset_t32		mask;	/* __siginfo_fpu32_t * */ u32 fpu_save;	unsigned int		insns [2];	stack_t32		stack;	unsigned		extra_size; /* Should be sizeof(siginfo_extra_v8plus_t) */	/* Only valid if (regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */	siginfo_extra_v8plus_t	v8plus;	__siginfo_fpu_t		fpu_state;};/* Align macros */#define SF_ALIGNEDSZ  (((sizeof(struct signal_sframe32) + 7) & (~7)))#define NF_ALIGNEDSZ  (((sizeof(struct new_signal_frame32) + 7) & (~7)))#define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame32) + 7) & (~7)))int copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from){	int err;	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32)))		return -EFAULT;	/* If you change siginfo_t structure, please be sure	   this code is fixed accordingly.	   It should never copy any pad contained in the structure	   to avoid security leaks, but must copy the generic	   3 ints plus the relevant union member.	   This routine must convert siginfo from 64bit to 32bit as well	   at the same time.  */	err = __put_user(from->si_signo, &to->si_signo);	err |= __put_user(from->si_errno, &to->si_errno);	err |= __put_user((short)from->si_code, &to->si_code);	if (from->si_code < 0)		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);	else {		switch (from->si_code >> 16) {		case __SI_CHLD >> 16:			err |= __put_user(from->si_utime, &to->si_utime);			err |= __put_user(from->si_stime, &to->si_stime);			err |= __put_user(from->si_status, &to->si_status);		default:			err |= __put_user(from->si_pid, &to->si_pid);			err |= __put_user(from->si_uid, &to->si_uid);			break;		case __SI_FAULT >> 16:		case __SI_POLL >> 16:			err |= __put_user(from->si_trapno, &to->si_trapno);			err |= __put_user((long)from->si_addr, &to->si_addr);			break;		/* case __SI_RT: This is not generated by the kernel as of now.  */		}	}	return err;}/* * atomically swap in the new signal mask, and wait for a signal. * This is really tricky on the Sparc, watch out... */asmlinkage void _sigpause32_common(old_sigset_t32 set, struct pt_regs *regs){	sigset_t saveset;	set &= _BLOCKABLE;	spin_lock_irq(&current->sigmask_lock);	saveset = current->blocked;	siginitset(&current->blocked, set);	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);		regs->tpc = regs->tnpc;	regs->tnpc += 4;	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {		regs->tpc &= 0xffffffff;		regs->tnpc &= 0xffffffff;	}	/* Condition codes and return value where set here for sigpause,	 * and so got used by setup_frame, which again causes sigreturn()	 * to return -EINTR.	 */	while (1) {		current->state = TASK_INTERRUPTIBLE;		schedule();		/*		 * Return -EINTR and set condition code here,		 * so the interrupted system call actually returns		 * these.		 */		regs->tstate |= TSTATE_ICARRY;		regs->u_regs[UREG_I0] = EINTR;		if (do_signal32(&saveset, regs, 0, 0))			return;	}}asmlinkage void do_rt_sigsuspend32(u32 uset, size_t sigsetsize, struct pt_regs *regs){	sigset_t oldset, set;	sigset_t32 set32;        	/* XXX: Don't preclude handling different sized sigset_t's.  */	if (((__kernel_size_t32)sigsetsize) != sizeof(sigset_t)) {		regs->tstate |= TSTATE_ICARRY;		regs->u_regs[UREG_I0] = EINVAL;		return;	}	if (copy_from_user(&set32, (void *)(long)uset, sizeof(set32))) {		regs->tstate |= TSTATE_ICARRY;		regs->u_regs[UREG_I0] = EFAULT;		return;	}	switch (_NSIG_WORDS) {	case 4: set.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32);	case 3: set.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32);	case 2: set.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32);	case 1: set.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32);	}	sigdelsetmask(&set, ~_BLOCKABLE);	spin_lock_irq(&current->sigmask_lock);	oldset = current->blocked;	current->blocked = set;	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);		regs->tpc = regs->tnpc;	regs->tnpc += 4;	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {		regs->tpc &= 0xffffffff;		regs->tnpc &= 0xffffffff;	}	/* Condition codes and return value where set here for sigpause,	 * and so got used by setup_frame, which again causes sigreturn()	 * to return -EINTR.	 */	while (1) {		current->state = TASK_INTERRUPTIBLE;		schedule();		/*		 * Return -EINTR and set condition code here,		 * so the interrupted system call actually returns		 * these.		 */		regs->tstate |= TSTATE_ICARRY;		regs->u_regs[UREG_I0] = EINTR;		if (do_signal32(&oldset, regs, 0, 0))			return;	}}static inline int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu){	unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);	unsigned long fprs;	int err;		err = __get_user(fprs, &fpu->si_fprs);	fprs_write(0);	regs->tstate &= ~TSTATE_PEF;	if (fprs & FPRS_DL)		err |= copy_from_user(fpregs, &fpu->si_float_regs[0], (sizeof(unsigned int) * 32));	if (fprs & FPRS_DU)		err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32], (sizeof(unsigned int) * 32));	err |= __get_user(current->thread.xfsr[0], &fpu->si_fsr);	err |= __get_user(current->thread.gsr[0], &fpu->si_gsr);	current->thread.fpsaved[0] |= fprs;	return err;}void do_new_sigreturn32(struct pt_regs *regs){	struct new_signal_frame32 *sf;	unsigned int psr;	unsigned pc, npc, fpu_save;	sigset_t set;	unsigned seta[_NSIG_WORDS32];	int err, i;		regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;	sf = (struct new_signal_frame32 *) regs->u_regs [UREG_FP];	/* 1. Make sure we are not getting garbage from the user */	if (verify_area (VERIFY_READ, sf, sizeof (*sf))	||	    (((unsigned long) sf) & 3))		goto segv;	get_user(pc, &sf->info.si_regs.pc);	__get_user(npc, &sf->info.si_regs.npc);	if ((pc | npc) & 3)		goto segv;	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {		pc &= 0xffffffff;		npc &= 0xffffffff;	}	regs->tpc = pc;	regs->tnpc = npc;	/* 2. Restore the state */	err = __get_user(regs->y, &sf->info.si_regs.y);	err |= __get_user(psr, &sf->info.si_regs.psr);	for (i = UREG_G1; i <= UREG_I7; i++)		err |= __get_user(regs->u_regs[i], &sf->info.si_regs.u_regs[i]);	if ((psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS) {		err |= __get_user(i, &sf->v8plus.g_upper[0]);		if (i == SIGINFO_EXTRA_V8PLUS_MAGIC) {			for (i = UREG_G1; i <= UREG_I7; i++)				err |= __get_user(((u32 *)regs->u_regs)[2*i], &sf->v8plus.g_upper[i]);		}	}	/* User can only change condition codes in %tstate. */	regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);	regs->tstate |= psr_to_tstate_icc(psr);	err |= __get_user(fpu_save, &sf->fpu_save);	if (fpu_save)		err |= restore_fpu_state32(regs, &sf->fpu_state);	err |= __get_user(seta[0], &sf->info.si_mask);	err |= copy_from_user(seta+1, &sf->extramask, (_NSIG_WORDS32 - 1) * sizeof(unsigned));	if (err)	    	goto segv;	switch (_NSIG_WORDS) {		case 4: set.sig[3] = seta[6] + (((long)seta[7]) << 32);		case 3: set.sig[2] = seta[4] + (((long)seta[5]) << 32);		case 2: set.sig[1] = seta[2] + (((long)seta[3]) << 32);		case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32);	}	sigdelsetmask(&set, ~_BLOCKABLE);	spin_lock_irq(&current->sigmask_lock);	current->blocked = set;	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);	return;segv:	do_exit(SIGSEGV);}asmlinkage void do_sigreturn32(struct pt_regs *regs){	struct sigcontext32 *scptr;	unsigned pc, npc, psr;	sigset_t set;	unsigned seta[_NSIG_WORDS32];	int err;	synchronize_user_stack();	if (current->thread.flags & SPARC_FLAG_NEWSIGNALS)		return do_new_sigreturn32(regs);	scptr = (struct sigcontext32 *)		(regs->u_regs[UREG_I0] & 0x00000000ffffffffUL);	/* Check sanity of the user arg. */	if(verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext32)) ||	   (((unsigned long) scptr) & 3))		goto segv;	err = __get_user(pc, &scptr->sigc_pc);	err |= __get_user(npc, &scptr->sigc_npc);	if((pc | npc) & 3)		goto segv; /* Nice try. */	err |= __get_user(seta[0], &scptr->sigc_mask);	/* Note that scptr + 1 points to extramask */	err |= copy_from_user(seta+1, scptr + 1, (_NSIG_WORDS32 - 1) * sizeof(unsigned));	if (err)	    	goto segv;	switch (_NSIG_WORDS) {		case 4: set.sig[3] = seta[6] + (((long)seta[7]) << 32);		case 3: set.sig[2] = seta[4] + (((long)seta[5]) << 32);		case 2: set.sig[1] = seta[2] + (((long)seta[3]) << 32);		case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32);	}	sigdelsetmask(&set, ~_BLOCKABLE);	spin_lock_irq(&current->sigmask_lock);	current->blocked = set;	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);		if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {		pc &= 0xffffffff;		npc &= 0xffffffff;	}	regs->tpc = pc;	regs->tnpc = npc;	err = __get_user(regs->u_regs[UREG_FP], &scptr->sigc_sp);	err |= __get_user(regs->u_regs[UREG_I0], &scptr->sigc_o0);	err |= __get_user(regs->u_regs[UREG_G1], &scptr->sigc_g1);	/* User can only change condition codes in %tstate. */	err |= __get_user(psr, &scptr->sigc_psr);	if (err)		goto segv;	regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);	regs->tstate |= psr_to_tstate_icc(psr);	return;segv:	do_exit(SIGSEGV);}asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)

⌨️ 快捷键说明

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