📄 ia32_signal.c
字号:
fcr = (fcr & (~0xff1000001f3fUL)) | num64; /* setting bits 0..31 with sw and tag and 32..37 from mxcsr */ __get_user(lo, (unsigned int __user *)&save->sw); /* set bits 15,7 (fsw.b, fsw.es) to reflect the current error status */ if ( !(lo & 0x7f) ) lo &= (~0x8080); __get_user(hi, (unsigned int __user *)&save->tag); num64 = mxcsr & 0x3f; num64 = (num64 << 16) | (hi & 0xffff); num64 = (num64 << 16) | (lo & 0xffff); fsr = (fsr & (~0x3fffffffffUL)) | num64; /* setting bits 0..47 with cssel and ipoff */ __get_user(lo, (unsigned int __user *)&save->ipoff); __get_user(hi, (unsigned int __user *)&save->cssel); num64 = hi & 0xffff; num64 = (num64 << 32) | lo; fir = (fir & (~0xffffffffffffUL)) | num64; /* setting bits 0..47 with datasel and dataoff */ __get_user(lo, (unsigned int __user *)&save->dataoff); __get_user(hi, (unsigned int __user *)&save->datasel); num64 = hi & 0xffff; num64 = (num64 << 32) | lo; fdr = (fdr & (~0xffffffffffffUL)) | num64; ia64_setreg(_IA64_REG_AR_FSR, fsr); ia64_setreg(_IA64_REG_AR_FCR, fcr); ia64_setreg(_IA64_REG_AR_FIR, fir); ia64_setreg(_IA64_REG_AR_FDR, fdr); /* * restore f8..f11 onto pt_regs * restore f12..f15 onto live registers */ /* * 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; fpregp = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15); ptp = ia64_task_regs(tsk); copy_from_user(fpregp, &save->_st[(0+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); ia32f2ia64f(&ptp->f8, fpregp); copy_from_user(fpregp, &save->_st[(1+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); ia32f2ia64f(&ptp->f9, fpregp); copy_from_user(fpregp, &save->_st[(2+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); ia32f2ia64f(&ptp->f10, fpregp); copy_from_user(fpregp, &save->_st[(3+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); ia32f2ia64f(&ptp->f11, fpregp); copy_from_user(fpregp, &save->_st[(4+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); ia64_ldfe(12, fpregp); copy_from_user(fpregp, &save->_st[(5+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); ia64_ldfe(13, fpregp); copy_from_user(fpregp, &save->_st[(6+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); ia64_ldfe(14, fpregp); copy_from_user(fpregp, &save->_st[(7+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); ia64_ldfe(15, fpregp); copy_from_user(num128, &save->_xmm[0], sizeof(struct _xmmreg_ia32)); ia64_ldf8(16, &num128[0]); ia64_ldf8(17, &num128[1]); copy_from_user(num128, &save->_xmm[1], sizeof(struct _xmmreg_ia32)); ia64_ldf8(18, &num128[0]); ia64_ldf8(19, &num128[1]); copy_from_user(num128, &save->_xmm[2], sizeof(struct _xmmreg_ia32)); ia64_ldf8(20, &num128[0]); ia64_ldf8(21, &num128[1]); copy_from_user(num128, &save->_xmm[3], sizeof(struct _xmmreg_ia32)); ia64_ldf8(22, &num128[0]); ia64_ldf8(23, &num128[1]); copy_from_user(num128, &save->_xmm[4], sizeof(struct _xmmreg_ia32)); ia64_ldf8(24, &num128[0]); ia64_ldf8(25, &num128[1]); copy_from_user(num128, &save->_xmm[5], sizeof(struct _xmmreg_ia32)); ia64_ldf8(26, &num128[0]); ia64_ldf8(27, &num128[1]); copy_from_user(num128, &save->_xmm[6], sizeof(struct _xmmreg_ia32)); ia64_ldf8(28, &num128[0]); ia64_ldf8(29, &num128[1]); copy_from_user(num128, &save->_xmm[7], sizeof(struct _xmmreg_ia32)); ia64_ldf8(30, &num128[0]); ia64_ldf8(31, &num128[1]); return 0;}static inline voidsigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int restorer){ if (handler + 1 <= 2) /* SIG_DFL, SIG_IGN, or SIG_ERR: must sign-extend to 64-bits */ sa->sa.sa_handler = (__sighandler_t) A((int) handler); else sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler);}long__ia32_rt_sigsuspend (compat_sigset_t *sset, unsigned int sigsetsize, struct sigscratch *scr){ extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall); sigset_t oldset, set; scr->scratch_unat = 0; /* avoid leaking kernel bits to user level */ memset(&set, 0, sizeof(set)); memcpy(&set.sig, &sset->sig, sigsetsize); sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); { oldset = current->blocked; current->blocked = set; recalc_sigpending(); } spin_unlock_irq(¤t->sighand->siglock); /* * The return below usually returns to the signal handler. We need to pre-set the * correct error code here to ensure that the right values get saved in sigcontext * by ia64_do_signal. */ scr->pt.r8 = -EINTR; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); if (ia64_do_signal(&oldset, scr, 1)) return -EINTR; }}asmlinkage longia32_rt_sigsuspend (compat_sigset_t __user *uset, unsigned int sigsetsize, struct sigscratch *scr){ compat_sigset_t set; if (sigsetsize > sizeof(compat_sigset_t)) return -EINVAL; if (copy_from_user(&set.sig, &uset->sig, sigsetsize)) return -EFAULT; return __ia32_rt_sigsuspend(&set, sigsetsize, scr);}asmlinkage longia32_sigsuspend (unsigned int mask, struct sigscratch *scr){ return __ia32_rt_sigsuspend((compat_sigset_t *) &mask, sizeof(mask), scr);}asmlinkage longsys32_signal (int sig, unsigned int handler){ struct k_sigaction new_sa, old_sa; int ret; sigact_set_handler(&new_sa, handler, 0); new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK; sigemptyset(&new_sa.sa.sa_mask); ret = do_sigaction(sig, &new_sa, &old_sa); return ret ? ret : IA32_SA_HANDLER(&old_sa);}asmlinkage longsys32_rt_sigaction (int sig, struct sigaction32 __user *act, struct sigaction32 __user *oact, unsigned int sigsetsize){ struct k_sigaction new_ka, old_ka; unsigned int handler, restorer; int ret; /* XXX: Don't preclude handling different sized sigset_t's. */ if (sigsetsize != sizeof(compat_sigset_t)) return -EINVAL; if (act) { ret = get_user(handler, &act->sa_handler); ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags); ret |= get_user(restorer, &act->sa_restorer); ret |= copy_from_user(&new_ka.sa.sa_mask, &act->sa_mask, sizeof(compat_sigset_t)); if (ret) return -EFAULT; sigact_set_handler(&new_ka, handler, restorer); } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { ret = put_user(IA32_SA_HANDLER(&old_ka), &oact->sa_handler); ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags); ret |= put_user(IA32_SA_RESTORER(&old_ka), &oact->sa_restorer); ret |= copy_to_user(&oact->sa_mask, &old_ka.sa.sa_mask, sizeof(compat_sigset_t)); } return ret;}asmlinkage longsys32_rt_sigprocmask (int how, compat_sigset_t __user *set, compat_sigset_t __user *oset, unsigned int sigsetsize){ mm_segment_t old_fs = get_fs(); sigset_t s; long ret; if (sigsetsize > sizeof(s)) return -EINVAL; if (set) { memset(&s, 0, sizeof(s)); if (copy_from_user(&s.sig, set, sigsetsize)) return -EFAULT; } set_fs(KERNEL_DS); ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *) &s : NULL, oset ? (sigset_t __user *) &s : NULL, sizeof(s)); set_fs(old_fs); if (ret) return ret; if (oset) { if (copy_to_user(oset, &s.sig, sigsetsize)) return -EFAULT; } return 0;}asmlinkage longsys32_rt_sigqueueinfo (int pid, int sig, compat_siginfo_t __user *uinfo){ mm_segment_t old_fs = get_fs(); siginfo_t info; int ret; if (copy_siginfo_from_user32(&info, uinfo)) return -EFAULT; set_fs(KERNEL_DS); ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info); set_fs(old_fs); return ret;}asmlinkage longsys32_sigaction (int sig, struct old_sigaction32 __user *act, struct old_sigaction32 __user *oact){ struct k_sigaction new_ka, old_ka; unsigned int handler, restorer; int ret; if (act) { compat_old_sigset_t mask; ret = get_user(handler, &act->sa_handler); ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags); ret |= get_user(restorer, &act->sa_restorer); ret |= get_user(mask, &act->sa_mask); if (ret) return ret; sigact_set_handler(&new_ka, handler, restorer); siginitset(&new_ka.sa.sa_mask, mask); } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { ret = put_user(IA32_SA_HANDLER(&old_ka), &oact->sa_handler); ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags); ret |= put_user(IA32_SA_RESTORER(&old_ka), &oact->sa_restorer); ret |= put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } return ret;}static intsetup_sigcontext_ia32 (struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __user *fpstate, struct pt_regs *regs, unsigned long mask){ int err = 0; unsigned long flag; if (!access_ok(VERIFY_WRITE, sc, sizeof(*sc))) return -EFAULT; err |= __put_user((regs->r16 >> 32) & 0xffff, (unsigned int __user *)&sc->fs); err |= __put_user((regs->r16 >> 48) & 0xffff, (unsigned int __user *)&sc->gs); err |= __put_user((regs->r16 >> 16) & 0xffff, (unsigned int __user *)&sc->es); err |= __put_user(regs->r16 & 0xffff, (unsigned int __user *)&sc->ds); err |= __put_user(regs->r15, &sc->edi); err |= __put_user(regs->r14, &sc->esi); err |= __put_user(regs->r13, &sc->ebp); err |= __put_user(regs->r12, &sc->esp); err |= __put_user(regs->r11, &sc->ebx); err |= __put_user(regs->r10, &sc->edx); err |= __put_user(regs->r9, &sc->ecx); err |= __put_user(regs->r8, &sc->eax);#if 0 err |= __put_user(current->tss.trap_no, &sc->trapno); err |= __put_user(current->tss.error_code, &sc->err);#endif err |= __put_user(regs->cr_iip, &sc->eip); err |= __put_user(regs->r17 & 0xffff, (unsigned int __user *)&sc->cs); /* * `eflags' is in an ar register for this context */ flag = ia64_getreg(_IA64_REG_AR_EFLAG); err |= __put_user((unsigned int)flag, &sc->eflags); err |= __put_user(regs->r12, &sc->esp_at_signal); err |= __put_user((regs->r17 >> 16) & 0xffff, (unsigned int __user *)&sc->ss); if ( save_ia32_fpstate_live(fpstate) < 0 ) err = -EFAULT; else err |= __put_user((u32)(u64)fpstate, &sc->fpstate);#if 0 tmp = save_i387(fpstate); if (tmp < 0) err = 1; else err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate); /* non-iBCS2 extensions.. */#endif err |= __put_user(mask, &sc->oldmask);#if 0 err |= __put_user(current->tss.cr2, &sc->cr2);#endif return err;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -