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

📄 traps.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
			       "r" (physaddr), "i" (ASI_PHYS_USE_EC));	/* Did that trigger another error? */	if (cheetah_recheck_errors(NULL)) {		/* Try one more time. */		__asm__ __volatile__("ldxa [%0] %1, %%g0\n\t"				     "membar #Sync"				     : : "r" (physaddr), "i" (ASI_PHYS_USE_EC));		if (cheetah_recheck_errors(NULL))			ret = 2;		else			ret = 1;	} else {		/* No new error, intermittent problem. */		ret = 0;	}	/* Restore error enables. */	__asm__ __volatile__("stxa	%0, [%%g0] %1\n\t"			     "membar	#Sync"			     : : "r" (orig_estate), "i" (ASI_ESTATE_ERROR_EN));	return ret;}/* Return non-zero if PADDR is a valid physical memory address. */static int cheetah_check_main_memory(unsigned long paddr){	unsigned long vaddr = PAGE_OFFSET + paddr;	if (vaddr > (unsigned long) high_memory)		return 0;	return kern_addr_valid(vaddr);}void cheetah_cee_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar){	struct cheetah_err_info local_snapshot, *p;	int recoverable, is_memory;	p = cheetah_get_error_log(afsr);	if (!p) {		prom_printf("ERROR: Early CEE error afsr[%016lx] afar[%016lx]\n",			    afsr, afar);		prom_printf("ERROR: CPU(%d) TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n",			    smp_processor_id(), regs->tpc, regs->tnpc, regs->tstate);		prom_halt();	}	/* Grab snapshot of logged error. */	memcpy(&local_snapshot, p, sizeof(local_snapshot));	/* If the current trap snapshot does not match what the	 * trap handler passed along into our args, big trouble.	 * In such a case, mark the local copy as invalid.	 *	 * Else, it matches and we mark the afsr in the non-local	 * copy as invalid so we may log new error traps there.	 */	if (p->afsr != afsr || p->afar != afar)		local_snapshot.afsr = CHAFSR_INVALID;	else		p->afsr = CHAFSR_INVALID;	is_memory = cheetah_check_main_memory(afar);	if (is_memory && (afsr & CHAFSR_CE) != 0UL) {		/* XXX Might want to log the results of this operation		 * XXX somewhere... -DaveM		 */		cheetah_fix_ce(afar);	}	{		int flush_all, flush_line;		flush_all = flush_line = 0;		if ((afsr & CHAFSR_EDC) != 0UL) {			if ((afsr & cheetah_afsr_errors) == CHAFSR_EDC)				flush_line = 1;			else				flush_all = 1;		} else if ((afsr & CHAFSR_CPC) != 0UL) {			if ((afsr & cheetah_afsr_errors) == CHAFSR_CPC)				flush_line = 1;			else				flush_all = 1;		}		/* Trap handler only disabled I-cache, flush it. */		cheetah_flush_icache();		/* Re-enable I-cache */		__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"				     "or %%g1, %1, %%g1\n\t"				     "stxa %%g1, [%%g0] %0\n\t"				     "membar #Sync"				     : /* no outputs */				     : "i" (ASI_DCU_CONTROL_REG),				     "i" (DCU_IC)				     : "g1");		if (flush_all)			cheetah_flush_ecache();		else if (flush_line)			cheetah_flush_ecache_line(afar);	}	/* Re-enable error reporting */	__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"			     "or %%g1, %1, %%g1\n\t"			     "stxa %%g1, [%%g0] %0\n\t"			     "membar #Sync"			     : /* no outputs */			     : "i" (ASI_ESTATE_ERROR_EN),			       "i" (ESTATE_ERROR_CEEN)			     : "g1");	/* Decide if we can continue after handling this trap and	 * logging the error.	 */	recoverable = 1;	if (afsr & (CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP))		recoverable = 0;	/* Re-check AFSR/AFAR */	(void) cheetah_recheck_errors(&local_snapshot);	/* Log errors. */	cheetah_log_errors(regs, &local_snapshot, afsr, afar, recoverable);	if (!recoverable)		panic("Irrecoverable Correctable-ECC error trap.\n");}void cheetah_deferred_handler(struct pt_regs *regs, unsigned long afsr, unsigned long afar){	struct cheetah_err_info local_snapshot, *p;	int recoverable, is_memory;#ifdef CONFIG_PCI	/* Check for the special PCI poke sequence. */	if (pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {		cheetah_flush_icache();		cheetah_flush_dcache();		/* Re-enable I-cache/D-cache */		__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"				     "or %%g1, %1, %%g1\n\t"				     "stxa %%g1, [%%g0] %0\n\t"				     "membar #Sync"				     : /* no outputs */				     : "i" (ASI_DCU_CONTROL_REG),				       "i" (DCU_DC | DCU_IC)				     : "g1");		/* Re-enable error reporting */		__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"				     "or %%g1, %1, %%g1\n\t"				     "stxa %%g1, [%%g0] %0\n\t"				     "membar #Sync"				     : /* no outputs */				     : "i" (ASI_ESTATE_ERROR_EN),				       "i" (ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN)				     : "g1");		(void) cheetah_recheck_errors(NULL);		pci_poke_faulted = 1;		regs->tpc += 4;		regs->tnpc = regs->tpc + 4;		return;	}#endif	p = cheetah_get_error_log(afsr);	if (!p) {		prom_printf("ERROR: Early deferred error afsr[%016lx] afar[%016lx]\n",			    afsr, afar);		prom_printf("ERROR: CPU(%d) TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n",			    smp_processor_id(), regs->tpc, regs->tnpc, regs->tstate);		prom_halt();	}	/* Grab snapshot of logged error. */	memcpy(&local_snapshot, p, sizeof(local_snapshot));	/* If the current trap snapshot does not match what the	 * trap handler passed along into our args, big trouble.	 * In such a case, mark the local copy as invalid.	 *	 * Else, it matches and we mark the afsr in the non-local	 * copy as invalid so we may log new error traps there.	 */	if (p->afsr != afsr || p->afar != afar)		local_snapshot.afsr = CHAFSR_INVALID;	else		p->afsr = CHAFSR_INVALID;	is_memory = cheetah_check_main_memory(afar);	{		int flush_all, flush_line;		flush_all = flush_line = 0;		if ((afsr & CHAFSR_EDU) != 0UL) {			if ((afsr & cheetah_afsr_errors) == CHAFSR_EDU)				flush_line = 1;			else				flush_all = 1;		} else if ((afsr & CHAFSR_BERR) != 0UL) {			if ((afsr & cheetah_afsr_errors) == CHAFSR_BERR)				flush_line = 1;			else				flush_all = 1;		}		cheetah_flush_icache();		cheetah_flush_dcache();		/* Re-enable I/D caches */		__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"				     "or %%g1, %1, %%g1\n\t"				     "stxa %%g1, [%%g0] %0\n\t"				     "membar #Sync"				     : /* no outputs */				     : "i" (ASI_DCU_CONTROL_REG),				     "i" (DCU_IC | DCU_DC)				     : "g1");		if (flush_all)			cheetah_flush_ecache();		else if (flush_line)			cheetah_flush_ecache_line(afar);	}	/* Re-enable error reporting */	__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"			     "or %%g1, %1, %%g1\n\t"			     "stxa %%g1, [%%g0] %0\n\t"			     "membar #Sync"			     : /* no outputs */			     : "i" (ASI_ESTATE_ERROR_EN),			     "i" (ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN)			     : "g1");	/* Decide if we can continue after handling this trap and	 * logging the error.	 */	recoverable = 1;	if (afsr & (CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP))		recoverable = 0;	/* Re-check AFSR/AFAR.  What we are looking for here is whether a new	 * error was logged while we had error reporting traps disabled.	 */	if (cheetah_recheck_errors(&local_snapshot)) {		unsigned long new_afsr = local_snapshot.afsr;		/* If we got a new asynchronous error, die... */		if (new_afsr & (CHAFSR_EMU | CHAFSR_EDU |				CHAFSR_WDU | CHAFSR_CPU |				CHAFSR_IVU | CHAFSR_UE |				CHAFSR_BERR | CHAFSR_TO))			recoverable = 0;	}	/* Log errors. */	cheetah_log_errors(regs, &local_snapshot, afsr, afar, recoverable);	/* "Recoverable" here means we try to yank the page from ever	 * being newly used again.  This depends upon a few things:	 * 1) Must be main memory, and AFAR must be valid.	 * 2) If we trapped from user, OK.	 * 3) Else, if we trapped from kernel we must find exception	 *    table entry (ie. we have to have been accessing user	 *    space).	 *	 * If AFAR is not in main memory, or we trapped from kernel	 * and cannot find an exception table entry, it is unacceptable	 * to try and continue.	 */	if (recoverable && is_memory) {		if ((regs->tstate & TSTATE_PRIV) == 0UL) {			/* OK, usermode access. */			recoverable = 1;		} else {			const struct exception_table_entry *entry;			entry = search_exception_tables(regs->tpc);			if (entry) {				/* OK, kernel access to userspace. */				recoverable = 1;			} else {				/* BAD, privileged state is corrupted. */				recoverable = 0;			}			if (recoverable) {				if (pfn_valid(afar >> PAGE_SHIFT))					get_page(pfn_to_page(afar >> PAGE_SHIFT));				else					recoverable = 0;				/* Only perform fixup if we still have a				 * recoverable condition.				 */				if (recoverable) {					regs->tpc = entry->fixup;					regs->tnpc = regs->tpc + 4;				}			}		}	} else {		recoverable = 0;	}	if (!recoverable)		panic("Irrecoverable deferred error trap.\n");}/* Handle a D/I cache parity error trap.  TYPE is encoded as: * * Bit0:	0=dcache,1=icache * Bit1:	0=recoverable,1=unrecoverable * * The hardware has disabled both the I-cache and D-cache in * the %dcr register.   */void cheetah_plus_parity_error(int type, struct pt_regs *regs){	if (type & 0x1)		__cheetah_flush_icache();	else		cheetah_plus_zap_dcache_parity();	cheetah_flush_dcache();	/* Re-enable I-cache/D-cache */	__asm__ __volatile__("ldxa [%%g0] %0, %%g1\n\t"			     "or %%g1, %1, %%g1\n\t"			     "stxa %%g1, [%%g0] %0\n\t"			     "membar #Sync"			     : /* no outputs */			     : "i" (ASI_DCU_CONTROL_REG),			       "i" (DCU_DC | DCU_IC)			     : "g1");	if (type & 0x2) {		printk(KERN_EMERG "CPU[%d]: Cheetah+ %c-cache parity error at TPC[%016lx]\n",		       smp_processor_id(),		       (type & 0x1) ? 'I' : 'D',		       regs->tpc);		panic("Irrecoverable Cheetah+ parity error.");	}	printk(KERN_WARNING "CPU[%d]: Cheetah+ %c-cache parity error at TPC[%016lx]\n",	       smp_processor_id(),	       (type & 0x1) ? 'I' : 'D',	       regs->tpc);}void do_fpe_common(struct pt_regs *regs){	if (regs->tstate & TSTATE_PRIV) {		regs->tpc = regs->tnpc;		regs->tnpc += 4;	} else {		unsigned long fsr = current_thread_info()->xfsr[0];		siginfo_t info;		if (test_thread_flag(TIF_32BIT)) {			regs->tpc &= 0xffffffff;			regs->tnpc &= 0xffffffff;		}		info.si_signo = SIGFPE;		info.si_errno = 0;		info.si_addr = (void __user *)regs->tpc;		info.si_trapno = 0;		info.si_code = __SI_FAULT;		if ((fsr & 0x1c000) == (1 << 14)) {			if (fsr & 0x10)				info.si_code = FPE_FLTINV;			else if (fsr & 0x08)				info.si_code = FPE_FLTOVF;			else if (fsr & 0x04)				info.si_code = FPE_FLTUND;			else if (fsr & 0x02)				info.si_code = FPE_FLTDIV;			else if (fsr & 0x01)				info.si_code = FPE_FLTRES;		}		force_sig_info(SIGFPE, &info, current);	}}void do_fpieee(struct pt_regs *regs){	if (notify_die(DIE_TRAP, "fpu exception ieee", regs,		       0, 0x24, SIGFPE) == NOTIFY_STOP)		return;	do_fpe_common(regs);}extern int do_mathemu(struct pt_regs *, struct fpustate *);void do_fpother(struct pt_regs *regs){	struct fpustate *f = FPUSTATE;	int ret = 0;	if (notify_die(DIE_TRAP, "fpu exception other", regs,		       0, 0x25, SIGFPE) == NOTIFY_STOP)		return;	switch ((current_thread_info()->xfsr[0] & 0x1c000)) {	case (2 << 14): /* unfinished_FPop */	case (3 << 14): /* unimplemented_FPop */		ret = do_mathemu(regs, f);		break;	}	if (ret)		return;	do_fpe_common(regs);}void do_tof(struct pt_regs *regs){	siginfo_t info;	if (notify_die(DIE_TRAP, "tagged arithmetic overflow", regs,		       0, 0x26, SIGEMT) == NOTIFY_STOP)		return;

⌨️ 快捷键说明

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