traps.c

来自「linux 内核源代码」· C语言 代码 · 共 832 行 · 第 1/2 页

C
832
字号
		CHK_DEBUGGER_TRAP();		break;	/* 0x2F - Reserved, Caught by default */	/* 0x30 - Reserved, Caught by default */	/* 0x31 - Reserved, Caught by default */	/* 0x32 - Reserved, Caught by default */	/* 0x33 - Reserved, Caught by default */	/* 0x34 - Reserved, Caught by default */	/* 0x35 - Reserved, Caught by default */	/* 0x36 - Reserved, Caught by default */	/* 0x37 - Reserved, Caught by default */	/* 0x38 - Reserved, Caught by default */	/* 0x39 - Reserved, Caught by default */	/* 0x3A - Reserved, Caught by default */	/* 0x3B - Reserved, Caught by default */	/* 0x3C - Reserved, Caught by default */	/* 0x3D - Reserved, Caught by default */	/* 0x3E - Reserved, Caught by default */	/* 0x3F - Reserved, Caught by default */	default:		info.si_code = TRAP_ILLTRAP;		sig = SIGTRAP;		printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",			(fp->seqstat & SEQSTAT_EXCAUSE));		CHK_DEBUGGER_TRAP();		break;	}	BUG_ON(sig == 0);	if (sig != SIGTRAP) {		unsigned long stack;		dump_bfin_process(fp);		dump_bfin_mem((void *)fp->retx);		show_regs(fp);		/* Print out the trace buffer if it makes sense */#ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE		if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M)			printk(KERN_NOTICE "No trace since you do not have "				"CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n"				KERN_NOTICE "\n");		else#endif			dump_bfin_trace_buffer();		show_stack(current, &stack);		if (oops_in_progress) {#ifndef CONFIG_ACCESS_CHECK			printk(KERN_EMERG "Please turn on "			       "CONFIG_ACCESS_CHECK\n");#endif			panic("Kernel exception");		}	}	info.si_signo = sig;	info.si_errno = 0;	info.si_addr = (void *)fp->pc;	force_sig_info(sig, &info, current);	/* Ensure that bad return addresses don't end up in an infinite	 * loop, due to speculative loads/reads. This needs to be done after	 * the signal has been sent.	 */	if (trapnr == VEC_CPLB_I_M && sig != SIGTRAP)		fp->pc = SAFE_USER_INSTRUCTION;	trace_buffer_restore(j);	return;}/* Typical exception handling routines	*/#define EXPAND_LEN ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 256 - 1)void dump_bfin_trace_buffer(void){#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON	int tflags, i = 0;	char buf[150];#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND	int j, index;#endif	trace_buffer_save(tflags);	printk(KERN_NOTICE "Hardware Trace:\n");	if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) {		for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) {			decode_address(buf, (unsigned long)bfin_read_TBUF());			printk(KERN_NOTICE "%4i Target : %s\n", i, buf);			decode_address(buf, (unsigned long)bfin_read_TBUF());			printk(KERN_NOTICE "     Source : %s\n", buf);		}	}#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND	if (trace_buff_offset)		index = trace_buff_offset/4 - 1;	else		index = EXPAND_LEN;	j = (1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 128;	while (j) {		decode_address(buf, software_trace_buff[index]);		printk(KERN_NOTICE "%4i Target : %s\n", i, buf);		index -= 1;		if (index < 0 )			index = EXPAND_LEN;		decode_address(buf, software_trace_buff[index]);		printk(KERN_NOTICE "     Source : %s\n", buf);		index -= 1;		if (index < 0)			index = EXPAND_LEN;		j--;		i++;	}#endif	trace_buffer_restore(tflags);#endif}EXPORT_SYMBOL(dump_bfin_trace_buffer);static void show_trace(struct task_struct *tsk, unsigned long *sp){	unsigned long addr;	printk(KERN_NOTICE "\n" KERN_NOTICE "Call Trace:\n");	while (!kstack_end(sp)) {		addr = *sp++;		/*		 * If the address is either in the text segment of the		 * kernel, or in the region which contains vmalloc'ed		 * memory, it *may* be the address of a calling		 * routine; if so, print it so that someone tracing		 * down the cause of the crash will be able to figure		 * out the call path that was taken.		 */		if (kernel_text_address(addr))			print_ip_sym(addr);	}	printk(KERN_NOTICE "\n");}void show_stack(struct task_struct *task, unsigned long *stack){	unsigned long *endstack, addr;	int i;	/* Cannot call dump_bfin_trace_buffer() here as show_stack() is	 * called externally in some places in the kernel.	 */	if (!stack) {		if (task)			stack = (unsigned long *)task->thread.ksp;		else			stack = (unsigned long *)&stack;	}	addr = (unsigned long)stack;	endstack = (unsigned long *)PAGE_ALIGN(addr);	printk(KERN_NOTICE "Stack from %08lx:", (unsigned long)stack);	for (i = 0; i < kstack_depth_to_print; i++) {		if (stack + 1 > endstack)			break;		if (i % 8 == 0)			printk("\n" KERN_NOTICE "       ");		printk(" %08lx", *stack++);	}	printk("\n");	show_trace(task, stack);}void dump_stack(void){	unsigned long stack;#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON	int tflags;#endif	trace_buffer_save(tflags);	dump_bfin_trace_buffer();	show_stack(current, &stack);	trace_buffer_restore(tflags);}EXPORT_SYMBOL(dump_stack);void dump_bfin_process(struct pt_regs *fp){	/* We should be able to look at fp->ipend, but we don't push it on the	 * stack all the time, so do this until we fix that */	unsigned int context = bfin_read_IPEND();	if (oops_in_progress)		printk(KERN_EMERG "Kernel OOPS in progress\n");	if (context & 0x0020)		printk(KERN_NOTICE "Deferred excecption or HW Error context\n");	else if (context & 0x3FC0)		printk(KERN_NOTICE "Interrupt context\n");	else if (context & 0x4000)		printk(KERN_NOTICE "Deferred Interrupt context\n");	else if (context & 0x8000)		printk(KERN_NOTICE "Kernel process context\n");	if (current->pid && current->mm) {		printk(KERN_NOTICE "CURRENT PROCESS:\n");		printk(KERN_NOTICE "COMM=%s PID=%d\n",			current->comm, current->pid);		printk(KERN_NOTICE "TEXT = 0x%p-0x%p  DATA = 0x%p-0x%p\n"			KERN_NOTICE "BSS = 0x%p-0x%p   USER-STACK = 0x%p\n"			KERN_NOTICE "\n",			(void *)current->mm->start_code,			(void *)current->mm->end_code,			(void *)current->mm->start_data,			(void *)current->mm->end_data,			(void *)current->mm->end_data,			(void *)current->mm->brk,			(void *)current->mm->start_stack);	} else		printk(KERN_NOTICE "\n" KERN_NOTICE		     "No Valid process in current context\n");}void dump_bfin_mem(void *retaddr){	if (retaddr >= (void *)FIXED_CODE_START  && retaddr < (void *)physical_mem_end#if L1_CODE_LENGTH != 0	    /* FIXME: Copy the code out of L1 Instruction SRAM through dma	       memcpy.  */	    && !(retaddr >= (void *)L1_CODE_START	         && retaddr < (void *)(L1_CODE_START + L1_CODE_LENGTH))#endif	) {		int i = ((unsigned int)retaddr & 0xFFFFFFF0) - 32;		unsigned short x = 0;		printk(KERN_NOTICE "return address: [0x%p]; contents of:", retaddr);		for (; i < ((unsigned int)retaddr & 0xFFFFFFF0) + 32; i += 2) {			if (!(i & 0xF))				printk("\n" KERN_NOTICE "0x%08x: ", i);			if (get_user(x, (unsigned short *)i))				break;#ifndef CONFIG_DEBUG_HWERR			/* If one of the last few instructions was a STI			 * it is likely that the error occured awhile ago			 * and we just noticed. This only happens in kernel			 * context, which should mean an oops is happening			 */			if (oops_in_progress && x >= 0x0040 && x <= 0x0047 && i <= 0)				panic("\n\nWARNING : You should reconfigure"					" the kernel to turn on\n"					" 'Hardware error interrupt"					" debugging'\n"					" The rest of this error"					" is meanless\n");#endif			if (i == (unsigned int)retaddr)				printk("[%04x]", x);			else				printk(" %04x ", x);		}		printk("\n");	} else		printk("\n" KERN_NOTICE			"Cannot look at the [PC] <%p> for it is"			" in unreadable memory - sorry\n", retaddr);}void show_regs(struct pt_regs *fp){	char buf [150];	printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\n");	printk(KERN_NOTICE " SEQSTAT: %08lx  IPEND: %04lx  SYSCFG: %04lx\n",		(long)fp->seqstat, fp->ipend, fp->syscfg);	decode_address(buf, fp->rete);	printk(KERN_NOTICE " RETE: %s\n", buf);	decode_address(buf, fp->retn);	printk(KERN_NOTICE " RETN: %s\n", buf);	decode_address(buf, fp->retx);	printk(KERN_NOTICE " RETX: %s\n", buf);	decode_address(buf, fp->rets);	printk(KERN_NOTICE " RETS: %s\n", buf);	decode_address(buf, fp->pc);	printk(KERN_NOTICE " PC: %s\n", buf);	if ((long)fp->seqstat & SEQSTAT_EXCAUSE) {		decode_address(buf, bfin_read_DCPLB_FAULT_ADDR());		printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);		decode_address(buf, bfin_read_ICPLB_FAULT_ADDR());		printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);	}	printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n");	printk(KERN_NOTICE " R0 : %08lx    R1 : %08lx    R2 : %08lx    R3 : %08lx\n",		fp->r0, fp->r1, fp->r2, fp->r3);	printk(KERN_NOTICE " R4 : %08lx    R5 : %08lx    R6 : %08lx    R7 : %08lx\n",		fp->r4, fp->r5, fp->r6, fp->r7);	printk(KERN_NOTICE " P0 : %08lx    P1 : %08lx    P2 : %08lx    P3 : %08lx\n",		fp->p0, fp->p1, fp->p2, fp->p3);	printk(KERN_NOTICE " P4 : %08lx    P5 : %08lx    FP : %08lx    SP : %08lx\n",		fp->p4, fp->p5, fp->fp, (long)fp);	printk(KERN_NOTICE " LB0: %08lx    LT0: %08lx    LC0: %08lx\n",		fp->lb0, fp->lt0, fp->lc0);	printk(KERN_NOTICE " LB1: %08lx    LT1: %08lx    LC1: %08lx\n",		fp->lb1, fp->lt1, fp->lc1);	printk(KERN_NOTICE " B0 : %08lx    L0 : %08lx    M0 : %08lx    I0 : %08lx\n",		fp->b0, fp->l0, fp->m0, fp->i0);	printk(KERN_NOTICE " B1 : %08lx    L1 : %08lx    M1 : %08lx    I1 : %08lx\n",		fp->b1, fp->l1, fp->m1, fp->i1);	printk(KERN_NOTICE " B2 : %08lx    L2 : %08lx    M2 : %08lx    I2 : %08lx\n",		fp->b2, fp->l2, fp->m2, fp->i2);	printk(KERN_NOTICE " B3 : %08lx    L3 : %08lx    M3 : %08lx    I3 : %08lx\n",		fp->b3, fp->l3, fp->m3, fp->i3);	printk(KERN_NOTICE "A0.w: %08lx   A0.x: %08lx   A1.w: %08lx   A1.x: %08lx\n",		fp->a0w, fp->a0x, fp->a1w, fp->a1x);	printk(KERN_NOTICE "USP : %08lx  ASTAT: %08lx\n",		rdusp(), fp->astat);	printk(KERN_NOTICE "\n");}#ifdef CONFIG_SYS_BFIN_SPINLOCK_L1asmlinkage int sys_bfin_spinlock(int *spinlock)__attribute__((l1_text));#endifasmlinkage int sys_bfin_spinlock(int *spinlock){	int ret = 0;	int tmp = 0;	local_irq_disable();	ret = get_user(tmp, spinlock);	if (ret == 0) {		if (tmp)			ret = 1;		tmp = 1;		put_user(tmp, spinlock);	}	local_irq_enable();	return ret;}int bfin_request_exception(unsigned int exception, void (*handler)(void)){	void (*curr_handler)(void);	if (exception > 0x3F)		return -EINVAL;	curr_handler = ex_table[exception];	if (curr_handler != ex_replaceable)		return -EBUSY;	ex_table[exception] = handler;	return 0;}EXPORT_SYMBOL(bfin_request_exception);int bfin_free_exception(unsigned int exception, void (*handler)(void)){	void (*curr_handler)(void);	if (exception > 0x3F)		return -EINVAL;	curr_handler = ex_table[exception];	if (curr_handler != handler)		return -EBUSY;	ex_table[exception] = ex_replaceable;	return 0;}EXPORT_SYMBOL(bfin_free_exception);void panic_cplb_error(int cplb_panic, struct pt_regs *fp){	switch (cplb_panic) {	case CPLB_NO_UNLOCKED:		printk(KERN_EMERG "All CPLBs are locked\n");		break;	case CPLB_PROT_VIOL:		return;	case CPLB_NO_ADDR_MATCH:		return;	case CPLB_UNKNOWN_ERR:		printk(KERN_EMERG "Unknown CPLB Exception\n");		break;	}	oops_in_progress = 1;	printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR());	printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR());	dump_bfin_process(fp);	dump_bfin_mem((void *)fp->retx);	show_regs(fp);	dump_stack();	panic("Unrecoverable event\n");}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?