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

📄 ia32_signal.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * IA32 Architecture-specific signal handling support. * * Copyright (C) 1999, 2001-2002, 2005 Hewlett-Packard Co *	David Mosberger-Tang <davidm@hpl.hp.com> * Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com> * Copyright (C) 2000 VA Linux Co * Copyright (C) 2000 Don Dugger <n0ano@valinux.com> * * Derived from i386 and Alpha versions. */#include <linux/errno.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/personality.h>#include <linux/ptrace.h>#include <linux/sched.h>#include <linux/signal.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/stddef.h>#include <linux/syscalls.h>#include <linux/unistd.h>#include <linux/wait.h>#include <linux/compat.h>#include <asm/intrinsics.h>#include <asm/uaccess.h>#include <asm/rse.h>#include <asm/sigcontext.h>#include "ia32priv.h"#include "../kernel/sigframe.h"#define A(__x)		((unsigned long)(__x))#define DEBUG_SIG	0#define _BLOCKABLE	(~(sigmask(SIGKILL) | sigmask(SIGSTOP)))#define __IA32_NR_sigreturn            119#define __IA32_NR_rt_sigreturn         173struct sigframe_ia32{       int pretcode;       int sig;       struct sigcontext_ia32 sc;       struct _fpstate_ia32 fpstate;       unsigned int extramask[_COMPAT_NSIG_WORDS-1];       char retcode[8];};struct rt_sigframe_ia32{       int pretcode;       int sig;       int pinfo;       int puc;       compat_siginfo_t info;       struct ucontext_ia32 uc;       struct _fpstate_ia32 fpstate;       char retcode[8];};intcopy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from){	unsigned long tmp;	int err;	if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))		return -EFAULT;	err = __get_user(to->si_signo, &from->si_signo);	err |= __get_user(to->si_errno, &from->si_errno);	err |= __get_user(to->si_code, &from->si_code);	if (to->si_code < 0)		err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);	else {		switch (to->si_code >> 16) {		      case __SI_CHLD >> 16:			err |= __get_user(to->si_utime, &from->si_utime);			err |= __get_user(to->si_stime, &from->si_stime);			err |= __get_user(to->si_status, &from->si_status);		      default:			err |= __get_user(to->si_pid, &from->si_pid);			err |= __get_user(to->si_uid, &from->si_uid);			break;		      case __SI_FAULT >> 16:			err |= __get_user(tmp, &from->si_addr);			to->si_addr = (void __user *) tmp;			break;		      case __SI_POLL >> 16:			err |= __get_user(to->si_band, &from->si_band);			err |= __get_user(to->si_fd, &from->si_fd);			break;		      case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */		      case __SI_MESGQ >> 16:			err |= __get_user(to->si_pid, &from->si_pid);			err |= __get_user(to->si_uid, &from->si_uid);			err |= __get_user(to->si_int, &from->si_int);			break;		}	}	return err;}intcopy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from){	unsigned int addr;	int err;	if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))		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:			/* avoid type-checking warnings by copying _pad[0] in lieu of si_addr... */			err |= __put_user(from->_sifields._pad[0], &to->si_addr);			break;		case __SI_POLL >> 16:			err |= __put_user(from->si_band, &to->si_band);			err |= __put_user(from->si_fd, &to->si_fd);			break;		case __SI_TIMER >> 16:			err |= __put_user(from->si_tid, &to->si_tid);			err |= __put_user(from->si_overrun, &to->si_overrun);			addr = (unsigned long) from->si_ptr;			err |= __put_user(addr, &to->si_ptr);			break;		case __SI_RT >> 16:	/* Not generated by the kernel as of now.  */		case __SI_MESGQ >> 16:			err |= __put_user(from->si_uid, &to->si_uid);			err |= __put_user(from->si_pid, &to->si_pid);			addr = (unsigned long) from->si_ptr;			err |= __put_user(addr, &to->si_ptr);			break;		}	}	return err;}/* *  SAVE and RESTORE of ia32 fpstate info, from ia64 current state *  Used in exception handler to pass the fpstate to the user, and restore *  the fpstate while returning from the exception handler. * *    fpstate info and their mapping to IA64 regs: *    fpstate    REG(BITS)      Attribute    Comments *    cw         ar.fcr(0:12)                with bits 7 and 6 not used *    sw         ar.fsr(0:15) *    tag        ar.fsr(16:31)               with odd numbered bits not used *                                           (read returns 0, writes ignored) *    ipoff      ar.fir(0:31) *    cssel      ar.fir(32:47) *    dataoff    ar.fdr(0:31) *    datasel    ar.fdr(32:47) * *    _st[(0+TOS)%8]   f8 *    _st[(1+TOS)%8]   f9 *    _st[(2+TOS)%8]   f10 *    _st[(3+TOS)%8]   f11                   (f8..f11 from ptregs) *      : :            :                     (f12..f15 from live reg) *      : :            : *    _st[(7+TOS)%8]   f15                   TOS=sw.top(bits11:13) * *    status     Same as sw     RO *    magic      0                           as X86_FXSR_MAGIC in ia32 *    mxcsr      Bits(7:15)=ar.fcr(39:47) *               Bits(0:5) =ar.fsr(32:37)    with bit 6 reserved *    _xmm[0..7] f16..f31                    (live registers) *                                           with _xmm[0] *                                             Bit(64:127)=f17(0:63) *                                             Bit(0:63)=f16(0:63) *    All other fields unused... */static intsave_ia32_fpstate_live (struct _fpstate_ia32 __user *save){	struct task_struct *tsk = current;	struct pt_regs *ptp;	struct _fpreg_ia32 *fpregp;	char buf[32];	unsigned long fsr, fcr, fir, fdr;	unsigned long new_fsr;	unsigned long num128[2];	unsigned long mxcsr=0;	int fp_tos, fr8_st_map;	if (!access_ok(VERIFY_WRITE, save, sizeof(*save)))		return -EFAULT;	/* Read in fsr, fcr, fir, fdr and copy onto fpstate */	fsr = ia64_getreg(_IA64_REG_AR_FSR);	fcr = ia64_getreg(_IA64_REG_AR_FCR);	fir = ia64_getreg(_IA64_REG_AR_FIR);	fdr = ia64_getreg(_IA64_REG_AR_FDR);	/*	 * We need to clear the exception state before calling the signal handler. Clear	 * the bits 15, bits 0-7 in fp status word. Similar to the functionality of fnclex	 * instruction.	 */	new_fsr = fsr & ~0x80ff;	ia64_setreg(_IA64_REG_AR_FSR, new_fsr);	__put_user(fcr & 0xffff, &save->cw);	__put_user(fsr & 0xffff, &save->sw);	__put_user((fsr>>16) & 0xffff, &save->tag);	__put_user(fir, &save->ipoff);	__put_user((fir>>32) & 0xffff, &save->cssel);	__put_user(fdr, &save->dataoff);	__put_user((fdr>>32) & 0xffff, &save->datasel);	__put_user(fsr & 0xffff, &save->status);	mxcsr = ((fcr>>32) & 0xff80) | ((fsr>>32) & 0x3f);	__put_user(mxcsr & 0xffff, &save->mxcsr);	__put_user( 0, &save->magic); //#define X86_FXSR_MAGIC   0x0000	/*	 * save f8..f11  from pt_regs	 * save f12..f15 from live register set	 */	/*	 *  Find the location where f8 has to go in fp reg stack.  This depends on	 *  TOP(11:13) field of sw. Other f reg continue sequentially from where f8 maps	 *  to.	 */	fp_tos = (fsr>>11)&0x7;	fr8_st_map = (8-fp_tos)&0x7;	ptp = ia64_task_regs(tsk);	fpregp = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15);	ia64f2ia32f(fpregp, &ptp->f8);	copy_to_user(&save->_st[(0+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));	ia64f2ia32f(fpregp, &ptp->f9);	copy_to_user(&save->_st[(1+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));	ia64f2ia32f(fpregp, &ptp->f10);	copy_to_user(&save->_st[(2+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));	ia64f2ia32f(fpregp, &ptp->f11);	copy_to_user(&save->_st[(3+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));	ia64_stfe(fpregp, 12);	copy_to_user(&save->_st[(4+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));	ia64_stfe(fpregp, 13);	copy_to_user(&save->_st[(5+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));	ia64_stfe(fpregp, 14);	copy_to_user(&save->_st[(6+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));	ia64_stfe(fpregp, 15);	copy_to_user(&save->_st[(7+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));	ia64_stf8(&num128[0], 16);	ia64_stf8(&num128[1], 17);	copy_to_user(&save->_xmm[0], num128, sizeof(struct _xmmreg_ia32));	ia64_stf8(&num128[0], 18);	ia64_stf8(&num128[1], 19);	copy_to_user(&save->_xmm[1], num128, sizeof(struct _xmmreg_ia32));	ia64_stf8(&num128[0], 20);	ia64_stf8(&num128[1], 21);	copy_to_user(&save->_xmm[2], num128, sizeof(struct _xmmreg_ia32));	ia64_stf8(&num128[0], 22);	ia64_stf8(&num128[1], 23);	copy_to_user(&save->_xmm[3], num128, sizeof(struct _xmmreg_ia32));	ia64_stf8(&num128[0], 24);	ia64_stf8(&num128[1], 25);	copy_to_user(&save->_xmm[4], num128, sizeof(struct _xmmreg_ia32));	ia64_stf8(&num128[0], 26);	ia64_stf8(&num128[1], 27);	copy_to_user(&save->_xmm[5], num128, sizeof(struct _xmmreg_ia32));	ia64_stf8(&num128[0], 28);	ia64_stf8(&num128[1], 29);	copy_to_user(&save->_xmm[6], num128, sizeof(struct _xmmreg_ia32));	ia64_stf8(&num128[0], 30);	ia64_stf8(&num128[1], 31);	copy_to_user(&save->_xmm[7], num128, sizeof(struct _xmmreg_ia32));	return 0;}static intrestore_ia32_fpstate_live (struct _fpstate_ia32 __user *save){	struct task_struct *tsk = current;	struct pt_regs *ptp;	unsigned int lo, hi;	unsigned long num128[2];	unsigned long num64, mxcsr;	struct _fpreg_ia32 *fpregp;	char buf[32];	unsigned long fsr, fcr, fir, fdr;	int fp_tos, fr8_st_map;	if (!access_ok(VERIFY_READ, save, sizeof(*save)))		return(-EFAULT);	/*	 * Updating fsr, fcr, fir, fdr.	 * Just a bit more complicated than save.	 * - Need to make sure that we don't write any value other than the	 *   specific fpstate info	 * - Need to make sure that the untouched part of frs, fdr, fir, fcr	 *   should remain same while writing.	 * So, we do a read, change specific fields and write.	 */	fsr = ia64_getreg(_IA64_REG_AR_FSR);	fcr = ia64_getreg(_IA64_REG_AR_FCR);	fir = ia64_getreg(_IA64_REG_AR_FIR);	fdr = ia64_getreg(_IA64_REG_AR_FDR);	__get_user(mxcsr, (unsigned int __user *)&save->mxcsr);	/* setting bits 0..5 8..12 with cw and 39..47 from mxcsr */	__get_user(lo, (unsigned int __user *)&save->cw);	num64 = mxcsr & 0xff10;	num64 = (num64 << 32) | (lo & 0x1f3f);

⌨️ 快捷键说明

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