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

📄 traps.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
📖 第 1 页 / 共 4 页
字号:
/* $Id: traps.c,v 1.82 2001/11/18 00:12:56 davem Exp $ * arch/sparc64/kernel/traps.c * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com) *//* * I like traps on v9, :)))) */#include <linux/config.h>#include <linux/sched.h>  /* for jiffies */#include <linux/kernel.h>#include <linux/signal.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/mm.h>#include <asm/delay.h>#include <asm/system.h>#include <asm/ptrace.h>#include <asm/oplib.h>#include <asm/page.h>#include <asm/pgtable.h>#include <asm/unistd.h>#include <asm/uaccess.h>#include <asm/fpumacro.h>#include <asm/lsu.h>#include <asm/dcu.h>#include <asm/estate.h>#include <asm/chafsr.h>#include <asm/psrcompat.h>#include <asm/processor.h>#ifdef CONFIG_KMOD#include <linux/kmod.h>#endifvoid bad_trap (struct pt_regs *regs, long lvl){	char buffer[32];	siginfo_t info;	if (lvl < 0x100) {		sprintf(buffer, "Bad hw trap %lx at tl0\n", lvl);		die_if_kernel(buffer, regs);	}	lvl -= 0x100;	if (regs->tstate & TSTATE_PRIV) {		sprintf(buffer, "Kernel bad sw trap %lx", lvl);		die_if_kernel (buffer, regs);	}	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {		regs->tpc &= 0xffffffff;		regs->tnpc &= 0xffffffff;	}	info.si_signo = SIGILL;	info.si_errno = 0;	info.si_code = ILL_ILLTRP;	info.si_addr = (void *)regs->tpc;	info.si_trapno = lvl;	force_sig_info(SIGILL, &info, current);}void bad_trap_tl1 (struct pt_regs *regs, long lvl){	char buffer[24];		sprintf (buffer, "Bad trap %lx at tl>0", lvl);	die_if_kernel (buffer, regs);}#ifdef CONFIG_DEBUG_BUGVERBOSEvoid do_BUG(const char *file, int line){	bust_spinlocks(1);	printk("kernel BUG at %s:%d!\n", file, line);}#endifvoid instruction_access_exception (struct pt_regs *regs,				   unsigned long sfsr, unsigned long sfar){	siginfo_t info;	if (regs->tstate & TSTATE_PRIV) {		printk("instruction_access_exception: SFSR[%016lx] SFAR[%016lx], going.\n",		       sfsr, sfar);		die_if_kernel("Iax", regs);	}	if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) {		regs->tpc &= 0xffffffff;		regs->tnpc &= 0xffffffff;	}	info.si_signo = SIGSEGV;	info.si_errno = 0;	info.si_code = SEGV_MAPERR;	info.si_addr = (void *)regs->tpc;	info.si_trapno = 0;	force_sig_info(SIGSEGV, &info, current);}void data_access_exception (struct pt_regs *regs,			    unsigned long sfsr, unsigned long sfar){	siginfo_t info;	if (regs->tstate & TSTATE_PRIV) {		/* Test if this comes from uaccess places. */		unsigned long fixup, g2;		g2 = regs->u_regs[UREG_G2];		if ((fixup = search_exception_table (regs->tpc, &g2))) {			/* Ouch, somebody is trying ugly VM hole tricks on us... */#ifdef DEBUG_EXCEPTIONS			printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc);			printk("EX_TABLE: insn<%016lx> fixup<%016lx> "			       "g2<%016lx>\n", regs->tpc, fixup, g2);#endif			regs->tpc = fixup;			regs->tnpc = regs->tpc + 4;			regs->u_regs[UREG_G2] = g2;			return;		}		/* Shit... */		printk("data_access_exception: SFSR[%016lx] SFAR[%016lx], going.\n",		       sfsr, sfar);		die_if_kernel("Dax", regs);	}	info.si_signo = SIGSEGV;	info.si_errno = 0;	info.si_code = SEGV_MAPERR;	info.si_addr = (void *)sfar;	info.si_trapno = 0;	force_sig_info(SIGSEGV, &info, current);}#ifdef CONFIG_PCI/* This is really pathetic... */extern volatile int pci_poke_in_progress;extern volatile int pci_poke_cpu;extern volatile int pci_poke_faulted;#endif/* When access exceptions happen, we must do this. */static void clean_and_reenable_l1_caches(void){	unsigned long va;	if (tlb_type == spitfire) {		/* Clean 'em. */		for (va =  0; va < (PAGE_SIZE << 1); va += 32) {			spitfire_put_icache_tag(va, 0x0);			spitfire_put_dcache_tag(va, 0x0);		}		/* Re-enable in LSU. */		__asm__ __volatile__("flush %%g6\n\t"				     "membar #Sync\n\t"				     "stxa %0, [%%g0] %1\n\t"				     "membar #Sync"				     : /* no outputs */				     : "r" (LSU_CONTROL_IC | LSU_CONTROL_DC |					    LSU_CONTROL_IM | LSU_CONTROL_DM),				     "i" (ASI_LSU_CONTROL)				     : "memory");	} else if (tlb_type == cheetah) {		/* Flush D-cache */		for (va = 0; va < (1 << 16); va += (1 << 5)) {			__asm__ __volatile__("stxa %%g0, [%0] %1\n\t"					     "membar #Sync"					     : /* no outputs */					     : "r" (va), "i" (ASI_DCACHE_TAG));		}	}}void do_iae(struct pt_regs *regs){	siginfo_t info;	clean_and_reenable_l1_caches();	info.si_signo = SIGBUS;	info.si_errno = 0;	info.si_code = BUS_OBJERR;	info.si_addr = (void *)0;	info.si_trapno = 0;	force_sig_info(SIGBUS, &info, current);}void do_dae(struct pt_regs *regs){#ifdef CONFIG_PCI	if (pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {		clean_and_reenable_l1_caches();		pci_poke_faulted = 1;		/* Why the fuck did they have to change this? */		if (tlb_type == cheetah)			regs->tpc += 4;		regs->tnpc = regs->tpc + 4;		return;	}#endif	do_iae(regs);}static char ecc_syndrome_table[] = {	0x4c, 0x40, 0x41, 0x48, 0x42, 0x48, 0x48, 0x49,	0x43, 0x48, 0x48, 0x49, 0x48, 0x49, 0x49, 0x4a,	0x44, 0x48, 0x48, 0x20, 0x48, 0x39, 0x4b, 0x48,	0x48, 0x25, 0x31, 0x48, 0x28, 0x48, 0x48, 0x2c,	0x45, 0x48, 0x48, 0x21, 0x48, 0x3d, 0x04, 0x48,	0x48, 0x4b, 0x35, 0x48, 0x2d, 0x48, 0x48, 0x29,	0x48, 0x00, 0x01, 0x48, 0x0a, 0x48, 0x48, 0x4b,	0x0f, 0x48, 0x48, 0x4b, 0x48, 0x49, 0x49, 0x48,	0x46, 0x48, 0x48, 0x2a, 0x48, 0x3b, 0x27, 0x48,	0x48, 0x4b, 0x33, 0x48, 0x22, 0x48, 0x48, 0x2e,	0x48, 0x19, 0x1d, 0x48, 0x1b, 0x4a, 0x48, 0x4b,	0x1f, 0x48, 0x4a, 0x4b, 0x48, 0x4b, 0x4b, 0x48,	0x48, 0x4b, 0x24, 0x48, 0x07, 0x48, 0x48, 0x36,	0x4b, 0x48, 0x48, 0x3e, 0x48, 0x30, 0x38, 0x48,	0x49, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x16, 0x48,	0x48, 0x12, 0x4b, 0x48, 0x49, 0x48, 0x48, 0x4b,	0x47, 0x48, 0x48, 0x2f, 0x48, 0x3f, 0x4b, 0x48,	0x48, 0x06, 0x37, 0x48, 0x23, 0x48, 0x48, 0x2b,	0x48, 0x05, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x32,	0x26, 0x48, 0x48, 0x3a, 0x48, 0x34, 0x3c, 0x48,	0x48, 0x11, 0x15, 0x48, 0x13, 0x4a, 0x48, 0x4b,	0x17, 0x48, 0x4a, 0x4b, 0x48, 0x4b, 0x4b, 0x48,	0x49, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x1e, 0x48,	0x48, 0x1a, 0x4b, 0x48, 0x49, 0x48, 0x48, 0x4b,	0x48, 0x08, 0x0d, 0x48, 0x02, 0x48, 0x48, 0x49,	0x03, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x4b, 0x48,	0x49, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x10, 0x48,	0x48, 0x14, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x4b,	0x49, 0x48, 0x48, 0x49, 0x48, 0x4b, 0x18, 0x48,	0x48, 0x1c, 0x4b, 0x48, 0x4b, 0x48, 0x48, 0x4b,	0x4a, 0x0c, 0x09, 0x48, 0x0e, 0x48, 0x48, 0x4b,	0x0b, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x4b, 0x4a};/* cee_trap in entry.S encodes AFSR/UDBH/UDBL error status * in the following format.  The AFAR is left as is, with * reserved bits cleared, and is a raw 40-bit physical * address. */#define CE_STATUS_UDBH_UE		(1UL << (43 + 9))#define CE_STATUS_UDBH_CE		(1UL << (43 + 8))#define CE_STATUS_UDBH_ESYNDR		(0xffUL << 43)#define CE_STATUS_UDBH_SHIFT		43#define CE_STATUS_UDBL_UE		(1UL << (33 + 9))#define CE_STATUS_UDBL_CE		(1UL << (33 + 8))#define CE_STATUS_UDBL_ESYNDR		(0xffUL << 33)#define CE_STATUS_UDBL_SHIFT		33#define CE_STATUS_AFSR_MASK		(0x1ffffffffUL)#define CE_STATUS_AFSR_ME		(1UL << 32)#define CE_STATUS_AFSR_PRIV		(1UL << 31)#define CE_STATUS_AFSR_ISAP		(1UL << 30)#define CE_STATUS_AFSR_ETP		(1UL << 29)#define CE_STATUS_AFSR_IVUE		(1UL << 28)#define CE_STATUS_AFSR_TO		(1UL << 27)#define CE_STATUS_AFSR_BERR		(1UL << 26)#define CE_STATUS_AFSR_LDP		(1UL << 25)#define CE_STATUS_AFSR_CP		(1UL << 24)#define CE_STATUS_AFSR_WP		(1UL << 23)#define CE_STATUS_AFSR_EDP		(1UL << 22)#define CE_STATUS_AFSR_UE		(1UL << 21)#define CE_STATUS_AFSR_CE		(1UL << 20)#define CE_STATUS_AFSR_ETS		(0xfUL << 16)#define CE_STATUS_AFSR_ETS_SHIFT	16#define CE_STATUS_AFSR_PSYND		(0xffffUL << 0)#define CE_STATUS_AFSR_PSYND_SHIFT	0/* Layout of Ecache TAG Parity Syndrome of AFSR */#define AFSR_ETSYNDROME_7_0		0x1UL /* E$-tag bus bits  <7:0> */#define AFSR_ETSYNDROME_15_8		0x2UL /* E$-tag bus bits <15:8> */#define AFSR_ETSYNDROME_21_16		0x4UL /* E$-tag bus bits <21:16> */#define AFSR_ETSYNDROME_24_22		0x8UL /* E$-tag bus bits <24:22> */static char *syndrome_unknown = "<Unknown>";asmlinkage void cee_log(unsigned long ce_status,			unsigned long afar,			struct pt_regs *regs){	char memmod_str[64];	char *p;	unsigned short scode, udb_reg;	printk(KERN_WARNING "CPU[%d]: Correctable ECC Error "	       "AFSR[%lx] AFAR[%016lx] UDBL[%lx] UDBH[%lx]\n",	       smp_processor_id(),	       (ce_status & CE_STATUS_AFSR_MASK),	       afar,	       ((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL),	       ((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL));	udb_reg = ((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL);	if (udb_reg & (1 << 8)) {		scode = ecc_syndrome_table[udb_reg & 0xff];		if (prom_getunumber(scode, afar,				    memmod_str, sizeof(memmod_str)) == -1)			p = syndrome_unknown;		else			p = memmod_str;		printk(KERN_WARNING "CPU[%d]: UDBL Syndrome[%x] "		       "Memory Module \"%s\"\n",		       smp_processor_id(), scode, p);	}	udb_reg = ((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL);	if (udb_reg & (1 << 8)) {		scode = ecc_syndrome_table[udb_reg & 0xff];		if (prom_getunumber(scode, afar,				    memmod_str, sizeof(memmod_str)) == -1)			p = syndrome_unknown;		else			p = memmod_str;		printk(KERN_WARNING "CPU[%d]: UDBH Syndrome[%x] "		       "Memory Module \"%s\"\n",		       smp_processor_id(), scode, p);	}}/* Cheetah error trap handling. */static unsigned long ecache_flush_physbase;static unsigned long ecache_flush_linesize;static unsigned long ecache_flush_size;/* WARNING: The error trap handlers in assembly know the precise *	    layout of the following structure. * * C-level handlers below use this information to log the error * and then determine how to recover (if possible). */struct cheetah_err_info {/*0x00*/u64 afsr;/*0x08*/u64 afar;	/* D-cache state *//*0x10*/u64 dcache_data[4];	/* The actual data	*//*0x30*/u64 dcache_index;	/* D-cache index	*//*0x38*/u64 dcache_tag;		/* D-cache tag/valid	*//*0x40*/u64 dcache_utag;	/* D-cache microtag	*//*0x48*/u64 dcache_stag;	/* D-cache snooptag	*/	/* I-cache state *//*0x50*/u64 icache_data[8];	/* The actual insns + predecode	*//*0x90*/u64 icache_index;	/* I-cache index	*//*0x98*/u64 icache_tag;		/* I-cache phys tag	*//*0xa0*/u64 icache_utag;	/* I-cache microtag	*//*0xa8*/u64 icache_stag;	/* I-cache snooptag	*//*0xb0*/u64 icache_upper;	/* I-cache upper-tag	*//*0xb8*/u64 icache_lower;	/* I-cache lower-tag	*/	/* E-cache state *//*0xc0*/u64 ecache_data[4];	/* 32 bytes from staging registers *//*0xe0*/u64 ecache_index;	/* E-cache index	*//*0xe8*/u64 ecache_tag;		/* E-cache tag/state	*//*0xf0*/u64 __pad[32 - 30];};#define CHAFSR_INVALID		((u64)-1L)/* This is allocated at boot time based upon the largest hardware * cpu ID in the system.  We allocate two entries per cpu, one for * TL==0 logging and one for TL >= 1 logging. */struct cheetah_err_info *cheetah_error_log;static __inline__ struct cheetah_err_info *cheetah_get_error_log(unsigned long afsr){	struct cheetah_err_info *p;	int cpu = smp_processor_id();	if (!cheetah_error_log)		return NULL;	p = cheetah_error_log + (cpu * 2);	if ((afsr & CHAFSR_TL1) != 0UL)		p++;	return p;}extern unsigned int tl0_fecc[], tl1_fecc[];extern unsigned int tl0_cee[], tl1_cee[];extern unsigned int tl0_iae[], tl1_iae[];extern unsigned int tl0_dae[], tl1_dae[];extern unsigned int cheetah_fecc_trap_vector[], cheetah_fecc_trap_vector_tl1[];extern unsigned int cheetah_cee_trap_vector[], cheetah_cee_trap_vector_tl1[];extern unsigned int cheetah_deferred_trap_vector[], cheetah_deferred_trap_vector_tl1[];void cheetah_ecache_flush_init(void){	unsigned long largest_size, smallest_linesize, order;	char type[16];	int node, highest_cpu, i;	/* Scan all cpu device tree nodes, note two values:	 * 1) largest E-cache size	 * 2) smallest E-cache line size	 */	largest_size = 0UL;	smallest_linesize = ~0UL;	node = prom_getchild(prom_root_node);	while ((node = prom_getsibling(node)) != 0) {		prom_getstring(node, "device_type", type, sizeof(type));		if (!strcmp(type, "cpu")) {			unsigned long val;			val = prom_getintdefault(node, "ecache-size",						 (2 * 1024 * 1024));

⌨️ 快捷键说明

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