📄 traps_32.c
字号:
/* * Copyright (C) 1991, 1992 Linus Torvalds * * Pentium III FXSR, SSE support * Gareth Hughes <gareth@valinux.com>, May 2000 *//* * 'Traps.c' handles hardware traps and faults after we have saved some * state in 'asm.s'. */#include <linux/sched.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/timer.h>#include <linux/mm.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/spinlock.h>#include <linux/interrupt.h>#include <linux/highmem.h>#include <linux/kallsyms.h>#include <linux/ptrace.h>#include <linux/utsname.h>#include <linux/kprobes.h>#include <linux/kexec.h>#include <linux/unwind.h>#include <linux/uaccess.h>#include <linux/nmi.h>#include <linux/bug.h>#ifdef CONFIG_EISA#include <linux/ioport.h>#include <linux/eisa.h>#endif#ifdef CONFIG_MCA#include <linux/mca.h>#endif#if defined(CONFIG_EDAC)#include <linux/edac.h>#endif#include <asm/processor.h>#include <asm/system.h>#include <asm/io.h>#include <asm/atomic.h>#include <asm/debugreg.h>#include <asm/desc.h>#include <asm/i387.h>#include <asm/nmi.h>#include <asm/unwind.h>#include <asm/smp.h>#include <asm/arch_hooks.h>#include <linux/kdebug.h>#include <asm/stacktrace.h>#include <linux/module.h>#include "mach_traps.h"int panic_on_unrecovered_nmi;DECLARE_BITMAP(used_vectors, NR_VECTORS);EXPORT_SYMBOL_GPL(used_vectors);asmlinkage int system_call(void);/* Do we ignore FPU interrupts ? */char ignore_fpu_irq = 0;/* * The IDT has to be page-aligned to simplify the Pentium * F0 0F bug workaround.. We have a special link segment * for this. */struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };asmlinkage void divide_error(void);asmlinkage void debug(void);asmlinkage void nmi(void);asmlinkage void int3(void);asmlinkage void overflow(void);asmlinkage void bounds(void);asmlinkage void invalid_op(void);asmlinkage void device_not_available(void);asmlinkage void coprocessor_segment_overrun(void);asmlinkage void invalid_TSS(void);asmlinkage void segment_not_present(void);asmlinkage void stack_segment(void);asmlinkage void general_protection(void);asmlinkage void page_fault(void);asmlinkage void coprocessor_error(void);asmlinkage void simd_coprocessor_error(void);asmlinkage void alignment_check(void);asmlinkage void spurious_interrupt_bug(void);asmlinkage void machine_check(void);int kstack_depth_to_print = 24;static unsigned int code_bytes = 64;static inline int valid_stack_ptr(struct thread_info *tinfo, void *p, unsigned size){ return p > (void *)tinfo && p <= (void *)tinfo + THREAD_SIZE - size;}/* The form of the top of the frame on the stack */struct stack_frame { struct stack_frame *next_frame; unsigned long return_address;};static inline unsigned long print_context_stack(struct thread_info *tinfo, unsigned long *stack, unsigned long ebp, const struct stacktrace_ops *ops, void *data){#ifdef CONFIG_FRAME_POINTER struct stack_frame *frame = (struct stack_frame *)ebp; while (valid_stack_ptr(tinfo, frame, sizeof(*frame))) { struct stack_frame *next; unsigned long addr; addr = frame->return_address; ops->address(data, addr); /* * break out of recursive entries (such as * end_of_stack_stop_unwind_function). Also, * we can never allow a frame pointer to * move downwards! */ next = frame->next_frame; if (next <= frame) break; frame = next; }#else while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) { unsigned long addr; addr = *stack++; if (__kernel_text_address(addr)) ops->address(data, addr); }#endif return ebp;}#define MSG(msg) ops->warning(data, msg)void dump_trace(struct task_struct *task, struct pt_regs *regs, unsigned long *stack, const struct stacktrace_ops *ops, void *data){ unsigned long ebp = 0; if (!task) task = current; if (!stack) { unsigned long dummy; stack = &dummy; if (task != current) stack = (unsigned long *)task->thread.esp; }#ifdef CONFIG_FRAME_POINTER if (!ebp) { if (task == current) { /* Grab ebp right from our regs */ asm ("movl %%ebp, %0" : "=r" (ebp) : ); } else { /* ebp is the last reg pushed by switch_to */ ebp = *(unsigned long *) task->thread.esp; } }#endif while (1) { struct thread_info *context; context = (struct thread_info *) ((unsigned long)stack & (~(THREAD_SIZE - 1))); ebp = print_context_stack(context, stack, ebp, ops, data); /* Should be after the line below, but somewhere in early boot context comes out corrupted and we can't reference it -AK */ if (ops->stack(data, "IRQ") < 0) break; stack = (unsigned long*)context->previous_esp; if (!stack) break; touch_nmi_watchdog(); }}EXPORT_SYMBOL(dump_trace);static voidprint_trace_warning_symbol(void *data, char *msg, unsigned long symbol){ printk(data); print_symbol(msg, symbol); printk("\n");}static void print_trace_warning(void *data, char *msg){ printk("%s%s\n", (char *)data, msg);}static int print_trace_stack(void *data, char *name){ return 0;}/* * Print one address/symbol entries per line. */static void print_trace_address(void *data, unsigned long addr){ printk("%s [<%08lx>] ", (char *)data, addr); print_symbol("%s\n", addr); touch_nmi_watchdog();}static const struct stacktrace_ops print_trace_ops = { .warning = print_trace_warning, .warning_symbol = print_trace_warning_symbol, .stack = print_trace_stack, .address = print_trace_address,};static voidshow_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, unsigned long * stack, char *log_lvl){ dump_trace(task, regs, stack, &print_trace_ops, log_lvl); printk("%s =======================\n", log_lvl);}void show_trace(struct task_struct *task, struct pt_regs *regs, unsigned long * stack){ show_trace_log_lvl(task, regs, stack, "");}static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, unsigned long *esp, char *log_lvl){ unsigned long *stack; int i; if (esp == NULL) { if (task) esp = (unsigned long*)task->thread.esp; else esp = (unsigned long *)&esp; } stack = esp; for(i = 0; i < kstack_depth_to_print; i++) { if (kstack_end(stack)) break; if (i && ((i % 8) == 0)) printk("\n%s ", log_lvl); printk("%08lx ", *stack++); } printk("\n%sCall Trace:\n", log_lvl); show_trace_log_lvl(task, regs, esp, log_lvl);}void show_stack(struct task_struct *task, unsigned long *esp){ printk(" "); show_stack_log_lvl(task, NULL, esp, "");}/* * The architecture-independent dump_stack generator */void dump_stack(void){ unsigned long stack; printk("Pid: %d, comm: %.20s %s %s %.*s\n", current->pid, current->comm, print_tainted(), init_utsname()->release, (int)strcspn(init_utsname()->version, " "), init_utsname()->version); show_trace(current, NULL, &stack);}EXPORT_SYMBOL(dump_stack);void show_registers(struct pt_regs *regs){ int i; print_modules(); __show_registers(regs, 0); printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)", TASK_COMM_LEN, current->comm, task_pid_nr(current), current_thread_info(), current, task_thread_info(current)); /* * When in-kernel, we also print out the stack and code at the * time of the fault.. */ if (!user_mode_vm(regs)) { u8 *eip; unsigned int code_prologue = code_bytes * 43 / 64; unsigned int code_len = code_bytes; unsigned char c; printk("\n" KERN_EMERG "Stack: "); show_stack_log_lvl(NULL, regs, ®s->esp, KERN_EMERG); printk(KERN_EMERG "Code: "); eip = (u8 *)regs->eip - code_prologue; if (eip < (u8 *)PAGE_OFFSET || probe_kernel_address(eip, c)) { /* try starting at EIP */ eip = (u8 *)regs->eip; code_len = code_len - code_prologue + 1; } for (i = 0; i < code_len; i++, eip++) { if (eip < (u8 *)PAGE_OFFSET || probe_kernel_address(eip, c)) { printk(" Bad EIP value."); break; } if (eip == (u8 *)regs->eip) printk("<%02x> ", c); else printk("%02x ", c); } } printk("\n");} int is_valid_bugaddr(unsigned long eip){ unsigned short ud2; if (eip < PAGE_OFFSET) return 0; if (probe_kernel_address((unsigned short *)eip, ud2)) return 0; return ud2 == 0x0b0f;}/* * This is gone through when something in the kernel has done something bad and * is about to be terminated. */void die(const char * str, struct pt_regs * regs, long err){ static struct { raw_spinlock_t lock; u32 lock_owner; int lock_owner_depth; } die = { .lock = __RAW_SPIN_LOCK_UNLOCKED, .lock_owner = -1, .lock_owner_depth = 0 }; static int die_counter; unsigned long flags; oops_enter(); if (die.lock_owner != raw_smp_processor_id()) { console_verbose(); raw_local_irq_save(flags); __raw_spin_lock(&die.lock); die.lock_owner = smp_processor_id(); die.lock_owner_depth = 0; bust_spinlocks(1); } else raw_local_irq_save(flags); if (++die.lock_owner_depth < 3) { unsigned long esp; unsigned short ss; report_bug(regs->eip, regs); printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);#ifdef CONFIG_PREEMPT printk("PREEMPT ");#endif#ifdef CONFIG_SMP printk("SMP ");#endif#ifdef CONFIG_DEBUG_PAGEALLOC printk("DEBUG_PAGEALLOC");#endif printk("\n"); if (notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV) != NOTIFY_STOP) { show_registers(regs); /* Executive summary in case the oops scrolled away */ esp = (unsigned long) (®s->esp); savesegment(ss, ss);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -