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

📄 traps.c

📁 linux-2.6.15.6
💻 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 <linux/kallsyms.h>#include <asm/assembly.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 <asm/unwind.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)          */#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)DEFINE_SPINLOCK(pa_dbit_lock);#endifint 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"#endifvoid show_regs(struct pt_regs *regs){	int i;	char buf[128], *p;	char *level;	unsigned long cr30;	unsigned long cr31;	/* carlos says that gcc understands better memory in a struct,	 * and it makes our life easier with fpregs -- T-Bone */	struct { u32 sw[2]; } s;		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);	}	/* FR are 64bit everywhere. Need to use asm to get the content	 * of fpsr/fper1, and we assume that we won't have a FP Identify	 * in our way, otherwise we're screwed.	 * The fldd is used to restore the T-bit if there was one, as the	 * store clears it anyway.	 * BTW, PA2.0 book says "thou shall not use fstw on FPSR/FPERs". */ 	__asm__ (		"fstd %%fr0,0(%1)	\n\t"		"fldd 0(%1),%%fr0	\n\t"		: "=m" (s) : "r" (&s) : "%r0"		);	printk("%s\n", level);	printk("%s      VZOUICununcqcqcqcqcqcrmunTDVZOUI\n", level);	printbinary(buf, s.sw[0], 32);	printk("%sFPSR: %s\n", level, buf);	printk("%sFPER1: %08x\n", level, s.sw[1]);	/* here we'll print fr0 again, tho it'll be meaningless */	for (i = 0; i < 32; i += 4) {		int j;		p = buf;		p += sprintf(p, "%sfr%02d-%02d ", level, i, i + 3);		for (j = 0; j < 4; j++)			p += sprintf(p, " %016llx", (i+j) == 0 ? 0 : regs->fr[i+j]);		printk("%s\n", buf);	}	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, current_thread_info()->cpu, cr30, cr31);	printk("%s ORIG_R28: " RFMT "\n", level, regs->orig_r28);	printk(level);	print_symbol(" IAOQ[0]: %s\n", regs->iaoq[0]);	printk(level);	print_symbol(" IAOQ[1]: %s\n", regs->iaoq[1]);	printk(level);	print_symbol(" RP(r2): %s\n", regs->gr[2]);}void dump_stack(void){	show_stack(NULL, NULL);}EXPORT_SYMBOL(dump_stack);static void do_show_stack(struct unwind_frame_info *info){	int i = 1;	printk("Backtrace:\n");	while (i <= 16) {		if (unwind_once(info) < 0 || info->ip == 0)			break;		if (__kernel_text_address(info->ip)) {			printk(" [<" RFMT ">] ", info->ip);#ifdef CONFIG_KALLSYMS			print_symbol("%s\n", info->ip);#else			if ((i & 0x03) == 0)				printk("\n");#endif			i++;		}	}	printk("\n");}void show_stack(struct task_struct *task, unsigned long *s){	struct unwind_frame_info info;	if (!task) {		unsigned long sp;		struct pt_regs *r;HERE:		asm volatile ("copy %%r30, %0" : "=r"(sp));		r = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL);		if (!r)			return;		memset(r, 0, sizeof(struct pt_regs));		r->iaoq[0] = (unsigned long)&&HERE;		r->gr[2] = (unsigned long)__builtin_return_address(0);		r->gr[30] = sp;		unwind_frame_init(&info, current, r);		kfree(r);	} else {		unwind_frame_init_from_blocked_task(&info, task);	}	do_show_stack(&info);}void die_if_kernel(char *str, struct pt_regs *regs, long err){	if (user_mode(regs)) {		if (err == 0)			return; /* STFU */		printk(KERN_CRIT "%s (pid %d): %s (code %ld) at " RFMT "\n",			current->comm, current->pid, str, err, regs->iaoq[0]);#ifdef PRINT_USER_FAULTS		/* XXX for debugging only */		show_regs(regs);#endif		return;	}	oops_in_progress = 1;	/* Amuse the user in a SPARC fashion */	printk("      _______________________________ \n""     < Your System ate a SPARC! Gah! >\n""      ------------------------------- \n""             \\   ^__^\n""              \\  (xx)\\_______\n""                 (__)\\       )\\/\\\n""                  U  ||----w |\n""                     ||     ||\n");		/* 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__);		local_irq_enable();		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 __user *) (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 __user *) (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 __user *) (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;}/* * This routine is called as a last resort when everything else * has gone clearly wrong. We get called for faults in kernel space, * and HPMC's. */void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset){	static DEFINE_SPINLOCK(terminate_lock);	oops_in_progress = 1;	set_eiem(0);	local_irq_disable();	spin_lock(&terminate_lock);	/* unlock the pdc lock if necessary */	pdc_emergency_unlock();

⌨️ 快捷键说明

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