📄 ia32_signal.c
字号:
/* setting bits 0..31 with sw and tag and 32..37 from mxcsr */ __get_user(lo, (unsigned int *)&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 *)&save->tag); num64 = mxcsr & 0x3f; num64 = (num64 << 16) | (hi & 0xffff); num64 = (num64 << 16) | (lo & 0xffff); fsr = (fsr & (~0x3fffffffff)) | num64; /* setting bits 0..47 with cssel and ipoff */ __get_user(lo, (unsigned int *)&save->ipoff); __get_user(hi, (unsigned int *)&save->cssel); num64 = hi & 0xffff; num64 = (num64 << 32) | lo; fir = (fir & (~0xffffffffffff)) | num64; /* setting bits 0..47 with datasel and dataoff */ __get_user(lo, (unsigned int *)&save->dataoff); __get_user(hi, (unsigned int *)&save->datasel); num64 = hi & 0xffff; num64 = (num64 << 32) | lo; fdr = (fdr & (~0xffffffffffff)) | num64; asm volatile ( "mov ar.fsr=%0;" :: "r"(fsr)); asm volatile ( "mov ar.fcr=%0;" :: "r"(fcr)); asm volatile ( "mov ar.fir=%0;" :: "r"(fir)); asm volatile ( "mov ar.fdr=%0;" :: "r"(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)); __ldfe(12, fpregp); copy_from_user(fpregp, &save->_st[(5+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); __ldfe(13, fpregp); copy_from_user(fpregp, &save->_st[(6+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); __ldfe(14, fpregp); copy_from_user(fpregp, &save->_st[(7+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32)); __ldfe(15, fpregp); copy_from_user(num128, &save->_xmm[0], sizeof(struct _xmmreg_ia32)); __ldf8(16, &num128[0]); __ldf8(17, &num128[1]); copy_from_user(num128, &save->_xmm[1], sizeof(struct _xmmreg_ia32)); __ldf8(18, &num128[0]); __ldf8(19, &num128[1]); copy_from_user(num128, &save->_xmm[2], sizeof(struct _xmmreg_ia32)); __ldf8(20, &num128[0]); __ldf8(21, &num128[1]); copy_from_user(num128, &save->_xmm[3], sizeof(struct _xmmreg_ia32)); __ldf8(22, &num128[0]); __ldf8(23, &num128[1]); copy_from_user(num128, &save->_xmm[4], sizeof(struct _xmmreg_ia32)); __ldf8(24, &num128[0]); __ldf8(25, &num128[1]); copy_from_user(num128, &save->_xmm[5], sizeof(struct _xmmreg_ia32)); __ldf8(26, &num128[0]); __ldf8(27, &num128[1]); copy_from_user(num128, &save->_xmm[6], sizeof(struct _xmmreg_ia32)); __ldf8(28, &num128[0]); __ldf8(29, &num128[1]); copy_from_user(num128, &save->_xmm[7], sizeof(struct _xmmreg_ia32)); __ldf8(30, &num128[0]); __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);}asmlinkage longia32_rt_sigsuspend (sigset32_t *uset, 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)); if (sigsetsize > sizeof(sigset_t)) return -EINVAL; if (copy_from_user(&set.sig, &uset->sig, sigsetsize)) return -EFAULT; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sigmask_lock); { oldset = current->blocked; current->blocked = set; recalc_sigpending(current); } spin_unlock_irq(¤t->sigmask_lock); /* * 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_sigsuspend (unsigned int mask, struct sigscratch *scr){ return ia32_rt_sigsuspend((sigset32_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; ret = do_sigaction(sig, &new_sa, &old_sa); return ret ? ret : IA32_SA_HANDLER(&old_sa);}asmlinkage longsys32_rt_sigaction (int sig, struct sigaction32 *act, struct sigaction32 *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(sigset32_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(sigset32_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(sigset32_t)); } return ret;}extern asmlinkage long sys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset, size_t sigsetsize);asmlinkage longsys32_rt_sigprocmask (int how, sigset32_t *set, sigset32_t *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 ? &s : NULL, oset ? &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_sigprocmask (int how, unsigned int *set, unsigned int *oset){ return sys32_rt_sigprocmask(how, (sigset32_t *) set, (sigset32_t *) oset, sizeof(*set));}asmlinkage longsys32_rt_sigtimedwait (sigset32_t *uthese, siginfo_t32 *uinfo, struct timespec32 *uts, unsigned int sigsetsize){ extern asmlinkage long sys_rt_sigtimedwait (const sigset_t *, siginfo_t *, const struct timespec *, size_t); extern int copy_siginfo_to_user32 (siginfo_t32 *, siginfo_t *); mm_segment_t old_fs = get_fs(); struct timespec t; siginfo_t info; sigset_t s; int ret; if (copy_from_user(&s.sig, uthese, sizeof(sigset32_t))) return -EFAULT; if (uts) { ret = get_user(t.tv_sec, &uts->tv_sec); ret |= get_user(t.tv_nsec, &uts->tv_nsec); if (ret) return -EFAULT; } set_fs(KERNEL_DS); ret = sys_rt_sigtimedwait(&s, uinfo ? &info : NULL, uts ? &t : NULL, sigsetsize); set_fs(old_fs); if (ret >= 0 && uinfo) { if (copy_siginfo_to_user32(uinfo, &info)) return -EFAULT; } return ret;}asmlinkage longsys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 *uinfo){ extern asmlinkage long sys_rt_sigqueueinfo (int, int, siginfo_t *); extern int copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from); 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, &info); set_fs(old_fs); return ret;}asmlinkage longsys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact){ struct k_sigaction new_ka, old_ka; unsigned int handler, restorer; int ret; if (act) { old_sigset32_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 *sc, struct _fpstate_ia32 *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 *)&sc->fs); err |= __put_user((regs->r16 >> 48) & 0xffff, (unsigned int *)&sc->gs); err |= __put_user((regs->r16 >> 16) & 0xffff, (unsigned int *)&sc->es); err |= __put_user(regs->r16 & 0xffff, (unsigned int *)&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 *)&sc->cs); /* * `eflags' is in an ar register for this context */ asm volatile ("mov %0=ar.eflag ;;" : "=r"(flag)); 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 *)&sc->ss); if ( save_ia32_fpstate_live(fpstate) < 0 ) err = -EFAULT; else err |= __put_user((u32)(u64)fpstate, &sc->fpstate);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -