📄 traps.c
字号:
if (regs->tstate & TSTATE_PRIV) die_if_kernel("Penguin overflow trap from kernel mode", regs); if (test_thread_flag(TIF_32BIT)) { regs->tpc &= 0xffffffff; regs->tnpc &= 0xffffffff; } info.si_signo = SIGEMT; info.si_errno = 0; info.si_code = EMT_TAGOVF; info.si_addr = (void __user *)regs->tpc; info.si_trapno = 0; force_sig_info(SIGEMT, &info, current);}void do_div0(struct pt_regs *regs){ siginfo_t info; if (notify_die(DIE_TRAP, "integer division by zero", regs, 0, 0x28, SIGFPE) == NOTIFY_STOP) return; if (regs->tstate & TSTATE_PRIV) die_if_kernel("TL0: Kernel divide by zero.", regs); if (test_thread_flag(TIF_32BIT)) { regs->tpc &= 0xffffffff; regs->tnpc &= 0xffffffff; } info.si_signo = SIGFPE; info.si_errno = 0; info.si_code = FPE_INTDIV; info.si_addr = (void __user *)regs->tpc; info.si_trapno = 0; force_sig_info(SIGFPE, &info, current);}void instruction_dump (unsigned int *pc){ int i; if ((((unsigned long) pc) & 3)) return; printk("Instruction DUMP:"); for (i = -3; i < 6; i++) printk("%c%08x%c",i?' ':'<',pc[i],i?' ':'>'); printk("\n");}static void user_instruction_dump (unsigned int __user *pc){ int i; unsigned int buf[9]; if ((((unsigned long) pc) & 3)) return; if (copy_from_user(buf, pc - 3, sizeof(buf))) return; printk("Instruction DUMP:"); for (i = 0; i < 9; i++) printk("%c%08x%c",i==3?' ':'<',buf[i],i==3?' ':'>'); printk("\n");}void show_stack(struct task_struct *tsk, unsigned long *_ksp){ unsigned long pc, fp, thread_base, ksp; struct thread_info *tp = tsk->thread_info; struct reg_window *rw; int count = 0; ksp = (unsigned long) _ksp; if (tp == current_thread_info()) flushw_all(); fp = ksp + STACK_BIAS; thread_base = (unsigned long) tp; printk("Call Trace:");#ifdef CONFIG_KALLSYMS printk("\n");#endif do { /* Bogus frame pointer? */ if (fp < (thread_base + sizeof(struct thread_info)) || fp >= (thread_base + THREAD_SIZE)) break; rw = (struct reg_window *)fp; pc = rw->ins[7]; printk(" [%016lx] ", pc); print_symbol("%s\n", pc); fp = rw->ins[6] + STACK_BIAS; } while (++count < 16);#ifndef CONFIG_KALLSYMS printk("\n");#endif}void dump_stack(void){ unsigned long *ksp; __asm__ __volatile__("mov %%fp, %0" : "=r" (ksp)); show_stack(current, ksp);}EXPORT_SYMBOL(dump_stack);static inline int is_kernel_stack(struct task_struct *task, struct reg_window *rw){ unsigned long rw_addr = (unsigned long) rw; unsigned long thread_base, thread_end; if (rw_addr < PAGE_OFFSET) { if (task != &init_task) return 0; } thread_base = (unsigned long) task->thread_info; thread_end = thread_base + sizeof(union thread_union); if (rw_addr >= thread_base && rw_addr < thread_end && !(rw_addr & 0x7UL)) return 1; return 0;}static inline struct reg_window *kernel_stack_up(struct reg_window *rw){ unsigned long fp = rw->ins[6]; if (!fp) return NULL; return (struct reg_window *) (fp + STACK_BIAS);}void die_if_kernel(char *str, struct pt_regs *regs){ static int die_counter; extern void __show_regs(struct pt_regs * regs); extern void smp_report_regs(void); int count = 0; /* Amuse the user. */ printk(" \\|/ ____ \\|/\n"" \"@'/ .. \\`@\"\n"" /_| \\__/ |_\\\n"" \\__U_/\n"); printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter); notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV); __asm__ __volatile__("flushw"); __show_regs(regs); if (regs->tstate & TSTATE_PRIV) { struct reg_window *rw = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS); /* Stop the back trace when we hit userland or we * find some badly aligned kernel stack. */ while (rw && count++ < 30&& is_kernel_stack(current, rw)) { printk("Caller[%016lx]", rw->ins[7]); print_symbol(": %s", rw->ins[7]); printk("\n"); rw = kernel_stack_up(rw); } instruction_dump ((unsigned int *) regs->tpc); } else { if (test_thread_flag(TIF_32BIT)) { regs->tpc &= 0xffffffff; regs->tnpc &= 0xffffffff; } user_instruction_dump ((unsigned int __user *) regs->tpc); }#ifdef CONFIG_SMP smp_report_regs();#endif if (regs->tstate & TSTATE_PRIV) do_exit(SIGKILL); do_exit(SIGSEGV);}extern int handle_popc(u32 insn, struct pt_regs *regs);extern int handle_ldf_stq(u32 insn, struct pt_regs *regs);void do_illegal_instruction(struct pt_regs *regs){ unsigned long pc = regs->tpc; unsigned long tstate = regs->tstate; u32 insn; siginfo_t info; if (notify_die(DIE_TRAP, "illegal instruction", regs, 0, 0x10, SIGILL) == NOTIFY_STOP) return; if (tstate & TSTATE_PRIV) die_if_kernel("Kernel illegal instruction", regs); if (test_thread_flag(TIF_32BIT)) pc = (u32)pc; if (get_user(insn, (u32 __user *) pc) != -EFAULT) { if ((insn & 0xc1ffc000) == 0x81700000) /* POPC */ { if (handle_popc(insn, regs)) return; } else if ((insn & 0xc1580000) == 0xc1100000) /* LDQ/STQ */ { if (handle_ldf_stq(insn, regs)) return; } } info.si_signo = SIGILL; info.si_errno = 0; info.si_code = ILL_ILLOPC; info.si_addr = (void __user *)pc; info.si_trapno = 0; force_sig_info(SIGILL, &info, current);}void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr){ siginfo_t info; if (notify_die(DIE_TRAP, "memory address unaligned", regs, 0, 0x34, SIGSEGV) == NOTIFY_STOP) return; if (regs->tstate & TSTATE_PRIV) { extern void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, unsigned long sfar, unsigned long sfsr); kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc), sfar, sfsr); return; } info.si_signo = SIGBUS; info.si_errno = 0; info.si_code = BUS_ADRALN; info.si_addr = (void __user *)sfar; info.si_trapno = 0; force_sig_info(SIGBUS, &info, current);}void do_privop(struct pt_regs *regs){ siginfo_t info; if (notify_die(DIE_TRAP, "privileged operation", regs, 0, 0x11, SIGILL) == NOTIFY_STOP) return; if (test_thread_flag(TIF_32BIT)) { regs->tpc &= 0xffffffff; regs->tnpc &= 0xffffffff; } info.si_signo = SIGILL; info.si_errno = 0; info.si_code = ILL_PRVOPC; info.si_addr = (void __user *)regs->tpc; info.si_trapno = 0; force_sig_info(SIGILL, &info, current);}void do_privact(struct pt_regs *regs){ do_privop(regs);}/* Trap level 1 stuff or other traps we should never see... */void do_cee(struct pt_regs *regs){ die_if_kernel("TL0: Cache Error Exception", regs);}void do_cee_tl1(struct pt_regs *regs){ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); die_if_kernel("TL1: Cache Error Exception", regs);}void do_dae_tl1(struct pt_regs *regs){ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); die_if_kernel("TL1: Data Access Exception", regs);}void do_iae_tl1(struct pt_regs *regs){ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); die_if_kernel("TL1: Instruction Access Exception", regs);}void do_div0_tl1(struct pt_regs *regs){ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); die_if_kernel("TL1: DIV0 Exception", regs);}void do_fpdis_tl1(struct pt_regs *regs){ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); die_if_kernel("TL1: FPU Disabled", regs);}void do_fpieee_tl1(struct pt_regs *regs){ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); die_if_kernel("TL1: FPU IEEE Exception", regs);}void do_fpother_tl1(struct pt_regs *regs){ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); die_if_kernel("TL1: FPU Other Exception", regs);}void do_ill_tl1(struct pt_regs *regs){ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); die_if_kernel("TL1: Illegal Instruction Exception", regs);}void do_irq_tl1(struct pt_regs *regs){ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); die_if_kernel("TL1: IRQ Exception", regs);}void do_lddfmna_tl1(struct pt_regs *regs){ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); die_if_kernel("TL1: LDDF Exception", regs);}void do_stdfmna_tl1(struct pt_regs *regs){ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); die_if_kernel("TL1: STDF Exception", regs);}void do_paw(struct pt_regs *regs){ die_if_kernel("TL0: Phys Watchpoint Exception", regs);}void do_paw_tl1(struct pt_regs *regs){ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); die_if_kernel("TL1: Phys Watchpoint Exception", regs);}void do_vaw(struct pt_regs *regs){ die_if_kernel("TL0: Virt Watchpoint Exception", regs);}void do_vaw_tl1(struct pt_regs *regs){ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); die_if_kernel("TL1: Virt Watchpoint Exception", regs);}void do_tof_tl1(struct pt_regs *regs){ dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); die_if_kernel("TL1: Tag Overflow Exception", regs);}void do_getpsr(struct pt_regs *regs){ regs->u_regs[UREG_I0] = tstate_to_psr(regs->tstate); regs->tpc = regs->tnpc; regs->tnpc += 4; if (test_thread_flag(TIF_32BIT)) { regs->tpc &= 0xffffffff; regs->tnpc &= 0xffffffff; }}extern void thread_info_offsets_are_bolixed_dave(void);/* Only invoked on boot processor. */void __init trap_init(void){ /* Compile time sanity check. */ if (TI_TASK != offsetof(struct thread_info, task) || TI_FLAGS != offsetof(struct thread_info, flags) || TI_CPU != offsetof(struct thread_info, cpu) || TI_FPSAVED != offsetof(struct thread_info, fpsaved) || TI_KSP != offsetof(struct thread_info, ksp) || TI_FAULT_ADDR != offsetof(struct thread_info, fault_address) || TI_KREGS != offsetof(struct thread_info, kregs) || TI_UTRAPS != offsetof(struct thread_info, utraps) || TI_EXEC_DOMAIN != offsetof(struct thread_info, exec_domain) || TI_REG_WINDOW != offsetof(struct thread_info, reg_window) || TI_RWIN_SPTRS != offsetof(struct thread_info, rwbuf_stkptrs) || TI_GSR != offsetof(struct thread_info, gsr) || TI_XFSR != offsetof(struct thread_info, xfsr) || TI_USER_CNTD0 != offsetof(struct thread_info, user_cntd0) || TI_USER_CNTD1 != offsetof(struct thread_info, user_cntd1) || TI_KERN_CNTD0 != offsetof(struct thread_info, kernel_cntd0) || TI_KERN_CNTD1 != offsetof(struct thread_info, kernel_cntd1) || TI_PCR != offsetof(struct thread_info, pcr_reg) || TI_CEE_STUFF != offsetof(struct thread_info, cee_stuff) || TI_PRE_COUNT != offsetof(struct thread_info, preempt_count) || TI_NEW_CHILD != offsetof(struct thread_info, new_child) || TI_SYS_NOERROR != offsetof(struct thread_info, syscall_noerror) || TI_RESTART_BLOCK != offsetof(struct thread_info, restart_block) || TI_KUNA_REGS != offsetof(struct thread_info, kern_una_regs) || TI_KUNA_INSN != offsetof(struct thread_info, kern_una_insn) || TI_FPREGS != offsetof(struct thread_info, fpregs) || (TI_FPREGS & (64 - 1))) thread_info_offsets_are_bolixed_dave(); /* Attach to the address space of init_task. On SMP we * do this in smp.c:smp_callin for other cpus. */ atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -