📄 signal.c
字号:
" bral " SYMBOL_NAME_STR(ret_from_signal) "\n" "4:\n" ".section __ex_table,\"a\"\n" " .align 4\n" " .long 2b,4b\n" " .long 3b,4b\n" ".previous" : /* no outputs, it doesn't ever return */ : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), "n" (frame_offset), "a" (fp) : "a0");#undef frame_offset /* * If we ever get here an exception occurred while * building the above stack-frame. */ goto badframe; }#endif /* CONFIG_UCLINUX */ *pd0 = context.sc_d0; return err;badframe: return 1;}static inline intrt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, struct ucontext *uc, int *pd0){#ifndef CONFIG_UCLINUX int fsize;#endif int temp; greg_t *gregs = uc->uc_mcontext.gregs; unsigned long usp; int err; err = __get_user(temp, &uc->uc_mcontext.version); if (temp != MCONTEXT_VERSION) goto badframe; /* restore passed registers */ err |= __get_user(regs->d0, &gregs[0]); err |= __get_user(regs->d1, &gregs[1]); err |= __get_user(regs->d2, &gregs[2]); err |= __get_user(regs->d3, &gregs[3]); err |= __get_user(regs->d4, &gregs[4]); err |= __get_user(regs->d5, &gregs[5]); err |= __get_user(sw->d6, &gregs[6]); err |= __get_user(sw->d7, &gregs[7]); err |= __get_user(regs->a0, &gregs[8]); err |= __get_user(regs->a1, &gregs[9]); err |= __get_user(regs->a2, &gregs[10]); err |= __get_user(sw->a3, &gregs[11]); err |= __get_user(sw->a4, &gregs[12]); err |= __get_user(sw->a5, &gregs[13]); err |= __get_user(sw->a6, &gregs[14]); err |= __get_user(usp, &gregs[15]); wrusp(usp); err |= __get_user(regs->pc, &gregs[16]); err |= __get_user(temp, &gregs[17]); regs->sr = (regs->sr & 0xff00) | (temp & 0xff); regs->orig_d0 = -1; /* disable syscall checks */#if DAVIDM /* ifdef uc_formatvec */ err |= __get_user(temp, &uc->uc_formatvec);#endif regs->format = temp >> 12; regs->vector = temp & 0xfff;#if DAVIDM /* NO_FPU */ err |= rt_restore_fpu_state(uc);#endif if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT) goto badframe;#ifndef CONFIG_UCLINUX fsize = frame_extra_sizes[regs->format]; if (fsize < 0) { /* * user process trying to return with weird frame format */#if DEBUG printk("user process returning with weird frame format\n");#endif goto badframe; } /* OK. Make room on the supervisor stack for the extra junk, * if necessary. */ if (fsize) {#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack)) __asm__ __volatile__ (" movel %0,%/a0\n\t" " subl %1,%/a0\n\t" /* make room on stack */ " movel %/a0,%/sp\n\t" /* set stack pointer */ /* move switch_stack and pt_regs */ "1: movel %0@+,%/a0@+\n\t" " dbra %2,1b\n\t" " lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */ " lsrl #2,%1\n\t" " subql #1,%1\n\t" "2: movesl %4@+,%2\n\t" "3: movel %2,%/a0@+\n\t" " dbra %1,2b\n\t" " bral " SYMBOL_NAME_STR(ret_from_signal) "\n" "4:\n" ".section __ex_table,\"a\"\n" " .align 4\n" " .long 2b,4b\n" " .long 3b,4b\n" ".previous" : /* no outputs, it doesn't ever return */ : "a" (sw), "d" (fsize), "d" (frame_offset/4-1), "n" (frame_offset), "a" (&uc->uc_extra) : "a0");#undef frame_offset /* * If we ever get here an exception occurred while * building the above stack-frame. */ goto badframe; }#endif /* CONFIG_UCLINUX */ *pd0 = regs->d0; return err;badframe: return 1;}asmlinkage int do_sigreturn(unsigned long __unused){ struct switch_stack *sw = (struct switch_stack *) &__unused; struct pt_regs *regs = (struct pt_regs *) (sw + 1); unsigned long usp = rdusp(); struct sigframe *frame = (struct sigframe *)(usp - 4); sigset_t set; int d0; if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__get_user(set.sig[0], &frame->sc.sc_mask) || (_NSIG_WORDS > 1 && __copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask)))) goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); current->blocked = set; recalc_sigpending(current); if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0)) goto badframe; return d0;badframe: force_sig(SIGSEGV, current); return 0;}asmlinkage int do_rt_sigreturn(unsigned long __unused){ struct switch_stack *sw = (struct switch_stack *) &__unused; struct pt_regs *regs = (struct pt_regs *) (sw + 1); unsigned long usp = rdusp(); struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4); sigset_t set; int d0; if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); current->blocked = set; recalc_sigpending(current); if (rt_restore_ucontext(regs, sw, &frame->uc, &d0)) goto badframe; return d0;badframe: force_sig(SIGSEGV, current); return 0;}#ifndef NO_FPU/* * Set up a signal frame. */static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs){ if (FPU_IS_EMU) { /* save registers */ memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12); memcpy(sc->sc_fpregs, current->thread.fp, 24); return; } __asm__ volatile (".chip 68k/68881\n\t" "fsave %0\n\t" ".chip 68k" : : "m" (*sc->sc_fpstate) : "memory"); if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) { fpu_version = sc->sc_fpstate[0]; if (CPU_IS_020_OR_030 && regs->vector >= (VEC_FPBRUC * 4) && regs->vector <= (VEC_FPNAN * 4)) { /* Clear pending exception in 68882 idle frame */ if (*(unsigned short *) sc->sc_fpstate == 0x1f38) sc->sc_fpstate[0x38] |= 1 << 3; } __asm__ volatile (".chip 68k/68881\n\t" "fmovemx %/fp0-%/fp1,%0\n\t" "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t" ".chip 68k" : /* no outputs */ : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl) : "memory"); }}static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs){ unsigned char fpstate[FPCONTEXT_SIZE]; int context_size = CPU_IS_060 ? 8 : 0; int err = 0; if (FPU_IS_EMU) { /* save fpu control register */ err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr, current->thread.fpcntl, 12); /* save all other fpu register */ err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs, current->thread.fp, 96); return err; } __asm__ volatile (".chip 68k/68881\n\t" "fsave %0\n\t" ".chip 68k" : : "m" (*fpstate) : "memory"); err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate); if (CPU_IS_060 ? fpstate[2] : fpstate[0]) { fpregset_t fpregs; if (!CPU_IS_060) context_size = fpstate[1]; fpu_version = fpstate[0]; if (CPU_IS_020_OR_030 && regs->vector >= (VEC_FPBRUC * 4) && regs->vector <= (VEC_FPNAN * 4)) { /* Clear pending exception in 68882 idle frame */ if (*(unsigned short *) fpstate == 0x1f38) fpstate[0x38] |= 1 << 3; } __asm__ volatile (".chip 68k/68881\n\t" "fmovemx %/fp0-%/fp7,%0\n\t" "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t" ".chip 68k" : /* no outputs */ : "m" (*fpregs.f_fpregs), "m" (fpregs.f_pcr) : "memory"); err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, sizeof(fpregs)); } if (context_size) err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4, context_size); return err;}#endifstatic void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, unsigned long mask){ sc->sc_mask = mask; sc->sc_usp = rdusp(); sc->sc_d0 = regs->d0; sc->sc_d1 = regs->d1; sc->sc_a0 = regs->a0; sc->sc_a1 = regs->a1; sc->sc_sr = regs->sr; sc->sc_pc = regs->pc; sc->sc_formatvec = regs->format << 12 | regs->vector;#ifndef NO_FPU save_fpu_state(sc, regs);#endif}static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs){ struct switch_stack *sw = (struct switch_stack *)regs - 1; greg_t *gregs = uc->uc_mcontext.gregs; int err = 0; err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version); err |= __put_user(regs->d0, &gregs[0]); err |= __put_user(regs->d1, &gregs[1]); err |= __put_user(regs->d2, &gregs[2]); err |= __put_user(regs->d3, &gregs[3]); err |= __put_user(regs->d4, &gregs[4]); err |= __put_user(regs->d5, &gregs[5]); err |= __put_user(sw->d6, &gregs[6]); err |= __put_user(sw->d7, &gregs[7]); err |= __put_user(regs->a0, &gregs[8]); err |= __put_user(regs->a1, &gregs[9]); err |= __put_user(regs->a2, &gregs[10]); err |= __put_user(sw->a3, &gregs[11]); err |= __put_user(sw->a4, &gregs[12]); err |= __put_user(sw->a5, &gregs[13]); err |= __put_user(sw->a6, &gregs[14]); err |= __put_user(rdusp(), &gregs[15]); err |= __put_user(regs->pc, &gregs[16]); err |= __put_user(regs->sr, &gregs[17]);#if DAVIDM /* ifdef uc_formatvec */ err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);#endif#ifndef NO_FPU err |= rt_save_fpu_state(uc, regs);#endif return err;}static inline void push_cache (unsigned long vaddr){#if 0 /* DAVIDM - implement this for 5407, maybe */ /* * Using the old cache_push_v() was really a big waste. * * What we are trying to do is to flush 8 bytes to ram. * Flushing 2 cache lines of 16 bytes is much cheaper than * flushing 1 or 2 pages, as previously done in * cache_push_v(). * Jes */ if (CPU_IS_040) { unsigned long temp; __asm__ __volatile__ (".chip 68040\n\t" "nop\n\t" "ptestr (%1)\n\t" "movec %%mmusr,%0\n\t" ".chip 68k" : "=r" (temp) : "a" (vaddr)); temp &= PAGE_MASK; temp |= vaddr & ~PAGE_MASK; __asm__ __volatile__ (".chip 68040\n\t" "nop\n\t" "cpushl %%bc,(%0)\n\t" ".chip 68k" : : "a" (temp)); } else if (CPU_IS_060) { unsigned long temp; __asm__ __volatile__ (".chip 68060\n\t" "plpar (%0)\n\t" ".chip 68k" : "=a" (temp) : "0" (vaddr)); __asm__ __volatile__ (".chip 68060\n\t" "cpushl %%bc,(%0)\n\t" ".chip 68k" : : "a" (temp)); } else { /* * 68030/68020 have no writeback cache; * still need to clear icache. * Note that vaddr is guaranteed to be long word aligned. */ unsigned long temp; asm volatile ("movec %%cacr,%0" : "=r" (temp)); temp += 4; asm volatile ("movec %0,%%caar\n\t" "movec %1,%%cacr" : : "r" (vaddr), "r" (temp)); asm volatile ("movec %0,%%caar\n\t" "movec %1,%%cacr" : : "r" (vaddr + 4), "r" (temp)); }#endif}static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size){ unsigned long usp; /* Default to using normal stack. */ usp = rdusp(); /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { if (!on_sig_stack(usp)) usp = current->sas_ss_sp + current->sas_ss_size; } return (void *)((usp - frame_size) & -8UL);}static void setup_frame (int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs){ struct sigframe *frame; unsigned long a5;#ifndef CONFIG_UCLINUX int fsize = frame_extra_sizes[regs->format];#endif struct sigcontext context; int err = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -