📄 ia32_signal.c
字号:
/* * IA32 Architecture-specific signal handling support. * * Copyright (C) 1999, 2001 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/unistd.h>#include <linux/wait.h>#include <asm/uaccess.h>#include <asm/rse.h>#include <asm/sigcontext.h>#include <asm/segment.h>#include <asm/ia32.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 173register double f16 asm ("f16"); register double f17 asm ("f17");register double f18 asm ("f18"); register double f19 asm ("f19");register double f20 asm ("f20"); register double f21 asm ("f21");register double f22 asm ("f22"); register double f23 asm ("f23");register double f24 asm ("f24"); register double f25 asm ("f25");register double f26 asm ("f26"); register double f27 asm ("f27");register double f28 asm ("f28"); register double f29 asm ("f29");register double f30 asm ("f30"); register double f31 asm ("f31");struct sigframe_ia32{ int pretcode; int sig; struct sigcontext_ia32 sc; struct _fpstate_ia32 fpstate; unsigned int extramask[_IA32_NSIG_WORDS-1]; char retcode[8];};struct rt_sigframe_ia32{ int pretcode; int sig; int pinfo; int puc; siginfo_t32 info; struct ucontext_ia32 uc; struct _fpstate_ia32 fpstate; char retcode[8];};intcopy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from){ unsigned long tmp; int err; if (!access_ok(VERIFY_READ, from, sizeof(siginfo_t32))) 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 (from->si_code < 0) err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); else { switch (from->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 *) 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: This is not generated by the kernel as of now. */ } } return err;}intcopy_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: err |= __put_user((long)from->si_addr, &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_RT: This is not generated by the kernel as of now. */ } } 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 (f8, f9 from ptregs) * : : : (f10..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... */#define __ldfe(regnum, x) \({ \ register double __f__ asm ("f"#regnum); \ __asm__ __volatile__ ("ldfe %0=[%1] ;;" :"=f"(__f__): "r"(x)); \})#define __ldf8(regnum, x) \({ \ register double __f__ asm ("f"#regnum); \ __asm__ __volatile__ ("ldf8 %0=[%1] ;;" :"=f"(__f__): "r"(x)); \})#define __stfe(x, regnum) \({ \ register double __f__ asm ("f"#regnum); \ __asm__ __volatile__ ("stfe [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \})#define __stf8(x, regnum) \({ \ register double __f__ asm ("f"#regnum); \ __asm__ __volatile__ ("stf8 [%0]=%1" :: "r"(x), "f"(__f__) : "memory"); \})static intsave_ia32_fpstate_live (struct _fpstate_ia32 *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; /* Readin fsr, fcr, fir, fdr and copy onto fpstate */ asm volatile ( "mov %0=ar.fsr;" : "=r"(fsr)); asm volatile ( "mov %0=ar.fcr;" : "=r"(fcr)); asm volatile ( "mov %0=ar.fir;" : "=r"(fir)); asm volatile ( "mov %0=ar.fdr;" : "=r"(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; asm volatile ( "mov ar.fsr=%0;" :: "r"(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 and f9 from pt_regs * save f10..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)); __stfe(fpregp, 10); copy_to_user(&save->_st[(2+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); __stfe(fpregp, 11); copy_to_user(&save->_st[(3+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); __stfe(fpregp, 12); copy_to_user(&save->_st[(4+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); __stfe(fpregp, 13); copy_to_user(&save->_st[(5+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); __stfe(fpregp, 14); copy_to_user(&save->_st[(6+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); __stfe(fpregp, 15); copy_to_user(&save->_st[(7+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32)); __stf8(&num128[0], 16); __stf8(&num128[1], 17); copy_to_user(&save->_xmm[0], num128, sizeof(struct _xmmreg_ia32)); __stf8(&num128[0], 18); __stf8(&num128[1], 19); copy_to_user(&save->_xmm[1], num128, sizeof(struct _xmmreg_ia32)); __stf8(&num128[0], 20); __stf8(&num128[1], 21); copy_to_user(&save->_xmm[2], num128, sizeof(struct _xmmreg_ia32)); __stf8(&num128[0], 22); __stf8(&num128[1], 23); copy_to_user(&save->_xmm[3], num128, sizeof(struct _xmmreg_ia32)); __stf8(&num128[0], 24); __stf8(&num128[1], 25); copy_to_user(&save->_xmm[4], num128, sizeof(struct _xmmreg_ia32)); __stf8(&num128[0], 26); __stf8(&num128[1], 27); copy_to_user(&save->_xmm[5], num128, sizeof(struct _xmmreg_ia32)); __stf8(&num128[0], 28); __stf8(&num128[1], 29); copy_to_user(&save->_xmm[6], num128, sizeof(struct _xmmreg_ia32)); __stf8(&num128[0], 30); __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 *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 dont 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. */ asm volatile ( "mov %0=ar.fsr;" : "=r"(fsr)); asm volatile ( "mov %0=ar.fcr;" : "=r"(fcr)); asm volatile ( "mov %0=ar.fir;" : "=r"(fir)); asm volatile ( "mov %0=ar.fdr;" : "=r"(fdr)); __get_user(mxcsr, (unsigned int *)&save->mxcsr); /* setting bits 0..5 8..12 with cw and 39..47 from mxcsr */ __get_user(lo, (unsigned int *)&save->cw); num64 = mxcsr & 0xff10; num64 = (num64 << 32) | (lo & 0x1f3f); fcr = (fcr & (~0xff1000001f3f)) | num64;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -