traps.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 640 行 · 第 1/2 页
C
640 行
unsigned long fpscr; flush_fp_to_thread(current); fpscr = current->thread.fpscr; /* Invalid operation */ if ((fpscr & FPSCR_VE) && (fpscr & FPSCR_VX)) code = FPE_FLTINV; /* Overflow */ else if ((fpscr & FPSCR_OE) && (fpscr & FPSCR_OX)) code = FPE_FLTOVF; /* Underflow */ else if ((fpscr & FPSCR_UE) && (fpscr & FPSCR_UX)) code = FPE_FLTUND; /* Divide by zero */ else if ((fpscr & FPSCR_ZE) && (fpscr & FPSCR_ZX)) code = FPE_FLTDIV; /* Inexact result */ else if ((fpscr & FPSCR_XE) && (fpscr & FPSCR_XX)) code = FPE_FLTRES; _exception(SIGFPE, regs, code, regs->nip);}/* * Illegal instruction emulation support. Return non-zero if we can't * emulate, or -EFAULT if the associated memory access caused an access * fault. Return zero on success. */#define INST_DCBA 0x7c0005ec#define INST_DCBA_MASK 0x7c0007fe#define INST_MCRXR 0x7c000400#define INST_MCRXR_MASK 0x7c0007festatic int emulate_instruction(struct pt_regs *regs){ unsigned int instword; if (!user_mode(regs)) return -EINVAL; CHECK_FULL_REGS(regs); if (get_user(instword, (unsigned int __user *)(regs->nip))) return -EFAULT; /* Emulating the dcba insn is just a no-op. */ if ((instword & INST_DCBA_MASK) == INST_DCBA) { static int warned; if (!warned) { printk(KERN_WARNING "process %d (%s) uses obsolete 'dcba' insn\n", current->pid, current->comm); warned = 1; } return 0; } /* Emulate the mcrxr insn. */ if ((instword & INST_MCRXR_MASK) == INST_MCRXR) { static int warned; unsigned int shift; if (!warned) { printk(KERN_WARNING "process %d (%s) uses obsolete 'mcrxr' insn\n", current->pid, current->comm); warned = 1; } shift = (instword >> 21) & 0x1c; regs->ccr &= ~(0xf0000000 >> shift); regs->ccr |= (regs->xer & 0xf0000000) >> shift; regs->xer &= ~0xf0000000; return 0; } return -EINVAL;}/* * Look through the list of trap instructions that are used for BUG(), * BUG_ON() and WARN_ON() and see if we hit one. At this point we know * that the exception was caused by a trap instruction of some kind. * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0 * otherwise. */extern struct bug_entry __start___bug_table[], __stop___bug_table[];#ifndef CONFIG_MODULES#define module_find_bug(x) NULL#endifstatic struct bug_entry *find_bug(unsigned long bugaddr){ struct bug_entry *bug; for (bug = __start___bug_table; bug < __stop___bug_table; ++bug) if (bugaddr == bug->bug_addr) return bug; return module_find_bug(bugaddr);}intcheck_bug_trap(struct pt_regs *regs){ struct bug_entry *bug; unsigned long addr; if (regs->msr & MSR_PR) return 0; /* not in kernel */ addr = regs->nip; /* address of trap instruction */ if (addr < PAGE_OFFSET) return 0; bug = find_bug(regs->nip); if (bug == NULL) return 0; if (bug->line & BUG_WARNING_TRAP) { /* this is a WARN_ON rather than BUG/BUG_ON */ printk(KERN_ERR "Badness in %s at %s:%d\n", bug->function, bug->file, (unsigned int)bug->line & ~BUG_WARNING_TRAP); show_stack(current, (void *)regs->gpr[1]); return 1; } printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n", bug->function, bug->file, (unsigned int)bug->line); return 0;}voidProgramCheckException(struct pt_regs *regs){ if (regs->msr & 0x100000) { /* IEEE FP exception */ parse_fpe(regs); } else if (regs->msr & 0x40000) { /* Privileged instruction */ _exception(SIGILL, regs, ILL_PRVOPC, regs->nip); } else if (regs->msr & 0x20000) { /* trap exception */ if (debugger_bpt(regs)) return; if (check_bug_trap(regs)) { regs->nip += 4; return; } _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); } else { /* Illegal instruction; try to emulate it. */ switch (emulate_instruction(regs)) { case 0: regs->nip += 4; emulate_single_step(regs); break; case -EFAULT: _exception(SIGSEGV, regs, SEGV_MAPERR, regs->nip); break; default: _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); break; } }}void KernelFPUnavailableException(struct pt_regs *regs){ printk(KERN_EMERG "Unrecoverable FP Unavailable Exception " "%lx at %lx\n", regs->trap, regs->nip); die("Unrecoverable FP Unavailable Exception", regs, SIGABRT);}void AltivecUnavailableException(struct pt_regs *regs){#ifndef CONFIG_ALTIVEC if (user_mode(regs)) { /* A user program has executed an altivec instruction, but this kernel doesn't support altivec. */ _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); return; }#endif printk(KERN_EMERG "Unrecoverable VMX/Altivec Unavailable Exception " "%lx at %lx\n", regs->trap, regs->nip); die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);}/* Ensure exceptions are disabled */#define MMCR0_PMXE (1UL << (31 - 5))#define MMCR0_PMAO (1UL << (31 - 24))static void dummy_perf(struct pt_regs *regs){ unsigned int mmcr0 = mfspr(SPRN_MMCR0); mmcr0 &= ~(MMCR0_PMXE|MMCR0_PMAO); mtspr(SPRN_MMCR0, mmcr0);}void (*perf_irq)(struct pt_regs *) = dummy_perf;EXPORT_SYMBOL(perf_irq);voidPerformanceMonitorException(struct pt_regs *regs){ perf_irq(regs);}voidAlignmentException(struct pt_regs *regs){ int fixed; fixed = fix_alignment(regs); if (fixed == 1) { regs->nip += 4; /* skip over emulated instruction */ emulate_single_step(regs); return; } /* Operand address was bad */ if (fixed == -EFAULT) { if (user_mode(regs)) { _exception(SIGSEGV, regs, SEGV_MAPERR, regs->dar); } else { /* Search exception table */ bad_page_fault(regs, regs->dar, SIGSEGV); } return; } _exception(SIGBUS, regs, BUS_ADRALN, regs->nip);}#ifdef CONFIG_ALTIVECvoidAltivecAssistException(struct pt_regs *regs){ int err; siginfo_t info; if (!user_mode(regs)) { printk(KERN_EMERG "VMX/Altivec assist exception in kernel mode" " at %lx\n", regs->nip); die("Kernel VMX/Altivec assist exception", regs, SIGILL); } flush_altivec_to_thread(current); err = emulate_altivec(regs); if (err == 0) { regs->nip += 4; /* skip emulated instruction */ emulate_single_step(regs); return; } if (err == -EFAULT) { /* got an error reading the instruction */ info.si_signo = SIGSEGV; info.si_errno = 0; info.si_code = SEGV_MAPERR; info.si_addr = (void __user *) regs->nip; force_sig_info(SIGSEGV, &info, current); } else { /* didn't recognize the instruction */ /* XXX quick hack for now: set the non-Java bit in the VSCR */ if (printk_ratelimit()) printk(KERN_ERR "Unrecognized altivec instruction " "in %s at %lx\n", current->comm, regs->nip); current->thread.vscr.u[3] |= 0x10000; }}#endif /* CONFIG_ALTIVEC *//* * We enter here if we get an unrecoverable exception, that is, one * that happened at a point where the RI (recoverable interrupt) bit * in the MSR is 0. This indicates that SRR0/1 are live, and that * we therefore lost state by taking this exception. */void unrecoverable_exception(struct pt_regs *regs){ printk(KERN_EMERG "Unrecoverable exception %lx at %lx\n", regs->trap, regs->nip); die("Unrecoverable exception", regs, SIGABRT);}/* * We enter here if we discover during exception entry that we are * running in supervisor mode with a userspace value in the stack pointer. */void kernel_bad_stack(struct pt_regs *regs){ printk(KERN_EMERG "Bad kernel stack pointer %lx at %lx\n", regs->gpr[1], regs->nip); die("Bad kernel stack pointer", regs, SIGABRT);}void __init trap_init(void){}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?