⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 traps.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/arch/parisc/traps.c * *  Copyright (C) 1991, 1992  Linus Torvalds *  Copyright (C) 1999, 2000  Philipp Rumpf <prumpf@tux.org> *//* * 'Traps.c' handles hardware traps and faults after we have saved some * state in 'asm.s'. */#include <linux/config.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/ptrace.h>#include <linux/timer.h>#include <linux/mm.h>#include <linux/module.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/spinlock.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/console.h>#include <asm/system.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/traps.h>#include <asm/unaligned.h>#include <asm/atomic.h>#include <asm/smp.h>#include <asm/pdc.h>#include <asm/pdc_chassis.h>#include "../math-emu/math-emu.h"	/* for handle_fpe() */#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */			  /*  dumped to the console via printk)          */static int printbinary(char *buf, unsigned long x, int nbits){	unsigned long mask = 1UL << (nbits - 1);	while (mask != 0) {		*buf++ = (mask & x ? '1' : '0');		mask >>= 1;	}	*buf = '\0';	return nbits;}#ifdef __LP64__#define RFMT "%016lx"#else#define RFMT "%08lx"#endifstatic int kstack_depth_to_print = 24;extern struct module *module_list;extern struct module kernel_module;static inline int kernel_text_address(unsigned long addr){#ifdef CONFIG_MODULES	int retval = 0;	struct module *mod;#endif	extern char _stext, _etext;	if (addr >= (unsigned long) &_stext &&	    addr <= (unsigned long) &_etext)		return 1;#ifdef CONFIG_MODULES	for (mod = module_list; mod != &kernel_module; mod = mod->next) {		/* mod_bound tests for addr being inside the vmalloc'ed		 * module area. Of course it'd be better to test only		 * for the .text subset... */		if (mod_bound(addr, 0, mod)) {			retval = 1;			break;		}	}	return retval;#endif}void show_trace(unsigned long * stack){	unsigned long *startstack;	unsigned long addr;	int i;	startstack = (unsigned long *)((unsigned long)stack & ~(THREAD_SIZE - 1));	i = 1;	printk("Kernel addresses on the stack:\n");	while (stack >= startstack) {		addr = *stack--;		if (kernel_text_address(addr)) {			printk(" [<" RFMT ">] ", addr);			if ((i & 0x03) == 0)				printk("\n");			i++;		}	}	printk("\n");}void show_trace_task(struct task_struct *tsk){	show_trace((unsigned long *)tsk->thread.regs.ksp);}void show_stack(unsigned long * sp){	unsigned long *stack;	int i;	/*	 * debugging aid: "show_stack(NULL);" prints the	 * back trace for this cpu.	 */	if (sp==NULL)		sp = (unsigned long*)&sp;	stack = sp;	printk("\n" KERN_CRIT "Stack Dump:\n");	printk(KERN_CRIT " " RFMT ":  ", (unsigned long) stack);	for (i=0; i < kstack_depth_to_print; i++) {		if (((long) stack & (THREAD_SIZE-1)) == 0)			break;		if (i && ((i & 0x03) == 0))			printk("\n" KERN_CRIT " " RFMT ":  ",				(unsigned long) stack);		printk(RFMT " ", *stack--);	}	printk("\n" KERN_CRIT "\n");	show_trace(sp);}/* * The architecture-independent backtrace generator */void dump_stack(void){	show_stack(0);}void show_regs(struct pt_regs *regs){	int i;	char buf[128], *p;	char *level;	unsigned long cr30;	unsigned long cr31;	level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT;	printk("%s\n", level); /* don't want to have that pretty register dump messed up */	printk("%s     YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n", level);	printbinary(buf, regs->gr[0], 32);	printk("%sPSW: %s %s\n", level, buf, print_tainted());	for (i = 0; i < 32; i += 4) {		int j;		p = buf;		p += sprintf(p, "%sr%02d-%02d ", level, i, i + 3);		for (j = 0; j < 4; j++) {			p += sprintf(p, " " RFMT, (i+j) == 0 ? 0 : regs->gr[i + j]);		}		printk("%s\n", buf);	}	for (i = 0; i < 8; i += 4) {		int j;		p = buf;		p += sprintf(p, "%ssr%d-%d  ", level, i, i + 3);		for (j = 0; j < 4; j++) {			p += sprintf(p, " " RFMT, regs->sr[i + j]);		}		printk("%s\n", buf);	}#if RIDICULOUSLY_VERBOSE	for (i = 0; i < 32; i += 2)		printk("%sFR%02d : %016lx  FR%2d : %016lx", level, i,				regs->fr[i], i+1, regs->fr[i+1]);#endif	cr30 = mfctl(30);	cr31 = mfctl(31);	printk("%s\n", level);	printk("%sIASQ: " RFMT " " RFMT " IAOQ: " RFMT " " RFMT "\n",	       level, regs->iasq[0], regs->iasq[1], regs->iaoq[0], regs->iaoq[1]);	printk("%s IIR: %08lx    ISR: " RFMT "  IOR: " RFMT "\n",	       level, regs->iir, regs->isr, regs->ior);	printk("%s CPU: %8d   CR30: " RFMT " CR31: " RFMT "\n",	       level, ((struct task_struct *)cr30)->processor, cr30, cr31);	printk("%s ORIG_R28: " RFMT "\n", level, regs->orig_r28);}void die_if_kernel(char *str, struct pt_regs *regs, long err){	if (user_mode(regs)) {#ifdef PRINT_USER_FAULTS		if (err == 0)			return; /* STFU */		/* XXX for debugging only */		printk(KERN_DEBUG "%s (pid %d): %s (code %ld)\n",			current->comm, current->pid, str, err);		show_regs(regs);#endif		return;	}		/* unlock the pdc lock if necessary */	pdc_emergency_unlock();	/* maybe the kernel hasn't booted very far yet and hasn't been able 	 * to initialize the serial or STI console. In that case we should 	 * re-enable the pdc console, so that the user will be able to 	 * identify the problem. */	if (!console_drivers)		pdc_console_restart();		printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n",		current->comm, current->pid, str, err);	show_regs(regs);	/* Wot's wrong wif bein' racy? */	if (current->thread.flags & PARISC_KERNEL_DEATH) {		printk(KERN_CRIT "%s() recursion detected.\n", __FUNCTION__);		sti();		while (1);	}	current->thread.flags |= PARISC_KERNEL_DEATH;	do_exit(SIGSEGV);}int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs){	return syscall(regs);}/* gdb uses break 4,8 */#define GDB_BREAK_INSN 0x10004void handle_gdb_break(struct pt_regs *regs, int wot){	struct siginfo si;	si.si_code = wot;	si.si_addr = (void *) (regs->iaoq[0] & ~3);	si.si_signo = SIGTRAP;	si.si_errno = 0;	force_sig_info(SIGTRAP, &si, current);}void handle_break(unsigned iir, struct pt_regs *regs){	struct siginfo si;	switch(iir) {	case 0x00:#ifdef PRINT_USER_FAULTS		printk(KERN_DEBUG "break 0,0: pid=%d command='%s'\n",		       current->pid, current->comm);#endif		die_if_kernel("Breakpoint", regs, 0);#ifdef PRINT_USER_FAULTS		show_regs(regs);#endif		si.si_code = TRAP_BRKPT;		si.si_addr = (void *) (regs->iaoq[0] & ~3);		si.si_signo = SIGTRAP;		force_sig_info(SIGTRAP, &si, current);		break;	case GDB_BREAK_INSN:		die_if_kernel("Breakpoint", regs, 0);		handle_gdb_break(regs, TRAP_BRKPT);		break;	default:#ifdef PRINT_USER_FAULTS		printk(KERN_DEBUG "break %#08x: pid=%d command='%s'\n",		       iir, current->pid, current->comm);		show_regs(regs);#endif		si.si_signo = SIGTRAP;		si.si_code = TRAP_BRKPT;		si.si_addr = (void *) (regs->iaoq[0] & ~3);		force_sig_info(SIGTRAP, &si, current);		return;	}}int handle_toc(void){	printk(KERN_CRIT "TOC call.\n");	return 0;}static void default_trap(int code, struct pt_regs *regs){	printk(KERN_ERR "Trap %d on CPU %d\n", code, smp_processor_id());	show_regs(regs);}void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap;void transfer_pim_to_trap_frame(struct pt_regs *regs){    register int i;    extern unsigned int hpmc_pim_data[];    struct pdc_hpmc_pim_11 *pim_narrow;    struct pdc_hpmc_pim_20 *pim_wide;    if (boot_cpu_data.cpu_type >= pcxu) {	pim_wide = (struct pdc_hpmc_pim_20 *)hpmc_pim_data;	/*	 * Note: The following code will probably generate a	 * bunch of truncation error warnings from the compiler.	 * Could be handled with an ifdef, but perhaps there	 * is a better way.	 */	regs->gr[0] = pim_wide->cr[22];	for (i = 1; i < 32; i++)	    regs->gr[i] = pim_wide->gr[i];	for (i = 0; i < 32; i++)	    regs->fr[i] = pim_wide->fr[i];	for (i = 0; i < 8; i++)	    regs->sr[i] = pim_wide->sr[i];	regs->iasq[0] = pim_wide->cr[17];	regs->iasq[1] = pim_wide->iasq_back;	regs->iaoq[0] = pim_wide->cr[18];	regs->iaoq[1] = pim_wide->iaoq_back;	regs->sar  = pim_wide->cr[11];	regs->iir  = pim_wide->cr[19];	regs->isr  = pim_wide->cr[20];	regs->ior  = pim_wide->cr[21];    }    else {	pim_narrow = (struct pdc_hpmc_pim_11 *)hpmc_pim_data;	regs->gr[0] = pim_narrow->cr[22];	for (i = 1; i < 32; i++)	    regs->gr[i] = pim_narrow->gr[i];	for (i = 0; i < 32; i++)	    regs->fr[i] = pim_narrow->fr[i];	for (i = 0; i < 8; i++)	    regs->sr[i] = pim_narrow->sr[i];	regs->iasq[0] = pim_narrow->cr[17];	regs->iasq[1] = pim_narrow->iasq_back;	regs->iaoq[0] = pim_narrow->cr[18];	regs->iaoq[1] = pim_narrow->iaoq_back;	regs->sar  = pim_narrow->cr[11];	regs->iir  = pim_narrow->cr[19];	regs->isr  = pim_narrow->cr[20];	regs->ior  = pim_narrow->cr[21];    }    /*     * The following fields only have meaning if we came through     * another path. So just zero them here.     */    regs->ksp = 0;    regs->kpc = 0;    regs->orig_r28 = 0;}

⌨️ 快捷键说明

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