📄 traps.c
字号:
if (val > largest_size) largest_size = val; val = prom_getintdefault(node, "ecache-line-size", 64); if (val < smallest_linesize) smallest_linesize = val; } } if (largest_size == 0UL || smallest_linesize == ~0UL) { prom_printf("cheetah_ecache_flush_init: Cannot probe cpu E-cache " "parameters.\n"); prom_halt(); } ecache_flush_size = (2 * largest_size); ecache_flush_linesize = smallest_linesize; /* Discover a physically contiguous chunk of physical * memory in 'sp_banks' of size ecache_flush_size calculated * above. Store the physical base of this area at * ecache_flush_physbase. */ for (node = 0; ; node++) { if (sp_banks[node].num_bytes == 0) break; if (sp_banks[node].num_bytes >= ecache_flush_size) { ecache_flush_physbase = sp_banks[node].base_addr; break; } } /* Note: Zero would be a valid value of ecache_flush_physbase so * don't use that as the success test. :-) */ if (sp_banks[node].num_bytes == 0) { prom_printf("cheetah_ecache_flush_init: Cannot find %d byte " "contiguous physical memory.\n", ecache_flush_size); prom_halt(); } /* Now allocate error trap reporting scoreboard. */ highest_cpu = 0;#ifdef CONFIG_SMP for (i = 0; i < NR_CPUS; i++) { if ((1UL << i) & cpu_present_map) highest_cpu = i; }#endif highest_cpu++; node = highest_cpu * (2 * sizeof(struct cheetah_err_info)); for (order = 0; order < MAX_ORDER; order++) { if ((PAGE_SIZE << order) >= node) break; } cheetah_error_log = (struct cheetah_err_info *) __get_free_pages(GFP_KERNEL, order); if (!cheetah_error_log) { prom_printf("cheetah_ecache_flush_init: Failed to allocate " "error logging scoreboard (%d bytes).\n", node); prom_halt(); } memset(cheetah_error_log, 0, PAGE_SIZE << order); /* Mark all AFSRs as invalid so that the trap handler will * log new new information there. */ for (i = 0; i < 2 * highest_cpu; i++) cheetah_error_log[i].afsr = CHAFSR_INVALID; /* Now patch trap tables. */ memcpy(tl0_fecc, cheetah_fecc_trap_vector, (8 * 4)); memcpy(tl1_fecc, cheetah_fecc_trap_vector_tl1, (8 * 4)); memcpy(tl0_cee, cheetah_cee_trap_vector, (8 * 4)); memcpy(tl1_cee, cheetah_cee_trap_vector_tl1, (8 * 4)); memcpy(tl0_iae, cheetah_deferred_trap_vector, (8 * 4)); memcpy(tl1_iae, cheetah_deferred_trap_vector_tl1, (8 * 4)); memcpy(tl0_dae, cheetah_deferred_trap_vector, (8 * 4)); memcpy(tl1_dae, cheetah_deferred_trap_vector_tl1, (8 * 4)); flushi(PAGE_OFFSET);}static void cheetah_flush_ecache(void){ unsigned long flush_base = ecache_flush_physbase; unsigned long flush_linesize = ecache_flush_linesize; unsigned long flush_size = ecache_flush_size; __asm__ __volatile__("1: subcc %0, %4, %0\n\t" " bne,pt %%xcc, 1b\n\t" " ldxa [%2 + %0] %3, %%g0\n\t" : "=&r" (flush_size) : "0" (flush_size), "r" (flush_base), "i" (ASI_PHYS_USE_EC), "r" (flush_linesize));}static void cheetah_flush_ecache_line(unsigned long physaddr){ unsigned long alias; physaddr &= ~(8UL - 1UL); physaddr = (ecache_flush_physbase + (physaddr & ((ecache_flush_size>>1UL) - 1UL))); alias = physaddr + (ecache_flush_size >> 1UL); __asm__ __volatile__("ldxa [%0] %2, %%g0\n\t" "ldxa [%1] %2, %%g0\n\t" "membar #Sync" : /* no outputs */ : "r" (physaddr), "r" (alias), "i" (ASI_PHYS_USE_EC));}/* Unfortunately, the diagnostic access to the I-cache tags we need to * use to clear the thing interferes with I-cache coherency transactions. * * So we must only flush the I-cache when it is disabled. */static void cheetah_flush_icache(void){ unsigned long dcu_save, i; /* Save current DCU, disable I-cache. */ __asm__ __volatile__("ldxa [%%g0] %1, %0\n\t" "or %0, %2, %%g1\n\t" "stxa %%g1, [%%g0] %1\n\t" "membar #Sync" : "=r" (dcu_save) : "i" (ASI_DCU_CONTROL_REG), "i" (DCU_IC) : "g1"); /* Clear the valid bits in all the tags. */ for (i = 0; i < (1 << 16); i += (1 << 5)) { __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : /* no outputs */ : "r" (i | (2 << 3)), "i" (ASI_IC_TAG)); } /* Restore DCU register */ __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" "membar #Sync" : /* no outputs */ : "r" (dcu_save), "i" (ASI_DCU_CONTROL_REG));}static void cheetah_flush_dcache(void){ unsigned long i; for (i = 0; i < (1 << 16); i += (1 << 5)) { __asm__ __volatile__("stxa %%g0, [%0] %1\n\t" "membar #Sync" : /* no outputs */ : "r" (i), "i" (ASI_DCACHE_TAG)); }}/* Conversion tables used to frob Cheetah AFSR syndrome values into * something palatable to the memory controller driver get_unumber * routine. */#define MT0 137#define MT1 138#define MT2 139#define NONE 254#define MTC0 140#define MTC1 141#define MTC2 142#define MTC3 143#define C0 128#define C1 129#define C2 130#define C3 131#define C4 132#define C5 133#define C6 134#define C7 135#define C8 136#define M2 144#define M3 145#define M4 146#define M 147static unsigned char cheetah_ecc_syntab[] = {/*00*/NONE, C0, C1, M2, C2, M2, M3, 47, C3, M2, M2, 53, M2, 41, 29, M,/*01*/C4, M, M, 50, M2, 38, 25, M2, M2, 33, 24, M2, 11, M, M2, 16,/*02*/C5, M, M, 46, M2, 37, 19, M2, M, 31, 32, M, 7, M2, M2, 10,/*03*/M2, 40, 13, M2, 59, M, M2, 66, M, M2, M2, 0, M2, 67, 71, M,/*04*/C6, M, M, 43, M, 36, 18, M, M2, 49, 15, M, 63, M2, M2, 6,/*05*/M2, 44, 28, M2, M, M2, M2, 52, 68, M2, M2, 62, M2, M3, M3, M4,/*06*/M2, 26, 106, M2, 64, M, M2, 2, 120, M, M2, M3, M, M3, M3, M4,/*07*/116, M2, M2, M3, M2, M3, M, M4, M2, 58, 54, M2, M, M4, M4, M3,/*08*/C7, M2, M, 42, M, 35, 17, M2, M, 45, 14, M2, 21, M2, M2, 5,/*09*/M, 27, M, M, 99, M, M, 3, 114, M2, M2, 20, M2, M3, M3, M,/*0a*/M2, 23, 113, M2, 112, M2, M, 51, 95, M, M2, M3, M2, M3, M3, M2,/*0b*/103, M, M2, M3, M2, M3, M3, M4, M2, 48, M, M, 73, M2, M, M3,/*0c*/M2, 22, 110, M2, 109, M2, M, 9, 108, M2, M, M3, M2, M3, M3, M,/*0d*/102, M2, M, M, M2, M3, M3, M, M2, M3, M3, M2, M, M4, M, M3,/*0e*/98, M, M2, M3, M2, M, M3, M4, M2, M3, M3, M4, M3, M, M, M,/*0f*/M2, M3, M3, M, M3, M, M, M, 56, M4, M, M3, M4, M, M, M,/*10*/C8, M, M2, 39, M, 34, 105, M2, M, 30, 104, M, 101, M, M, 4,/*11*/M, M, 100, M, 83, M, M2, 12, 87, M, M, 57, M2, M, M3, M,/*12*/M2, 97, 82, M2, 78, M2, M2, 1, 96, M, M, M, M, M, M3, M2,/*13*/94, M, M2, M3, M2, M, M3, M, M2, M, 79, M, 69, M, M4, M,/*14*/M2, 93, 92, M, 91, M, M2, 8, 90, M2, M2, M, M, M, M, M4,/*15*/89, M, M, M3, M2, M3, M3, M, M, M, M3, M2, M3, M2, M, M3,/*16*/86, M, M2, M3, M2, M, M3, M, M2, M, M3, M, M3, M, M, M3,/*17*/M, M, M3, M2, M3, M2, M4, M, 60, M, M2, M3, M4, M, M, M2,/*18*/M2, 88, 85, M2, 84, M, M2, 55, 81, M2, M2, M3, M2, M3, M3, M4,/*19*/77, M, M, M, M2, M3, M, M, M2, M3, M3, M4, M3, M2, M, M,/*1a*/74, M, M2, M3, M, M, M3, M, M, M, M3, M, M3, M, M4, M3,/*1b*/M2, 70, 107, M4, 65, M2, M2, M, 127, M, M, M, M2, M3, M3, M,/*1c*/80, M2, M2, 72, M, 119, 118, M, M2, 126, 76, M, 125, M, M4, M3,/*1d*/M2, 115, 124, M, 75, M, M, M3, 61, M, M4, M, M4, M, M, M,/*1e*/M, 123, 122, M4, 121, M4, M, M3, 117, M2, M2, M3, M4, M3, M, M,/*1f*/111, M, M, M, M4, M3, M3, M, M, M, M3, M, M3, M2, M, M};static unsigned char cheetah_mtag_syntab[] = { NONE, MTC0, MTC1, NONE, MTC2, NONE, NONE, MT0, MTC3, NONE, NONE, MT1, NONE, MT2, NONE, NONE};/* This table is ordered in priority of errors and matches the * AFAR overwrite policy as well. */static struct { unsigned long mask; char *name;} cheetah_error_table[] = { { CHAFSR_PERR, "System interface protocol error" }, { CHAFSR_IERR, "Internal processor error" }, { CHAFSR_ISAP, "System request parity error on incoming addresss" }, { CHAFSR_UCU, "Uncorrectable E-cache ECC error for ifetch/data" }, { CHAFSR_UCC, "SW Correctable E-cache ECC error for ifetch/data" }, { CHAFSR_UE, "Uncorrectable system bus data ECC error for read" }, { CHAFSR_EDU, "Uncorrectable E-cache ECC error for stmerge/blkld" }, { CHAFSR_EMU, "Uncorrectable system bus MTAG error" }, { CHAFSR_WDU, "Uncorrectable E-cache ECC error for writeback" }, { CHAFSR_CPU, "Uncorrectable ECC error for copyout" }, { CHAFSR_CE, "HW corrected system bus data ECC error for read" }, { CHAFSR_EDC, "HW corrected E-cache ECC error for stmerge/blkld" }, { CHAFSR_EMC, "HW corrected system bus MTAG ECC error" }, { CHAFSR_WDC, "HW corrected E-cache ECC error for writeback" }, { CHAFSR_CPC, "HW corrected ECC error for copyout" }, { CHAFSR_TO, "Unmapped error from system bus" }, { CHAFSR_BERR, "Bus error response from system bus" }, /* These two do not update the AFAR. */ { CHAFSR_IVC, "HW corrected system bus data ECC error for ivec read" }, { CHAFSR_IVU, "Uncorrectable system bus data ECC error for ivec read" }, { 0, NULL }};/* Return the highest priority error conditon mentioned. */static __inline__ unsigned long cheetah_get_hipri(unsigned long afsr){ unsigned long tmp = 0; int i; for (i = 0; cheetah_error_table[i].mask; i++) { if ((tmp = (afsr & cheetah_error_table[i].mask)) != 0UL) return tmp; } return tmp;}static char *cheetah_get_string(unsigned long bit){ int i; for (i = 0; cheetah_error_table[i].mask; i++) { if ((bit & cheetah_error_table[i].mask) != 0UL) return cheetah_error_table[i].name; } return "???";}extern int chmc_getunumber(int, unsigned long, char *, int);static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info, unsigned long afsr, unsigned long afar, int recoverable){ unsigned long hipri; char unum[256]; printk("%s" "ERROR(%d): Cheetah error trap taken afsr[%016lx] afar[%016lx] TL1(%d)\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), afsr, afar, (afsr & CHAFSR_TL1) ? 1 : 0); printk("%s" "ERROR(%d): TPC[%016lx] TNPC[%016lx] TSTATE[%016lx]\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), regs->tpc, regs->tnpc, regs->tstate); printk("%s" "ERROR(%d): M_SYND(%lx), E_SYND(%lx)%s%s\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT, (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT, (afsr & CHAFSR_ME) ? ", Multiple Errors" : "", (afsr & CHAFSR_PRIV) ? ", Privileged" : ""); hipri = cheetah_get_hipri(afsr); printk("%s" "ERROR(%d): Highest priority error (%016lx) \"%s\"\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), hipri, cheetah_get_string(hipri)); /* Try to get unumber if relevant. */#define ESYND_ERRORS (CHAFSR_IVC | CHAFSR_IVU | \ CHAFSR_CPC | CHAFSR_CPU | \ CHAFSR_UE | CHAFSR_CE | \ CHAFSR_EDC | CHAFSR_EDU | \ CHAFSR_UCC | CHAFSR_UCU | \ CHAFSR_WDU | CHAFSR_WDC)#define MSYND_ERRORS (CHAFSR_EMC | CHAFSR_EMU) if (afsr & ESYND_ERRORS) { int syndrome; int ret; syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT; syndrome = cheetah_ecc_syntab[syndrome]; ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); if (ret != -1) printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), unum); } else if (afsr & MSYND_ERRORS) { int syndrome; int ret; syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT; syndrome = cheetah_mtag_syntab[syndrome]; ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); if (ret != -1) printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), unum); } /* Now dump the cache snapshots. */ printk("%s" "ERROR(%d): D-cache idx[%x] tag[%016lx] utag[%016lx] stag[%016lx]\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), (int) info->dcache_index, info->dcache_tag, info->dcache_utag, info->dcache_stag); printk("%s" "ERROR(%d): D-cache data0[%016lx] data1[%016lx] data2[%016lx] data3[%016lx]\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), info->dcache_data[0], info->dcache_data[1], info->dcache_data[2], info->dcache_data[3]); printk("%s" "ERROR(%d): I-cache idx[%x] tag[%016lx] utag[%016lx] stag[%016lx] " "u[%016lx] l[%016lx]\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), (int) info->icache_index, info->icache_tag, info->icache_utag, info->icache_stag, info->icache_upper, info->icache_lower); printk("%s" "ERROR(%d): I-cache INSN0[%016lx] INSN1[%016lx] INSN2[%016lx] INSN3[%016lx]\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), info->icache_data[0], info->icache_data[1], info->icache_data[2], info->icache_data[3]); printk("%s" "ERROR(%d): I-cache INSN4[%016lx] INSN5[%016lx] INSN6[%016lx] INSN7[%016lx]\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), info->icache_data[4], info->icache_data[5], info->icache_data[6], info->icache_data[7]); printk("%s" "ERROR(%d): E-cache idx[%x] tag[%016lx]\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), (int) info->ecache_index, info->ecache_tag); printk("%s" "ERROR(%d): E-cache data0[%016lx] data1[%016lx] data2[%016lx] data3[%016lx]\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), info->ecache_data[0], info->ecache_data[1], info->ecache_data[2], info->ecache_data[3]); afsr = (afsr & ~hipri) & CHAFSR_ERRORS; while (afsr != 0UL) { unsigned long bit = cheetah_get_hipri(afsr); printk("%s" "ERROR: Multiple-error (%016lx) \"%s\"\n", (recoverable ? KERN_WARNING : KERN_CRIT), bit, cheetah_get_string(bit)); afsr &= ~bit; } if (!recoverable) printk(KERN_CRIT "ERROR: This condition is not recoverable.\n");}static int cheetah_recheck_errors(struct cheetah_err_info *logp){ unsigned long afsr, afar; int ret = 0; __asm__ __volatile__("ldxa [%%g0] %1, %0\n\t" : "=r" (afsr) : "i" (ASI_AFSR)); if ((afsr & CHAFSR_ERRORS) != 0) { if (logp != NULL) { __asm__ __volatile__("ldxa [%%g0] %1, %0\n\t" : "=r" (afar) : "i" (ASI_AFAR)); logp->afsr = afsr; logp->afar = afar; } ret = 1; } __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" "membar #Sync\n\t" : : "r" (afsr), "i" (ASI_AFSR)); return ret;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -