17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 593743541Smb91622 * Common Development and Distribution License (the "License"). 693743541Smb91622 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22b9e93c10SJonathan Haslam * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/types.h> 277c478bd9Sstevel@tonic-gate #include <sys/systm.h> 287c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 297c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 307c478bd9Sstevel@tonic-gate #include <sys/archsystm.h> 317c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h> 327c478bd9Sstevel@tonic-gate #include <sys/machparam.h> 337c478bd9Sstevel@tonic-gate #include <sys/machsystm.h> 347c478bd9Sstevel@tonic-gate #include <sys/machthread.h> 357c478bd9Sstevel@tonic-gate #include <sys/cpu.h> 367c478bd9Sstevel@tonic-gate #include <sys/cmp.h> 377c478bd9Sstevel@tonic-gate #include <sys/elf_SPARC.h> 387c478bd9Sstevel@tonic-gate #include <vm/hat_sfmmu.h> 397c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 407c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 417c478bd9Sstevel@tonic-gate #include <sys/cheetahregs.h> 427c478bd9Sstevel@tonic-gate #include <sys/us3_module.h> 437c478bd9Sstevel@tonic-gate #include <sys/async.h> 447c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 457c478bd9Sstevel@tonic-gate #include <sys/debug.h> 467c478bd9Sstevel@tonic-gate #include <sys/dditypes.h> 477c478bd9Sstevel@tonic-gate #include <sys/prom_debug.h> 487c478bd9Sstevel@tonic-gate #include <sys/prom_plat.h> 497c478bd9Sstevel@tonic-gate #include <sys/cpu_module.h> 507c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 517c478bd9Sstevel@tonic-gate #include <sys/intreg.h> 527c478bd9Sstevel@tonic-gate #include <sys/clock.h> 537c478bd9Sstevel@tonic-gate #include <sys/platform_module.h> 547c478bd9Sstevel@tonic-gate #include <sys/machtrap.h> 557c478bd9Sstevel@tonic-gate #include <sys/ontrap.h> 567c478bd9Sstevel@tonic-gate #include <sys/panic.h> 577c478bd9Sstevel@tonic-gate #include <sys/memlist.h> 587c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 597c478bd9Sstevel@tonic-gate #include <sys/ivintr.h> 607c478bd9Sstevel@tonic-gate #include <sys/atomic.h> 617c478bd9Sstevel@tonic-gate #include <sys/fm/protocol.h> 627c478bd9Sstevel@tonic-gate #include <sys/fm/cpu/UltraSPARC-III.h> 637c478bd9Sstevel@tonic-gate #include <sys/fm/util.h> 64fb2f18f8Sesaxe #include <sys/pghw.h> 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 677c478bd9Sstevel@tonic-gate #include <sys/cyclic.h> 687c478bd9Sstevel@tonic-gate #endif /* CHEETAHPLUS_ERRATUM_25 */ 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /* 717c478bd9Sstevel@tonic-gate * See comment above cpu_scrub_cpu_setup() for description 727c478bd9Sstevel@tonic-gate */ 737c478bd9Sstevel@tonic-gate #define SCRUBBER_NEITHER_CORE_ONLINE 0x0 747c478bd9Sstevel@tonic-gate #define SCRUBBER_CORE_0_ONLINE 0x1 757c478bd9Sstevel@tonic-gate #define SCRUBBER_CORE_1_ONLINE 0x2 767c478bd9Sstevel@tonic-gate #define SCRUBBER_BOTH_CORES_ONLINE (SCRUBBER_CORE_0_ONLINE | \ 777c478bd9Sstevel@tonic-gate SCRUBBER_CORE_1_ONLINE) 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate static int pn_matching_valid_l2_line(uint64_t faddr, ch_ec_data_t *clo_l2_data); 807c478bd9Sstevel@tonic-gate static void cpu_async_log_tlb_parity_err(void *flt); 817c478bd9Sstevel@tonic-gate static cpu_t *cpu_get_sibling_core(cpu_t *cpup); 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* 857c478bd9Sstevel@tonic-gate * Setup trap handlers. 867c478bd9Sstevel@tonic-gate */ 877c478bd9Sstevel@tonic-gate void 887c478bd9Sstevel@tonic-gate cpu_init_trap(void) 897c478bd9Sstevel@tonic-gate { 90b9e93c10SJonathan Haslam CH_SET_TRAP(pil15_epilogue, ch_pil15_interrupt_instr); 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate CH_SET_TRAP(tt0_fecc, fecc_err_instr); 937c478bd9Sstevel@tonic-gate CH_SET_TRAP(tt1_fecc, fecc_err_tl1_instr); 947c478bd9Sstevel@tonic-gate CH_SET_TRAP(tt1_swtrap0, fecc_err_tl1_cont_instr); 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate CH_SET_TRAP(tt0_dperr, dcache_parity_instr); 977c478bd9Sstevel@tonic-gate CH_SET_TRAP(tt1_dperr, dcache_parity_tl1_instr); 987c478bd9Sstevel@tonic-gate CH_SET_TRAP(tt1_swtrap1, dcache_parity_tl1_cont_instr); 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate CH_SET_TRAP(tt0_iperr, icache_parity_instr); 1017c478bd9Sstevel@tonic-gate CH_SET_TRAP(tt1_iperr, icache_parity_tl1_instr); 1027c478bd9Sstevel@tonic-gate CH_SET_TRAP(tt1_swtrap2, icache_parity_tl1_cont_instr); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * Set the magic constants of the implementation. 1077c478bd9Sstevel@tonic-gate */ 1087c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1097c478bd9Sstevel@tonic-gate void 110fa9e4066Sahrens cpu_fiximp(pnode_t dnode) 1117c478bd9Sstevel@tonic-gate { 1127c478bd9Sstevel@tonic-gate int i, a; 1137c478bd9Sstevel@tonic-gate extern int vac_size, vac_shift; 1147c478bd9Sstevel@tonic-gate extern uint_t vac_mask; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate dcache_size = CH_DCACHE_SIZE; 1177c478bd9Sstevel@tonic-gate dcache_linesize = CH_DCACHE_LSIZE; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate icache_size = CHP_ICACHE_MAX_SIZE; 1207c478bd9Sstevel@tonic-gate icache_linesize = CHP_ICACHE_MIN_LSIZE; 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate ecache_size = CH_ECACHE_MAX_SIZE; 1237c478bd9Sstevel@tonic-gate ecache_alignsize = CH_ECACHE_MAX_LSIZE; 1247c478bd9Sstevel@tonic-gate ecache_associativity = CHP_ECACHE_MIN_NWAY; 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /* 1277c478bd9Sstevel@tonic-gate * ecache_setsize needs to maximum of all cpu ecache setsizes 1287c478bd9Sstevel@tonic-gate */ 1297c478bd9Sstevel@tonic-gate ecache_setsize = CHP_ECACHE_MAX_SETSIZE; 1307c478bd9Sstevel@tonic-gate ASSERT(ecache_setsize >= (ecache_size / ecache_associativity)); 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate vac_size = CH_VAC_SIZE; 1337c478bd9Sstevel@tonic-gate vac_mask = MMU_PAGEMASK & (vac_size - 1); 1347c478bd9Sstevel@tonic-gate i = 0; a = vac_size; 1357c478bd9Sstevel@tonic-gate while (a >>= 1) 1367c478bd9Sstevel@tonic-gate ++i; 1377c478bd9Sstevel@tonic-gate vac_shift = i; 1387c478bd9Sstevel@tonic-gate shm_alignment = vac_size; 1397c478bd9Sstevel@tonic-gate vac = 1; 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 14235b14535Ssusans /* 14335b14535Ssusans * Use Panther values for Panther-only domains. 14435b14535Ssusans * See Panther PRM, 1.5.4 Cache Hierarchy 14535b14535Ssusans */ 14635b14535Ssusans void 14735b14535Ssusans cpu_fix_allpanther(void) 14835b14535Ssusans { 14935b14535Ssusans /* dcache same as Ch+ */ 15035b14535Ssusans icache_size = PN_ICACHE_SIZE; 15135b14535Ssusans icache_linesize = PN_ICACHE_LSIZE; 15235b14535Ssusans ecache_size = PN_L3_SIZE; 15335b14535Ssusans ecache_alignsize = PN_L3_LINESIZE; 15435b14535Ssusans ecache_associativity = PN_L3_NWAYS; 15535b14535Ssusans ecache_setsize = PN_L3_SET_SIZE; 15635b14535Ssusans ASSERT(ecache_setsize >= (ecache_size / ecache_associativity)); 15735b14535Ssusans /* vac same as Ch+ */ 1581b349f08Sck142721 /* fix hwcaps for USIV+-only domains */ 1591b349f08Sck142721 cpu_hwcap_flags |= AV_SPARC_POPC; 16035b14535Ssusans } 16135b14535Ssusans 1627c478bd9Sstevel@tonic-gate void 1637c478bd9Sstevel@tonic-gate send_mondo_set(cpuset_t set) 1647c478bd9Sstevel@tonic-gate { 1657c478bd9Sstevel@tonic-gate int lo, busy, nack, shipped = 0; 1667c478bd9Sstevel@tonic-gate uint16_t i, cpuids[IDSR_BN_SETS]; 1677c478bd9Sstevel@tonic-gate uint64_t idsr, nackmask = 0, busymask, curnack, curbusy; 1687c478bd9Sstevel@tonic-gate uint64_t starttick, endtick, tick, lasttick; 1697c478bd9Sstevel@tonic-gate #if (NCPU > IDSR_BN_SETS) 1707c478bd9Sstevel@tonic-gate int index = 0; 1717c478bd9Sstevel@tonic-gate int ncpuids = 0; 1727c478bd9Sstevel@tonic-gate #endif 1737c478bd9Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 1747c478bd9Sstevel@tonic-gate int recovered = 0; 1757c478bd9Sstevel@tonic-gate int cpuid; 1767c478bd9Sstevel@tonic-gate #endif 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate ASSERT(!CPUSET_ISNULL(set)); 1797c478bd9Sstevel@tonic-gate starttick = lasttick = gettick(); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate #if (NCPU <= IDSR_BN_SETS) 1827c478bd9Sstevel@tonic-gate for (i = 0; i < NCPU; i++) 1837c478bd9Sstevel@tonic-gate if (CPU_IN_SET(set, i)) { 1847c478bd9Sstevel@tonic-gate shipit(i, shipped); 1857c478bd9Sstevel@tonic-gate nackmask |= IDSR_NACK_BIT(shipped); 1867c478bd9Sstevel@tonic-gate cpuids[shipped++] = i; 1877c478bd9Sstevel@tonic-gate CPUSET_DEL(set, i); 1887c478bd9Sstevel@tonic-gate if (CPUSET_ISNULL(set)) 1897c478bd9Sstevel@tonic-gate break; 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, xcalls, shipped); 1927c478bd9Sstevel@tonic-gate #else 1937c478bd9Sstevel@tonic-gate for (i = 0; i < NCPU; i++) 1947c478bd9Sstevel@tonic-gate if (CPU_IN_SET(set, i)) { 1957c478bd9Sstevel@tonic-gate ncpuids++; 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate /* 1987c478bd9Sstevel@tonic-gate * Ship only to the first (IDSR_BN_SETS) CPUs. If we 1997c478bd9Sstevel@tonic-gate * find we have shipped to more than (IDSR_BN_SETS) 2007c478bd9Sstevel@tonic-gate * CPUs, set "index" to the highest numbered CPU in 2017c478bd9Sstevel@tonic-gate * the set so we can ship to other CPUs a bit later on. 2027c478bd9Sstevel@tonic-gate */ 2037c478bd9Sstevel@tonic-gate if (shipped < IDSR_BN_SETS) { 2047c478bd9Sstevel@tonic-gate shipit(i, shipped); 2057c478bd9Sstevel@tonic-gate nackmask |= IDSR_NACK_BIT(shipped); 2067c478bd9Sstevel@tonic-gate cpuids[shipped++] = i; 2077c478bd9Sstevel@tonic-gate CPUSET_DEL(set, i); 2087c478bd9Sstevel@tonic-gate if (CPUSET_ISNULL(set)) 2097c478bd9Sstevel@tonic-gate break; 2107c478bd9Sstevel@tonic-gate } else 2117c478bd9Sstevel@tonic-gate index = (int)i; 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, xcalls, ncpuids); 2157c478bd9Sstevel@tonic-gate #endif 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate busymask = IDSR_NACK_TO_BUSY(nackmask); 2187c478bd9Sstevel@tonic-gate busy = nack = 0; 2197c478bd9Sstevel@tonic-gate endtick = starttick + xc_tick_limit; 2207c478bd9Sstevel@tonic-gate for (;;) { 2217c478bd9Sstevel@tonic-gate idsr = getidsr(); 2227c478bd9Sstevel@tonic-gate #if (NCPU <= IDSR_BN_SETS) 2237c478bd9Sstevel@tonic-gate if (idsr == 0) 2247c478bd9Sstevel@tonic-gate break; 2257c478bd9Sstevel@tonic-gate #else 2267c478bd9Sstevel@tonic-gate if (idsr == 0 && shipped == ncpuids) 2277c478bd9Sstevel@tonic-gate break; 2287c478bd9Sstevel@tonic-gate #endif 2297c478bd9Sstevel@tonic-gate tick = gettick(); 2307c478bd9Sstevel@tonic-gate /* 2317c478bd9Sstevel@tonic-gate * If there is a big jump between the current tick 2327c478bd9Sstevel@tonic-gate * count and lasttick, we have probably hit a break 2337c478bd9Sstevel@tonic-gate * point. Adjust endtick accordingly to avoid panic. 2347c478bd9Sstevel@tonic-gate */ 2357c478bd9Sstevel@tonic-gate if (tick > (lasttick + xc_tick_jump_limit)) 2367c478bd9Sstevel@tonic-gate endtick += (tick - lasttick); 2377c478bd9Sstevel@tonic-gate lasttick = tick; 2387c478bd9Sstevel@tonic-gate if (tick > endtick) { 2397c478bd9Sstevel@tonic-gate if (panic_quiesce) 2407c478bd9Sstevel@tonic-gate return; 2417c478bd9Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 2427c478bd9Sstevel@tonic-gate cpuid = -1; 2437c478bd9Sstevel@tonic-gate for (i = 0; i < IDSR_BN_SETS; i++) { 2447c478bd9Sstevel@tonic-gate if (idsr & (IDSR_NACK_BIT(i) | 2457c478bd9Sstevel@tonic-gate IDSR_BUSY_BIT(i))) { 2467c478bd9Sstevel@tonic-gate cpuid = cpuids[i]; 2477c478bd9Sstevel@tonic-gate break; 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate if (cheetah_sendmondo_recover && cpuid != -1 && 2517c478bd9Sstevel@tonic-gate recovered == 0) { 2527c478bd9Sstevel@tonic-gate if (mondo_recover(cpuid, i)) { 2537c478bd9Sstevel@tonic-gate /* 2547c478bd9Sstevel@tonic-gate * We claimed the whole memory or 2557c478bd9Sstevel@tonic-gate * full scan is disabled. 2567c478bd9Sstevel@tonic-gate */ 2577c478bd9Sstevel@tonic-gate recovered++; 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate tick = gettick(); 2607c478bd9Sstevel@tonic-gate endtick = tick + xc_tick_limit; 2617c478bd9Sstevel@tonic-gate lasttick = tick; 2627c478bd9Sstevel@tonic-gate /* 2637c478bd9Sstevel@tonic-gate * Recheck idsr 2647c478bd9Sstevel@tonic-gate */ 2657c478bd9Sstevel@tonic-gate continue; 2667c478bd9Sstevel@tonic-gate } else 2677c478bd9Sstevel@tonic-gate #endif /* CHEETAHPLUS_ERRATUM_25 */ 2687c478bd9Sstevel@tonic-gate { 2697c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "send mondo timeout " 2707c478bd9Sstevel@tonic-gate "[%d NACK %d BUSY]\nIDSR 0x%" 2717c478bd9Sstevel@tonic-gate "" PRIx64 " cpuids:", nack, busy, idsr); 2727c478bd9Sstevel@tonic-gate for (i = 0; i < IDSR_BN_SETS; i++) { 2737c478bd9Sstevel@tonic-gate if (idsr & (IDSR_NACK_BIT(i) | 2747c478bd9Sstevel@tonic-gate IDSR_BUSY_BIT(i))) { 2757c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, " 0x%x", 2767c478bd9Sstevel@tonic-gate cpuids[i]); 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "\n"); 2807c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "send_mondo_set: timeout"); 2817c478bd9Sstevel@tonic-gate } 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate curnack = idsr & nackmask; 2847c478bd9Sstevel@tonic-gate curbusy = idsr & busymask; 2857c478bd9Sstevel@tonic-gate #if (NCPU > IDSR_BN_SETS) 2867c478bd9Sstevel@tonic-gate if (shipped < ncpuids) { 2877c478bd9Sstevel@tonic-gate uint64_t cpus_left; 2887c478bd9Sstevel@tonic-gate uint16_t next = (uint16_t)index; 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate cpus_left = ~(IDSR_NACK_TO_BUSY(curnack) | curbusy) & 2917c478bd9Sstevel@tonic-gate busymask; 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate if (cpus_left) { 2947c478bd9Sstevel@tonic-gate do { 2957c478bd9Sstevel@tonic-gate /* 2967c478bd9Sstevel@tonic-gate * Sequence through and ship to the 2977c478bd9Sstevel@tonic-gate * remainder of the CPUs in the system 2987c478bd9Sstevel@tonic-gate * (e.g. other than the first 2997c478bd9Sstevel@tonic-gate * (IDSR_BN_SETS)) in reverse order. 3007c478bd9Sstevel@tonic-gate */ 3017c478bd9Sstevel@tonic-gate lo = lowbit(cpus_left) - 1; 3027c478bd9Sstevel@tonic-gate i = IDSR_BUSY_IDX(lo); 3037c478bd9Sstevel@tonic-gate shipit(next, i); 3047c478bd9Sstevel@tonic-gate shipped++; 3057c478bd9Sstevel@tonic-gate cpuids[i] = next; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate /* 3087c478bd9Sstevel@tonic-gate * If we've processed all the CPUs, 3097c478bd9Sstevel@tonic-gate * exit the loop now and save 3107c478bd9Sstevel@tonic-gate * instructions. 3117c478bd9Sstevel@tonic-gate */ 3127c478bd9Sstevel@tonic-gate if (shipped == ncpuids) 3137c478bd9Sstevel@tonic-gate break; 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate for ((index = ((int)next - 1)); 3167c478bd9Sstevel@tonic-gate index >= 0; index--) 3177c478bd9Sstevel@tonic-gate if (CPU_IN_SET(set, index)) { 3187c478bd9Sstevel@tonic-gate next = (uint16_t)index; 3197c478bd9Sstevel@tonic-gate break; 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate cpus_left &= ~(1ull << lo); 3237c478bd9Sstevel@tonic-gate } while (cpus_left); 3247c478bd9Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 3257c478bd9Sstevel@tonic-gate /* 3267c478bd9Sstevel@tonic-gate * Clear recovered because we are sending to 3277c478bd9Sstevel@tonic-gate * a new set of targets. 3287c478bd9Sstevel@tonic-gate */ 3297c478bd9Sstevel@tonic-gate recovered = 0; 3307c478bd9Sstevel@tonic-gate #endif 3317c478bd9Sstevel@tonic-gate continue; 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate #endif 3357c478bd9Sstevel@tonic-gate if (curbusy) { 3367c478bd9Sstevel@tonic-gate busy++; 3377c478bd9Sstevel@tonic-gate continue; 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate #ifdef SEND_MONDO_STATS 3417c478bd9Sstevel@tonic-gate { 3427c478bd9Sstevel@tonic-gate int n = gettick() - starttick; 3437c478bd9Sstevel@tonic-gate if (n < 8192) 3447c478bd9Sstevel@tonic-gate x_nack_stimes[n >> 7]++; 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate #endif 3477c478bd9Sstevel@tonic-gate while (gettick() < (tick + sys_clock_mhz)) 3487c478bd9Sstevel@tonic-gate ; 3497c478bd9Sstevel@tonic-gate do { 3507c478bd9Sstevel@tonic-gate lo = lowbit(curnack) - 1; 3517c478bd9Sstevel@tonic-gate i = IDSR_NACK_IDX(lo); 3527c478bd9Sstevel@tonic-gate shipit(cpuids[i], i); 3537c478bd9Sstevel@tonic-gate curnack &= ~(1ull << lo); 3547c478bd9Sstevel@tonic-gate } while (curnack); 3557c478bd9Sstevel@tonic-gate nack++; 3567c478bd9Sstevel@tonic-gate busy = 0; 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate #ifdef SEND_MONDO_STATS 3597c478bd9Sstevel@tonic-gate { 3607c478bd9Sstevel@tonic-gate int n = gettick() - starttick; 3617c478bd9Sstevel@tonic-gate if (n < 8192) 3627c478bd9Sstevel@tonic-gate x_set_stimes[n >> 7]++; 3637c478bd9Sstevel@tonic-gate else 3647c478bd9Sstevel@tonic-gate x_set_ltimes[(n >> 13) & 0xf]++; 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate x_set_cpus[shipped]++; 3677c478bd9Sstevel@tonic-gate #endif 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate /* 3717c478bd9Sstevel@tonic-gate * Handles error logging for implementation specific error types 3727c478bd9Sstevel@tonic-gate */ 3737c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 3747c478bd9Sstevel@tonic-gate int 3757c478bd9Sstevel@tonic-gate cpu_impl_async_log_err(void *flt, errorq_elem_t *eqep) 3767c478bd9Sstevel@tonic-gate { 3777c478bd9Sstevel@tonic-gate ch_async_flt_t *ch_flt = (ch_async_flt_t *)flt; 3787c478bd9Sstevel@tonic-gate struct async_flt *aflt = (struct async_flt *)flt; 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate switch (ch_flt->flt_type) { 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate case CPU_IC_PARITY: 3837c478bd9Sstevel@tonic-gate cpu_async_log_ic_parity_err(flt); 3847c478bd9Sstevel@tonic-gate return (CH_ASYNC_LOG_DONE); 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate case CPU_DC_PARITY: 3877c478bd9Sstevel@tonic-gate cpu_async_log_dc_parity_err(flt); 3887c478bd9Sstevel@tonic-gate return (CH_ASYNC_LOG_DONE); 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate case CPU_DUE: 3917c478bd9Sstevel@tonic-gate cpu_log_err(aflt); 3927c478bd9Sstevel@tonic-gate cpu_page_retire(ch_flt); 3937c478bd9Sstevel@tonic-gate return (CH_ASYNC_LOG_DONE); 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate case CPU_ITLB_PARITY: 3967c478bd9Sstevel@tonic-gate case CPU_DTLB_PARITY: 3977c478bd9Sstevel@tonic-gate cpu_async_log_tlb_parity_err(flt); 3987c478bd9Sstevel@tonic-gate return (CH_ASYNC_LOG_DONE); 3997c478bd9Sstevel@tonic-gate 400b9048f8aSmb91622 /* report the error and continue */ 401b9048f8aSmb91622 case CPU_L3_ADDR_PE: 402b9048f8aSmb91622 cpu_log_err(aflt); 403b9048f8aSmb91622 return (CH_ASYNC_LOG_DONE); 404b9048f8aSmb91622 4057c478bd9Sstevel@tonic-gate default: 4067c478bd9Sstevel@tonic-gate return (CH_ASYNC_LOG_UNKNOWN); 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate /* 4117c478bd9Sstevel@tonic-gate * Figure out if Ecache is direct-mapped (Cheetah or Cheetah+ with Ecache 4127c478bd9Sstevel@tonic-gate * control ECCR_ASSOC bit off or 2-way (Cheetah+ with ECCR_ASSOC on). 4137c478bd9Sstevel@tonic-gate * We need to do this on the fly because we may have mixed Cheetah+'s with 4147c478bd9Sstevel@tonic-gate * both direct and 2-way Ecaches. Panther only supports 4-way L3$. 4157c478bd9Sstevel@tonic-gate */ 4167c478bd9Sstevel@tonic-gate int 4177c478bd9Sstevel@tonic-gate cpu_ecache_nway(void) 4187c478bd9Sstevel@tonic-gate { 4197c478bd9Sstevel@tonic-gate if (IS_PANTHER(cpunodes[CPU->cpu_id].implementation)) 4207c478bd9Sstevel@tonic-gate return (PN_L3_NWAYS); 4217c478bd9Sstevel@tonic-gate return ((get_ecache_ctrl() & ECCR_ASSOC) ? 2 : 1); 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate /* 4257c478bd9Sstevel@tonic-gate * Note that these are entered into the table: Fatal Errors (PERR, IERR, ISAP, 4267c478bd9Sstevel@tonic-gate * EMU, IMU) first, orphaned UCU/UCC, AFAR Overwrite policy, finally IVU, IVC. 4277c478bd9Sstevel@tonic-gate * Afar overwrite policy is: 4287c478bd9Sstevel@tonic-gate * Class 4: 4297c478bd9Sstevel@tonic-gate * AFSR -- UCC, UCU, TUE, TSCE, TUE_SH 4307c478bd9Sstevel@tonic-gate * AFSR_EXT -- L3_UCC, L3_UCU, L3_TUE, L3_TUE_SH 4317c478bd9Sstevel@tonic-gate * Class 3: 4327c478bd9Sstevel@tonic-gate * AFSR -- UE, DUE, EDU, WDU, CPU 4337c478bd9Sstevel@tonic-gate * AFSR_EXT -- L3_EDU, L3_WDU, L3_CPU 4347c478bd9Sstevel@tonic-gate * Class 2: 4357c478bd9Sstevel@tonic-gate * AFSR -- CE, EDC, EMC, WDC, CPC, THCE 4367c478bd9Sstevel@tonic-gate * AFSR_EXT -- L3_EDC, L3_WDC, L3_CPC, L3_THCE 4377c478bd9Sstevel@tonic-gate * Class 1: 4387c478bd9Sstevel@tonic-gate * AFSR -- TO, DTO, BERR, DBERR 4397c478bd9Sstevel@tonic-gate */ 4407c478bd9Sstevel@tonic-gate ecc_type_to_info_t ecc_type_to_info[] = { 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate /* Fatal Errors */ 4437c478bd9Sstevel@tonic-gate C_AFSR_PERR, "PERR ", ECC_ALL_TRAPS, 4447c478bd9Sstevel@tonic-gate CPU_FATAL, "PERR Fatal", 4457c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM2, 4467c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_PERR, 4477c478bd9Sstevel@tonic-gate C_AFSR_IERR, "IERR ", ECC_ALL_TRAPS, 4487c478bd9Sstevel@tonic-gate CPU_FATAL, "IERR Fatal", 4497c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM2, 4507c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IERR, 4517c478bd9Sstevel@tonic-gate C_AFSR_ISAP, "ISAP ", ECC_ALL_TRAPS, 4527c478bd9Sstevel@tonic-gate CPU_FATAL, "ISAP Fatal", 4537c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 4547c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_ISAP, 4557c478bd9Sstevel@tonic-gate C_AFSR_L3_TUE_SH, "L3_TUE_SH ", ECC_C_TRAP, 4567c478bd9Sstevel@tonic-gate CPU_FATAL, "L3_TUE_SH Fatal", 4577c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L3_TAG_ECC, 4587c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_L3_TUE_SH, 4597c478bd9Sstevel@tonic-gate C_AFSR_L3_TUE, "L3_TUE ", ECC_C_TRAP, 4607c478bd9Sstevel@tonic-gate CPU_FATAL, "L3_TUE Fatal", 4617c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L3_TAG_ECC, 4627c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_L3_TUE, 4637c478bd9Sstevel@tonic-gate C_AFSR_TUE_SH, "TUE_SH ", ECC_C_TRAP, 4647c478bd9Sstevel@tonic-gate CPU_FATAL, "TUE_SH Fatal", 4657c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_TAG_ECC, 4667c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_TUE_SH, 4677c478bd9Sstevel@tonic-gate C_AFSR_TUE, "TUE ", ECC_ALL_TRAPS, 4687c478bd9Sstevel@tonic-gate CPU_FATAL, "TUE Fatal", 4697c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_TAG_ECC, 4707c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_TUE, 4717c478bd9Sstevel@tonic-gate C_AFSR_EMU, "EMU ", ECC_ASYNC_TRAPS, 4727c478bd9Sstevel@tonic-gate CPU_FATAL, "EMU Fatal", 4737c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 4747c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EMU, 4757c478bd9Sstevel@tonic-gate C_AFSR_IMU, "IMU ", ECC_C_TRAP, 4767c478bd9Sstevel@tonic-gate CPU_FATAL, "IMU Fatal", 4777c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 4787c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IMU, 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate /* L3$ Address parity errors are reported via the MECC bit */ 4817c478bd9Sstevel@tonic-gate C_AFSR_L3_MECC, "L3_MECC ", ECC_MECC_TRAPS, 4827c478bd9Sstevel@tonic-gate CPU_L3_ADDR_PE, "L3 Address Parity", 4837c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L3_DATA, 4847c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_L3_MECC, 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate /* Orphaned UCC/UCU Errors */ 4877c478bd9Sstevel@tonic-gate C_AFSR_L3_UCU, "L3_OUCU ", ECC_ORPH_TRAPS, 4887c478bd9Sstevel@tonic-gate CPU_ORPH, "Orphaned L3_UCU", 4897c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L3_DATA, 4907c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_L3_UCU, 4917c478bd9Sstevel@tonic-gate C_AFSR_L3_UCC, "L3_OUCC ", ECC_ORPH_TRAPS, 4927c478bd9Sstevel@tonic-gate CPU_ORPH, "Orphaned L3_UCC", 4937c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L3_DATA, 4947c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_L3_UCC, 4957c478bd9Sstevel@tonic-gate C_AFSR_UCU, "OUCU ", ECC_ORPH_TRAPS, 4967c478bd9Sstevel@tonic-gate CPU_ORPH, "Orphaned UCU", 4977c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4987c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCU, 4997c478bd9Sstevel@tonic-gate C_AFSR_UCC, "OUCC ", ECC_ORPH_TRAPS, 5007c478bd9Sstevel@tonic-gate CPU_ORPH, "Orphaned UCC", 5017c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 5027c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCC, 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate /* UCU, UCC */ 5057c478bd9Sstevel@tonic-gate C_AFSR_L3_UCU, "L3_UCU ", ECC_F_TRAP, 5067c478bd9Sstevel@tonic-gate CPU_UE_ECACHE, "L3_UCU", 5077c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L3_DATA, 5087c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_L3_UCU, 5097c478bd9Sstevel@tonic-gate C_AFSR_L3_UCC, "L3_UCC ", ECC_F_TRAP, 5107c478bd9Sstevel@tonic-gate CPU_CE_ECACHE, "L3_UCC", 5117c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L3_DATA, 5127c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_L3_UCC, 5137c478bd9Sstevel@tonic-gate C_AFSR_UCU, "UCU ", ECC_F_TRAP, 5147c478bd9Sstevel@tonic-gate CPU_UE_ECACHE, "UCU", 5157c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 5167c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCU, 5177c478bd9Sstevel@tonic-gate C_AFSR_UCC, "UCC ", ECC_F_TRAP, 5187c478bd9Sstevel@tonic-gate CPU_CE_ECACHE, "UCC", 5197c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 5207c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCC, 5217c478bd9Sstevel@tonic-gate C_AFSR_TSCE, "TSCE ", ECC_F_TRAP, 5227c478bd9Sstevel@tonic-gate CPU_CE_ECACHE, "TSCE", 5237c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_TAG_ECC, 5247c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_TSCE, 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate /* UE, EDU:ST, EDU:BLD, WDU, CPU */ 5277c478bd9Sstevel@tonic-gate C_AFSR_UE, "UE ", ECC_ASYNC_TRAPS, 5287c478bd9Sstevel@tonic-gate CPU_UE, "Uncorrectable system bus (UE)", 5297c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 5307c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UE, 5317c478bd9Sstevel@tonic-gate C_AFSR_L3_EDU, "L3_EDU ", ECC_C_TRAP, 5327c478bd9Sstevel@tonic-gate CPU_UE_ECACHE_RETIRE, "L3_EDU:ST", 5337c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L3_DATA, 5347c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_L3_EDUST, 5357c478bd9Sstevel@tonic-gate C_AFSR_L3_EDU, "L3_EDU ", ECC_D_TRAP, 5367c478bd9Sstevel@tonic-gate CPU_UE_ECACHE_RETIRE, "L3_EDU:BLD", 5377c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L3_DATA, 5387c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_L3_EDUBL, 5397c478bd9Sstevel@tonic-gate C_AFSR_L3_WDU, "L3_WDU ", ECC_C_TRAP, 5407c478bd9Sstevel@tonic-gate CPU_UE_ECACHE_RETIRE, "L3_WDU", 5417c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L3_DATA, 5427c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_L3_WDU, 5437c478bd9Sstevel@tonic-gate C_AFSR_L3_CPU, "L3_CPU ", ECC_C_TRAP, 5447c478bd9Sstevel@tonic-gate CPU_UE_ECACHE, "L3_CPU", 5457c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L3_DATA, 5467c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_L3_CPU, 5477c478bd9Sstevel@tonic-gate C_AFSR_EDU, "EDU ", ECC_C_TRAP, 5487c478bd9Sstevel@tonic-gate CPU_UE_ECACHE_RETIRE, "EDU:ST", 5497c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 5507c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EDUST, 5517c478bd9Sstevel@tonic-gate C_AFSR_EDU, "EDU ", ECC_D_TRAP, 5527c478bd9Sstevel@tonic-gate CPU_UE_ECACHE_RETIRE, "EDU:BLD", 5537c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 5547c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EDUBL, 5557c478bd9Sstevel@tonic-gate C_AFSR_WDU, "WDU ", ECC_C_TRAP, 5567c478bd9Sstevel@tonic-gate CPU_UE_ECACHE_RETIRE, "WDU", 5577c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 5587c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_WDU, 5597c478bd9Sstevel@tonic-gate C_AFSR_CPU, "CPU ", ECC_C_TRAP, 5607c478bd9Sstevel@tonic-gate CPU_UE_ECACHE, "CPU", 5617c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 5627c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_CPU, 5637c478bd9Sstevel@tonic-gate C_AFSR_DUE, "DUE ", ECC_C_TRAP, 5647c478bd9Sstevel@tonic-gate CPU_DUE, "DUE", 5657c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 5667c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_DUE, 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate /* CE, EDC, EMC, WDC, CPC */ 5697c478bd9Sstevel@tonic-gate C_AFSR_CE, "CE ", ECC_C_TRAP, 5707c478bd9Sstevel@tonic-gate CPU_CE, "Corrected system bus (CE)", 5717c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 5727c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_CE, 5737c478bd9Sstevel@tonic-gate C_AFSR_L3_EDC, "L3_EDC ", ECC_C_TRAP, 5747c478bd9Sstevel@tonic-gate CPU_CE_ECACHE, "L3_EDC", 5757c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L3_DATA, 5767c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_L3_EDC, 5777c478bd9Sstevel@tonic-gate C_AFSR_EDC, "EDC ", ECC_C_TRAP, 5787c478bd9Sstevel@tonic-gate CPU_CE_ECACHE, "EDC", 5797c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 5807c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EDC, 5817c478bd9Sstevel@tonic-gate C_AFSR_EMC, "EMC ", ECC_C_TRAP, 5827c478bd9Sstevel@tonic-gate CPU_EMC, "EMC", 5837c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 5847c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EMC, 5857c478bd9Sstevel@tonic-gate C_AFSR_L3_WDC, "L3_WDC ", ECC_C_TRAP, 5867c478bd9Sstevel@tonic-gate CPU_CE_ECACHE, "L3_WDC", 5877c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L3_DATA, 5887c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_L3_WDC, 5897c478bd9Sstevel@tonic-gate C_AFSR_L3_CPC, "L3_CPC ", ECC_C_TRAP, 5907c478bd9Sstevel@tonic-gate CPU_CE_ECACHE, "L3_CPC", 5917c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L3_DATA, 5927c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_L3_CPC, 5937c478bd9Sstevel@tonic-gate C_AFSR_L3_THCE, "L3_THCE ", ECC_C_TRAP, 5947c478bd9Sstevel@tonic-gate CPU_CE_ECACHE, "L3_THCE", 5957c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L3_TAG_ECC, 5967c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_L3_THCE, 5977c478bd9Sstevel@tonic-gate C_AFSR_WDC, "WDC ", ECC_C_TRAP, 5987c478bd9Sstevel@tonic-gate CPU_CE_ECACHE, "WDC", 5997c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 6007c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_WDC, 6017c478bd9Sstevel@tonic-gate C_AFSR_CPC, "CPC ", ECC_C_TRAP, 6027c478bd9Sstevel@tonic-gate CPU_CE_ECACHE, "CPC", 6037c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 6047c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_CPC, 6057c478bd9Sstevel@tonic-gate C_AFSR_THCE, "THCE ", ECC_C_TRAP, 6067c478bd9Sstevel@tonic-gate CPU_CE_ECACHE, "THCE", 6077c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_TAG_ECC, 6087c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_THCE, 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate /* TO, BERR */ 6117c478bd9Sstevel@tonic-gate C_AFSR_TO, "TO ", ECC_ASYNC_TRAPS, 6127c478bd9Sstevel@tonic-gate CPU_TO, "Timeout (TO)", 6137c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_IO, 6147c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_TO, 6157c478bd9Sstevel@tonic-gate C_AFSR_BERR, "BERR ", ECC_ASYNC_TRAPS, 6167c478bd9Sstevel@tonic-gate CPU_BERR, "Bus Error (BERR)", 6177c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_IO, 6187c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_BERR, 6197c478bd9Sstevel@tonic-gate C_AFSR_DTO, "DTO ", ECC_C_TRAP, 6207c478bd9Sstevel@tonic-gate CPU_TO, "Disrupting Timeout (DTO)", 6217c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_IO, 6227c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_DTO, 6237c478bd9Sstevel@tonic-gate C_AFSR_DBERR, "DBERR ", ECC_C_TRAP, 6247c478bd9Sstevel@tonic-gate CPU_BERR, "Disrupting Bus Error (DBERR)", 6257c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_IO, 6267c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_DBERR, 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate /* IVU, IVC, IMC */ 6297c478bd9Sstevel@tonic-gate C_AFSR_IVU, "IVU ", ECC_C_TRAP, 6307c478bd9Sstevel@tonic-gate CPU_IV, "IVU", 6317c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 6327c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IVU, 6337c478bd9Sstevel@tonic-gate C_AFSR_IVC, "IVC ", ECC_C_TRAP, 6347c478bd9Sstevel@tonic-gate CPU_IV, "IVC", 6357c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 6367c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IVC, 6377c478bd9Sstevel@tonic-gate C_AFSR_IMC, "IMC ", ECC_C_TRAP, 6387c478bd9Sstevel@tonic-gate CPU_IV, "IMC", 6397c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 6407c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IMC, 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate 0, NULL, 0, 6437c478bd9Sstevel@tonic-gate 0, NULL, 6447c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_UNKNOWN, 6457c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UNKNOWN, 6467c478bd9Sstevel@tonic-gate }; 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate /* 6497c478bd9Sstevel@tonic-gate * See Cheetah+ Delta PRM 10.9 and section P.6.1 of the Panther PRM 6507c478bd9Sstevel@tonic-gate * Class 4: 6517c478bd9Sstevel@tonic-gate * AFSR -- UCC, UCU, TUE, TSCE, TUE_SH 6527c478bd9Sstevel@tonic-gate * AFSR_EXT -- L3_UCC, L3_UCU, L3_TUE, L3_TUE_SH 6537c478bd9Sstevel@tonic-gate * Class 3: 6547c478bd9Sstevel@tonic-gate * AFSR -- UE, DUE, EDU, EMU, WDU, CPU 6557c478bd9Sstevel@tonic-gate * AFSR_EXT -- L3_EDU, L3_WDU, L3_CPU 6567c478bd9Sstevel@tonic-gate * Class 2: 6577c478bd9Sstevel@tonic-gate * AFSR -- CE, EDC, EMC, WDC, CPC, THCE 6587c478bd9Sstevel@tonic-gate * AFSR_EXT -- L3_EDC, L3_WDC, L3_CPC, L3_THCE 6597c478bd9Sstevel@tonic-gate * Class 1: 6607c478bd9Sstevel@tonic-gate * AFSR -- TO, DTO, BERR, DBERR 6617c478bd9Sstevel@tonic-gate * AFSR_EXT -- 6627c478bd9Sstevel@tonic-gate */ 6637c478bd9Sstevel@tonic-gate uint64_t afar_overwrite[] = { 6647c478bd9Sstevel@tonic-gate /* class 4: */ 6657c478bd9Sstevel@tonic-gate C_AFSR_UCC | C_AFSR_UCU | C_AFSR_TUE | C_AFSR_TSCE | C_AFSR_TUE_SH | 6667c478bd9Sstevel@tonic-gate C_AFSR_L3_UCC | C_AFSR_L3_UCU | C_AFSR_L3_TUE | C_AFSR_L3_TUE_SH, 6677c478bd9Sstevel@tonic-gate /* class 3: */ 6687c478bd9Sstevel@tonic-gate C_AFSR_UE | C_AFSR_DUE | C_AFSR_EDU | C_AFSR_EMU | C_AFSR_WDU | 6697c478bd9Sstevel@tonic-gate C_AFSR_CPU | C_AFSR_L3_EDU | C_AFSR_L3_WDU | C_AFSR_L3_CPU, 6707c478bd9Sstevel@tonic-gate /* class 2: */ 6717c478bd9Sstevel@tonic-gate C_AFSR_CE | C_AFSR_EDC | C_AFSR_EMC | C_AFSR_WDC | C_AFSR_CPC | 6727c478bd9Sstevel@tonic-gate C_AFSR_THCE | C_AFSR_L3_EDC | C_AFSR_L3_WDC | C_AFSR_L3_CPC | 6737c478bd9Sstevel@tonic-gate C_AFSR_L3_THCE, 6747c478bd9Sstevel@tonic-gate /* class 1: */ 6757c478bd9Sstevel@tonic-gate C_AFSR_TO | C_AFSR_DTO | C_AFSR_BERR | C_AFSR_DBERR, 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate 0 6787c478bd9Sstevel@tonic-gate }; 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate /* 68193743541Smb91622 * For Cheetah+, the E_SYND and M_SYND overwrite priorities are combined. 68293743541Smb91622 * See Cheetah+ Delta PRM 10.9 and Cheetah+ PRM 11.6.2 68393743541Smb91622 * Class 2: UE, DUE, IVU, EDU, EMU, WDU, UCU, CPU 68493743541Smb91622 * Class 1: CE, IVC, EDC, EMC, WDC, UCC, CPC 6857c478bd9Sstevel@tonic-gate */ 6867c478bd9Sstevel@tonic-gate uint64_t esynd_overwrite[] = { 6877c478bd9Sstevel@tonic-gate /* class 2: */ 68893743541Smb91622 C_AFSR_UE | C_AFSR_DUE | C_AFSR_IVU | C_AFSR_EDU | C_AFSR_EMU | 68993743541Smb91622 C_AFSR_WDU | C_AFSR_UCU | C_AFSR_CPU, 6907c478bd9Sstevel@tonic-gate /* class 1: */ 69193743541Smb91622 C_AFSR_CE | C_AFSR_IVC | C_AFSR_EDC | C_AFSR_EMC | C_AFSR_WDC | 69293743541Smb91622 C_AFSR_UCC | C_AFSR_CPC, 6937c478bd9Sstevel@tonic-gate 0 6947c478bd9Sstevel@tonic-gate }; 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate /* 6977c478bd9Sstevel@tonic-gate * In panther, the E_SYND overwrite policy changed a little bit 6987c478bd9Sstevel@tonic-gate * by adding one more level. 69993743541Smb91622 * See Panther PRM P.6.2 7007c478bd9Sstevel@tonic-gate * class 3: 7017c478bd9Sstevel@tonic-gate * AFSR -- UCU, UCC 7027c478bd9Sstevel@tonic-gate * AFSR_EXT -- L3_UCU, L3_UCC 7037c478bd9Sstevel@tonic-gate * Class 2: 7047c478bd9Sstevel@tonic-gate * AFSR -- UE, DUE, IVU, EDU, WDU, CPU 7057c478bd9Sstevel@tonic-gate * AFSR_EXT -- L3_EDU, L3_WDU, L3_CPU 7067c478bd9Sstevel@tonic-gate * Class 1: 7077c478bd9Sstevel@tonic-gate * AFSR -- CE, IVC, EDC, WDC, CPC 7087c478bd9Sstevel@tonic-gate * AFSR_EXT -- L3_EDC, L3_WDC, L3_CPC 7097c478bd9Sstevel@tonic-gate */ 7107c478bd9Sstevel@tonic-gate uint64_t pn_esynd_overwrite[] = { 7117c478bd9Sstevel@tonic-gate /* class 3: */ 7127c478bd9Sstevel@tonic-gate C_AFSR_UCU | C_AFSR_UCC | 7137c478bd9Sstevel@tonic-gate C_AFSR_L3_UCU | C_AFSR_L3_UCC, 7147c478bd9Sstevel@tonic-gate /* class 2: */ 7157c478bd9Sstevel@tonic-gate C_AFSR_UE | C_AFSR_DUE | C_AFSR_IVU | C_AFSR_EDU | C_AFSR_WDU | 7167c478bd9Sstevel@tonic-gate C_AFSR_CPU | 7177c478bd9Sstevel@tonic-gate C_AFSR_L3_EDU | C_AFSR_L3_WDU | C_AFSR_L3_CPU, 7187c478bd9Sstevel@tonic-gate /* class 1: */ 7197c478bd9Sstevel@tonic-gate C_AFSR_CE | C_AFSR_IVC | C_AFSR_EDC | C_AFSR_WDC | C_AFSR_CPC | 7207c478bd9Sstevel@tonic-gate C_AFSR_L3_EDC | C_AFSR_L3_WDC | C_AFSR_L3_CPC, 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate 0 7237c478bd9Sstevel@tonic-gate }; 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate int 7267c478bd9Sstevel@tonic-gate afsr_to_pn_esynd_status(uint64_t afsr, uint64_t afsr_bit) 7277c478bd9Sstevel@tonic-gate { 7287c478bd9Sstevel@tonic-gate return (afsr_to_overw_status(afsr, afsr_bit, pn_esynd_overwrite)); 7297c478bd9Sstevel@tonic-gate } 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate /* 7327c478bd9Sstevel@tonic-gate * Prioritized list of Error bits for MSYND overwrite. 73393743541Smb91622 * See Panther PRM P.6.2 (For Cheetah+, see esynd_overwrite classes) 73493743541Smb91622 * Class 2: EMU, IMU 73593743541Smb91622 * Class 1: EMC, IMC 7367c478bd9Sstevel@tonic-gate * 7377c478bd9Sstevel@tonic-gate * Panther adds IMU and IMC. 7387c478bd9Sstevel@tonic-gate */ 7397c478bd9Sstevel@tonic-gate uint64_t msynd_overwrite[] = { 7407c478bd9Sstevel@tonic-gate /* class 2: */ 7417c478bd9Sstevel@tonic-gate C_AFSR_EMU | C_AFSR_IMU, 7427c478bd9Sstevel@tonic-gate /* class 1: */ 7437c478bd9Sstevel@tonic-gate C_AFSR_EMC | C_AFSR_IMC, 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate 0 7467c478bd9Sstevel@tonic-gate }; 7477c478bd9Sstevel@tonic-gate 7487c478bd9Sstevel@tonic-gate /* 7497c478bd9Sstevel@tonic-gate * change cpu speed bits -- new speed will be normal-speed/divisor. 7507c478bd9Sstevel@tonic-gate * 7517c478bd9Sstevel@tonic-gate * The Jalapeno memory controllers are required to drain outstanding 7527c478bd9Sstevel@tonic-gate * memory transactions within 32 JBus clocks in order to be ready 7537c478bd9Sstevel@tonic-gate * to enter Estar mode. In some corner cases however, that time 7547c478bd9Sstevel@tonic-gate * fell short. 7557c478bd9Sstevel@tonic-gate * 7567c478bd9Sstevel@tonic-gate * A safe software solution is to force MCU to act like in Estar mode, 7577c478bd9Sstevel@tonic-gate * then delay 1us (in ppm code) prior to assert J_CHNG_L signal. 7587c478bd9Sstevel@tonic-gate * To reverse the effect, upon exiting Estar, software restores the 7597c478bd9Sstevel@tonic-gate * MCU to its original state. 7607c478bd9Sstevel@tonic-gate */ 7617c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 7627c478bd9Sstevel@tonic-gate void 7637c478bd9Sstevel@tonic-gate cpu_change_speed(uint64_t divisor, uint64_t arg2) 7647c478bd9Sstevel@tonic-gate { 7657c478bd9Sstevel@tonic-gate bus_config_eclk_t *bceclk; 7667c478bd9Sstevel@tonic-gate uint64_t reg; 7675cff7825Smh27603 processor_info_t *pi = &(CPU->cpu_type_info); 7687c478bd9Sstevel@tonic-gate 7697c478bd9Sstevel@tonic-gate for (bceclk = bus_config_eclk; bceclk->divisor; bceclk++) { 7707c478bd9Sstevel@tonic-gate if (bceclk->divisor != divisor) 7717c478bd9Sstevel@tonic-gate continue; 7727c478bd9Sstevel@tonic-gate reg = get_safari_config(); 7737c478bd9Sstevel@tonic-gate reg &= ~SAFARI_CONFIG_ECLK_MASK; 7747c478bd9Sstevel@tonic-gate reg |= bceclk->mask; 7757c478bd9Sstevel@tonic-gate set_safari_config(reg); 7767c478bd9Sstevel@tonic-gate CPU->cpu_m.divisor = (uchar_t)divisor; 777*0e751525SEric Saxe cpu_set_curr_clock(((uint64_t)pi->pi_clock * 1000000) / 778*0e751525SEric Saxe divisor); 7797c478bd9Sstevel@tonic-gate return; 7807c478bd9Sstevel@tonic-gate } 7817c478bd9Sstevel@tonic-gate /* 7827c478bd9Sstevel@tonic-gate * We will reach here only if OBP and kernel don't agree on 7837c478bd9Sstevel@tonic-gate * the speeds supported by the CPU. 7847c478bd9Sstevel@tonic-gate */ 7857c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "cpu_change_speed: bad divisor %" PRIu64, divisor); 7867c478bd9Sstevel@tonic-gate } 7877c478bd9Sstevel@tonic-gate 7887c478bd9Sstevel@tonic-gate /* 7897c478bd9Sstevel@tonic-gate * Cpu private initialization. This includes allocating the cpu_private 7907c478bd9Sstevel@tonic-gate * data structure, initializing it, and initializing the scrubber for this 7917c478bd9Sstevel@tonic-gate * cpu. This function calls cpu_init_ecache_scrub_dr to init the scrubber. 7927c478bd9Sstevel@tonic-gate * We use kmem_cache_create for the cheetah private data structure because 7937c478bd9Sstevel@tonic-gate * it needs to be allocated on a PAGESIZE (8192) byte boundary. 7947c478bd9Sstevel@tonic-gate */ 7957c478bd9Sstevel@tonic-gate void 7967c478bd9Sstevel@tonic-gate cpu_init_private(struct cpu *cp) 7977c478bd9Sstevel@tonic-gate { 7987c478bd9Sstevel@tonic-gate cheetah_private_t *chprp; 7997c478bd9Sstevel@tonic-gate int i; 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate ASSERT(CPU_PRIVATE(cp) == NULL); 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate /* LINTED: E_TRUE_LOGICAL_EXPR */ 8047c478bd9Sstevel@tonic-gate ASSERT((offsetof(cheetah_private_t, chpr_tl1_err_data) + 8057c478bd9Sstevel@tonic-gate sizeof (ch_err_tl1_data_t) * CH_ERR_TL1_TLMAX) <= PAGESIZE); 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate /* 8087c478bd9Sstevel@tonic-gate * Running with Cheetah CPUs in a Cheetah+, Jaguar, Panther or 8097c478bd9Sstevel@tonic-gate * mixed Cheetah+/Jaguar/Panther machine is not a supported 8107c478bd9Sstevel@tonic-gate * configuration. Attempting to do so may result in unpredictable 8117c478bd9Sstevel@tonic-gate * failures (e.g. running Cheetah+ CPUs with Cheetah E$ disp flush) 8127c478bd9Sstevel@tonic-gate * so don't allow it. 8137c478bd9Sstevel@tonic-gate * 8147c478bd9Sstevel@tonic-gate * This is just defensive code since this configuration mismatch 8157c478bd9Sstevel@tonic-gate * should have been caught prior to OS execution. 8167c478bd9Sstevel@tonic-gate */ 8177c478bd9Sstevel@tonic-gate if (!(IS_CHEETAH_PLUS(cpunodes[cp->cpu_id].implementation) || 8187c478bd9Sstevel@tonic-gate IS_JAGUAR(cpunodes[cp->cpu_id].implementation) || 8197c478bd9Sstevel@tonic-gate IS_PANTHER(cpunodes[cp->cpu_id].implementation))) { 8207c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "CPU%d: UltraSPARC-III not supported" 8217c478bd9Sstevel@tonic-gate " on UltraSPARC-III+/IV/IV+ code\n", cp->cpu_id); 8227c478bd9Sstevel@tonic-gate } 8237c478bd9Sstevel@tonic-gate 8247c478bd9Sstevel@tonic-gate /* 8257c478bd9Sstevel@tonic-gate * If the ch_private_cache has not been created, create it. 8267c478bd9Sstevel@tonic-gate */ 8277c478bd9Sstevel@tonic-gate if (ch_private_cache == NULL) { 8287c478bd9Sstevel@tonic-gate ch_private_cache = kmem_cache_create("ch_private_cache", 8297c478bd9Sstevel@tonic-gate sizeof (cheetah_private_t), PAGESIZE, NULL, NULL, 8307c478bd9Sstevel@tonic-gate NULL, NULL, static_arena, 0); 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate chprp = CPU_PRIVATE(cp) = kmem_cache_alloc(ch_private_cache, KM_SLEEP); 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate bzero(chprp, sizeof (cheetah_private_t)); 8367c478bd9Sstevel@tonic-gate chprp->chpr_fecctl0_logout.clo_data.chd_afar = LOGOUT_INVALID; 8377c478bd9Sstevel@tonic-gate chprp->chpr_cecc_logout.clo_data.chd_afar = LOGOUT_INVALID; 8387c478bd9Sstevel@tonic-gate chprp->chpr_async_logout.clo_data.chd_afar = LOGOUT_INVALID; 8397c478bd9Sstevel@tonic-gate chprp->chpr_tlb_logout.tlo_addr = LOGOUT_INVALID; 8407c478bd9Sstevel@tonic-gate for (i = 0; i < CH_ERR_TL1_TLMAX; i++) 8417c478bd9Sstevel@tonic-gate chprp->chpr_tl1_err_data[i].ch_err_tl1_logout.clo_data.chd_afar 8427c478bd9Sstevel@tonic-gate = LOGOUT_INVALID; 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate /* Panther has a larger Icache compared to cheetahplus or Jaguar */ 8457c478bd9Sstevel@tonic-gate if (IS_PANTHER(cpunodes[cp->cpu_id].implementation)) { 8467c478bd9Sstevel@tonic-gate chprp->chpr_icache_size = PN_ICACHE_SIZE; 8477c478bd9Sstevel@tonic-gate chprp->chpr_icache_linesize = PN_ICACHE_LSIZE; 8487c478bd9Sstevel@tonic-gate } else { 8497c478bd9Sstevel@tonic-gate chprp->chpr_icache_size = CH_ICACHE_SIZE; 8507c478bd9Sstevel@tonic-gate chprp->chpr_icache_linesize = CH_ICACHE_LSIZE; 8517c478bd9Sstevel@tonic-gate } 8527c478bd9Sstevel@tonic-gate 8537c478bd9Sstevel@tonic-gate cpu_init_ecache_scrub_dr(cp); 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate /* 8567c478bd9Sstevel@tonic-gate * Panther's L2$ and E$ are shared between cores, so the scrubber is 8577c478bd9Sstevel@tonic-gate * only needed on one of the cores. At this point, we assume all cores 8587c478bd9Sstevel@tonic-gate * are online, and we only enable the scrubber on core 0. 8597c478bd9Sstevel@tonic-gate */ 8607c478bd9Sstevel@tonic-gate if (IS_PANTHER(cpunodes[cp->cpu_id].implementation)) { 8617c478bd9Sstevel@tonic-gate chprp->chpr_scrub_misc.chsm_core_state = 8627c478bd9Sstevel@tonic-gate SCRUBBER_BOTH_CORES_ONLINE; 8637c478bd9Sstevel@tonic-gate if (cp->cpu_id != (processorid_t)cmp_cpu_to_chip(cp->cpu_id)) { 8647c478bd9Sstevel@tonic-gate chprp->chpr_scrub_misc.chsm_enable[ 8657c478bd9Sstevel@tonic-gate CACHE_SCRUBBER_INFO_E] = 0; 8667c478bd9Sstevel@tonic-gate } 8677c478bd9Sstevel@tonic-gate } 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate chprp->chpr_ec_set_size = cpunodes[cp->cpu_id].ecache_size / 8707c478bd9Sstevel@tonic-gate cpu_ecache_nway(); 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate adjust_hw_copy_limits(cpunodes[cp->cpu_id].ecache_size); 8737c478bd9Sstevel@tonic-gate ch_err_tl1_paddrs[cp->cpu_id] = va_to_pa(chprp); 8747c478bd9Sstevel@tonic-gate ASSERT(ch_err_tl1_paddrs[cp->cpu_id] != -1); 8757c478bd9Sstevel@tonic-gate } 8767c478bd9Sstevel@tonic-gate 8777c478bd9Sstevel@tonic-gate /* 8787c478bd9Sstevel@tonic-gate * Clear the error state registers for this CPU. 8797c478bd9Sstevel@tonic-gate * For Cheetah+/Jaguar, just clear the AFSR but 8807c478bd9Sstevel@tonic-gate * for Panther we also have to clear the AFSR_EXT. 8817c478bd9Sstevel@tonic-gate */ 8827c478bd9Sstevel@tonic-gate void 8837c478bd9Sstevel@tonic-gate set_cpu_error_state(ch_cpu_errors_t *cpu_error_regs) 8847c478bd9Sstevel@tonic-gate { 8857c478bd9Sstevel@tonic-gate set_asyncflt(cpu_error_regs->afsr & ~C_AFSR_FATAL_ERRS); 8867c478bd9Sstevel@tonic-gate if (IS_PANTHER(cpunodes[CPU->cpu_id].implementation)) { 8877c478bd9Sstevel@tonic-gate set_afsr_ext(cpu_error_regs->afsr_ext & ~C_AFSR_EXT_FATAL_ERRS); 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate } 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate void 8927c478bd9Sstevel@tonic-gate pn_cpu_log_diag_l2_info(ch_async_flt_t *ch_flt) { 8937c478bd9Sstevel@tonic-gate struct async_flt *aflt = (struct async_flt *)ch_flt; 8947c478bd9Sstevel@tonic-gate ch_ec_data_t *l2_data = &ch_flt->flt_diag_data.chd_l2_data[0]; 8957c478bd9Sstevel@tonic-gate uint64_t faddr = aflt->flt_addr; 8967c478bd9Sstevel@tonic-gate uint8_t log_way_mask = 0; 8977c478bd9Sstevel@tonic-gate int i; 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate /* 9007c478bd9Sstevel@tonic-gate * Only Panther CPUs have the additional L2$ data that needs 9017c478bd9Sstevel@tonic-gate * to be logged here 9027c478bd9Sstevel@tonic-gate */ 9037c478bd9Sstevel@tonic-gate if (!IS_PANTHER(cpunodes[aflt->flt_inst].implementation)) 9047c478bd9Sstevel@tonic-gate return; 9057c478bd9Sstevel@tonic-gate 9067c478bd9Sstevel@tonic-gate /* 9077c478bd9Sstevel@tonic-gate * We'll use a simple bit mask to keep track of which way(s) 9087c478bd9Sstevel@tonic-gate * of the stored cache line we want to log. The idea is to 9097c478bd9Sstevel@tonic-gate * log the entry if it is a valid line and it matches our 9107c478bd9Sstevel@tonic-gate * fault AFAR. If no match is found, we will simply log all 9117c478bd9Sstevel@tonic-gate * the ways. 9127c478bd9Sstevel@tonic-gate */ 9137c478bd9Sstevel@tonic-gate for (i = 0; i < PN_L2_NWAYS; i++) 9147c478bd9Sstevel@tonic-gate if (pn_matching_valid_l2_line(faddr, &l2_data[i])) 9157c478bd9Sstevel@tonic-gate log_way_mask |= (1 << i); 9167c478bd9Sstevel@tonic-gate 9177c478bd9Sstevel@tonic-gate /* If no matching valid lines were found, we log all ways */ 9187c478bd9Sstevel@tonic-gate if (log_way_mask == 0) 9197c478bd9Sstevel@tonic-gate log_way_mask = (1 << PN_L2_NWAYS) - 1; 9207c478bd9Sstevel@tonic-gate 9217c478bd9Sstevel@tonic-gate /* Log the cache lines */ 9227c478bd9Sstevel@tonic-gate for (i = 0; i < PN_L2_NWAYS; i++) 9237c478bd9Sstevel@tonic-gate if (log_way_mask & (1 << i)) 9247c478bd9Sstevel@tonic-gate l2_data[i].ec_logflag = EC_LOGFLAG_MAGIC; 9257c478bd9Sstevel@tonic-gate } 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate /* 9287c478bd9Sstevel@tonic-gate * For this routine to return true, the L2 tag in question must be valid 9297c478bd9Sstevel@tonic-gate * and the tag PA must match the fault address (faddr) assuming the correct 9307c478bd9Sstevel@tonic-gate * index is being used. 9317c478bd9Sstevel@tonic-gate */ 9327c478bd9Sstevel@tonic-gate static int 9337c478bd9Sstevel@tonic-gate pn_matching_valid_l2_line(uint64_t faddr, ch_ec_data_t *clo_l2_data) { 9347c478bd9Sstevel@tonic-gate if ((!PN_L2_LINE_INVALID(clo_l2_data->ec_tag)) && 9357c478bd9Sstevel@tonic-gate ((faddr & P2ALIGN(C_AFAR_PA, PN_L2_SET_SIZE)) == 9367c478bd9Sstevel@tonic-gate PN_L2TAG_TO_PA(clo_l2_data->ec_tag))) 9377c478bd9Sstevel@tonic-gate return (1); 9387c478bd9Sstevel@tonic-gate return (0); 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate /* 9427c478bd9Sstevel@tonic-gate * This array is used to convert the 3 digit PgSz encoding (as used in 9437c478bd9Sstevel@tonic-gate * various MMU registers such as MMU_TAG_ACCESS_EXT) into the corresponding 9447c478bd9Sstevel@tonic-gate * page size. 9457c478bd9Sstevel@tonic-gate */ 9467c478bd9Sstevel@tonic-gate static uint64_t tlb_pgsz_to_size[] = { 9477c478bd9Sstevel@tonic-gate /* 000 = 8KB: */ 9487c478bd9Sstevel@tonic-gate 0x2000, 9497c478bd9Sstevel@tonic-gate /* 001 = 64KB: */ 9507c478bd9Sstevel@tonic-gate 0x10000, 9517c478bd9Sstevel@tonic-gate /* 010 = 512KB: */ 9527c478bd9Sstevel@tonic-gate 0x80000, 9537c478bd9Sstevel@tonic-gate /* 011 = 4MB: */ 9547c478bd9Sstevel@tonic-gate 0x400000, 9557c478bd9Sstevel@tonic-gate /* 100 = 32MB: */ 9567c478bd9Sstevel@tonic-gate 0x2000000, 9577c478bd9Sstevel@tonic-gate /* 101 = 256MB: */ 9587c478bd9Sstevel@tonic-gate 0x10000000, 9597c478bd9Sstevel@tonic-gate /* undefined for encodings 110 and 111: */ 9607c478bd9Sstevel@tonic-gate 0, 0 9617c478bd9Sstevel@tonic-gate }; 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate /* 9647c478bd9Sstevel@tonic-gate * The itlb_parity_trap and dtlb_parity_trap handlers transfer control here 9657c478bd9Sstevel@tonic-gate * after collecting logout information related to the TLB parity error and 9667c478bd9Sstevel@tonic-gate * flushing the offending TTE entries from the ITLB or DTLB. 9677c478bd9Sstevel@tonic-gate * 9687c478bd9Sstevel@tonic-gate * DTLB traps which occur at TL>0 are not recoverable because we will most 9697c478bd9Sstevel@tonic-gate * likely be corrupting some other trap handler's alternate globals. As 9707c478bd9Sstevel@tonic-gate * such, we simply panic here when that happens. ITLB parity errors are 9717c478bd9Sstevel@tonic-gate * not expected to happen at TL>0. 9727c478bd9Sstevel@tonic-gate */ 9737c478bd9Sstevel@tonic-gate void 9747c478bd9Sstevel@tonic-gate cpu_tlb_parity_error(struct regs *rp, ulong_t trap_va, ulong_t tlb_info) { 9757c478bd9Sstevel@tonic-gate ch_async_flt_t ch_flt; 9767c478bd9Sstevel@tonic-gate struct async_flt *aflt; 9777c478bd9Sstevel@tonic-gate pn_tlb_logout_t *tlop = NULL; 9787c478bd9Sstevel@tonic-gate int immu_parity = (tlb_info & PN_TLO_INFO_IMMU) != 0; 9797c478bd9Sstevel@tonic-gate int tl1_trap = (tlb_info & PN_TLO_INFO_TL1) != 0; 9807c478bd9Sstevel@tonic-gate char *error_class; 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate bzero(&ch_flt, sizeof (ch_async_flt_t)); 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate /* 9857c478bd9Sstevel@tonic-gate * Get the CPU log out info. If we can't find our CPU private 9867c478bd9Sstevel@tonic-gate * pointer, or if the logout information does not correspond to 9877c478bd9Sstevel@tonic-gate * this error, then we will have to make due without detailed 9887c478bd9Sstevel@tonic-gate * logout information. 9897c478bd9Sstevel@tonic-gate */ 9907c478bd9Sstevel@tonic-gate if (CPU_PRIVATE(CPU)) { 9917c478bd9Sstevel@tonic-gate tlop = CPU_PRIVATE_PTR(CPU, chpr_tlb_logout); 9927c478bd9Sstevel@tonic-gate if ((tlop->tlo_addr != trap_va) || 9937c478bd9Sstevel@tonic-gate (tlop->tlo_info != tlb_info)) 9947c478bd9Sstevel@tonic-gate tlop = NULL; 9957c478bd9Sstevel@tonic-gate } 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate if (tlop) { 9987c478bd9Sstevel@tonic-gate ch_flt.tlb_diag_data = *tlop; 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate /* Zero out + invalidate TLB logout. */ 10017c478bd9Sstevel@tonic-gate bzero(tlop, sizeof (pn_tlb_logout_t)); 10027c478bd9Sstevel@tonic-gate tlop->tlo_addr = LOGOUT_INVALID; 10037c478bd9Sstevel@tonic-gate } else { 10047c478bd9Sstevel@tonic-gate /* 10057c478bd9Sstevel@tonic-gate * Copy what logout information we have and mark 10067c478bd9Sstevel@tonic-gate * it incomplete. 10077c478bd9Sstevel@tonic-gate */ 10087c478bd9Sstevel@tonic-gate ch_flt.flt_data_incomplete = 1; 10097c478bd9Sstevel@tonic-gate ch_flt.tlb_diag_data.tlo_info = tlb_info; 10107c478bd9Sstevel@tonic-gate ch_flt.tlb_diag_data.tlo_addr = trap_va; 10117c478bd9Sstevel@tonic-gate } 10127c478bd9Sstevel@tonic-gate 10137c478bd9Sstevel@tonic-gate /* 10147c478bd9Sstevel@tonic-gate * Log the error. 10157c478bd9Sstevel@tonic-gate */ 10167c478bd9Sstevel@tonic-gate aflt = (struct async_flt *)&ch_flt; 10177c478bd9Sstevel@tonic-gate aflt->flt_id = gethrtime_waitfree(); 10187c478bd9Sstevel@tonic-gate aflt->flt_bus_id = getprocessorid(); 10197c478bd9Sstevel@tonic-gate aflt->flt_inst = CPU->cpu_id; 10207c478bd9Sstevel@tonic-gate aflt->flt_pc = (caddr_t)rp->r_pc; 10217c478bd9Sstevel@tonic-gate aflt->flt_addr = trap_va; 10227c478bd9Sstevel@tonic-gate aflt->flt_prot = AFLT_PROT_NONE; 10237c478bd9Sstevel@tonic-gate aflt->flt_class = CPU_FAULT; 10247c478bd9Sstevel@tonic-gate aflt->flt_priv = (rp->r_tstate & TSTATE_PRIV) ? 1 : 0; 10257c478bd9Sstevel@tonic-gate aflt->flt_tl = tl1_trap ? 1 : 0; 10267c478bd9Sstevel@tonic-gate aflt->flt_panic = tl1_trap ? 1 : 0; 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate if (immu_parity) { 10297c478bd9Sstevel@tonic-gate aflt->flt_status = ECC_ITLB_TRAP; 10307c478bd9Sstevel@tonic-gate ch_flt.flt_type = CPU_ITLB_PARITY; 10317c478bd9Sstevel@tonic-gate error_class = FM_EREPORT_CPU_USIII_ITLBPE; 10327c478bd9Sstevel@tonic-gate aflt->flt_payload = FM_EREPORT_PAYLOAD_ITLB_PE; 10337c478bd9Sstevel@tonic-gate } else { 10347c478bd9Sstevel@tonic-gate aflt->flt_status = ECC_DTLB_TRAP; 10357c478bd9Sstevel@tonic-gate ch_flt.flt_type = CPU_DTLB_PARITY; 10367c478bd9Sstevel@tonic-gate error_class = FM_EREPORT_CPU_USIII_DTLBPE; 10377c478bd9Sstevel@tonic-gate aflt->flt_payload = FM_EREPORT_PAYLOAD_DTLB_PE; 10387c478bd9Sstevel@tonic-gate } 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate /* 10417c478bd9Sstevel@tonic-gate * The TLB entries have already been flushed by the TL1 trap 10427c478bd9Sstevel@tonic-gate * handler so at this point the only thing left to do is log 10437c478bd9Sstevel@tonic-gate * the error message. 10447c478bd9Sstevel@tonic-gate */ 10457c478bd9Sstevel@tonic-gate if (aflt->flt_panic) { 10467c478bd9Sstevel@tonic-gate cpu_errorq_dispatch(error_class, (void *)&ch_flt, 10477c478bd9Sstevel@tonic-gate sizeof (ch_async_flt_t), ue_queue, aflt->flt_panic); 10487c478bd9Sstevel@tonic-gate /* 10497c478bd9Sstevel@tonic-gate * Panic here if aflt->flt_panic has been set. Enqueued 10507c478bd9Sstevel@tonic-gate * errors will be logged as part of the panic flow. 10517c478bd9Sstevel@tonic-gate */ 10527c478bd9Sstevel@tonic-gate fm_panic("%sError(s)", immu_parity ? "ITLBPE " : "DTLBPE "); 10537c478bd9Sstevel@tonic-gate } else { 10547c478bd9Sstevel@tonic-gate cpu_errorq_dispatch(error_class, (void *)&ch_flt, 10557c478bd9Sstevel@tonic-gate sizeof (ch_async_flt_t), ce_queue, aflt->flt_panic); 10567c478bd9Sstevel@tonic-gate } 10577c478bd9Sstevel@tonic-gate } 10587c478bd9Sstevel@tonic-gate 10597c478bd9Sstevel@tonic-gate /* 10607c478bd9Sstevel@tonic-gate * This routine is called when a TLB parity error event is 'ue_drain'ed 10617c478bd9Sstevel@tonic-gate * or 'ce_drain'ed from the errorq. 10627c478bd9Sstevel@tonic-gate */ 10637c478bd9Sstevel@tonic-gate void 10647c478bd9Sstevel@tonic-gate cpu_async_log_tlb_parity_err(void *flt) { 10657c478bd9Sstevel@tonic-gate ch_async_flt_t *ch_flt = (ch_async_flt_t *)flt; 10667c478bd9Sstevel@tonic-gate struct async_flt *aflt = (struct async_flt *)flt; 10677c478bd9Sstevel@tonic-gate #ifdef lint 10687c478bd9Sstevel@tonic-gate aflt = aflt; 10697c478bd9Sstevel@tonic-gate #endif 10707c478bd9Sstevel@tonic-gate 10717c478bd9Sstevel@tonic-gate /* 10727c478bd9Sstevel@tonic-gate * We only capture TLB information if we encountered 10737c478bd9Sstevel@tonic-gate * a TLB parity error and Panther is the only CPU which 10747c478bd9Sstevel@tonic-gate * can detect a TLB parity error. 10757c478bd9Sstevel@tonic-gate */ 10767c478bd9Sstevel@tonic-gate ASSERT(IS_PANTHER(cpunodes[aflt->flt_inst].implementation)); 10777c478bd9Sstevel@tonic-gate ASSERT((ch_flt->flt_type == CPU_ITLB_PARITY) || 10787c478bd9Sstevel@tonic-gate (ch_flt->flt_type == CPU_DTLB_PARITY)); 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate if (ch_flt->flt_data_incomplete == 0) { 10817c478bd9Sstevel@tonic-gate if (ch_flt->flt_type == CPU_ITLB_PARITY) 10827c478bd9Sstevel@tonic-gate ch_flt->tlb_diag_data.tlo_logflag = IT_LOGFLAG_MAGIC; 10837c478bd9Sstevel@tonic-gate else /* parity error is in DTLB */ 10847c478bd9Sstevel@tonic-gate ch_flt->tlb_diag_data.tlo_logflag = DT_LOGFLAG_MAGIC; 10857c478bd9Sstevel@tonic-gate } 10867c478bd9Sstevel@tonic-gate } 10877c478bd9Sstevel@tonic-gate 10887c478bd9Sstevel@tonic-gate /* 10897c478bd9Sstevel@tonic-gate * Add L1 Prefetch cache data to the ereport payload. 10907c478bd9Sstevel@tonic-gate */ 10917c478bd9Sstevel@tonic-gate void 10927c478bd9Sstevel@tonic-gate cpu_payload_add_pcache(struct async_flt *aflt, nvlist_t *nvl) 10937c478bd9Sstevel@tonic-gate { 10947c478bd9Sstevel@tonic-gate ch_async_flt_t *ch_flt = (ch_async_flt_t *)aflt; 10957c478bd9Sstevel@tonic-gate ch_pc_data_t *pcp; 10967c478bd9Sstevel@tonic-gate ch_pc_data_t pcdata[CH_PCACHE_NWAY]; 10977c478bd9Sstevel@tonic-gate uint_t nelem; 10987c478bd9Sstevel@tonic-gate int i, ways_logged = 0; 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate /* 11017c478bd9Sstevel@tonic-gate * We only capture P$ information if we encountered 11027c478bd9Sstevel@tonic-gate * a P$ parity error and Panther is the only CPU which 11037c478bd9Sstevel@tonic-gate * can detect a P$ parity error. 11047c478bd9Sstevel@tonic-gate */ 11057c478bd9Sstevel@tonic-gate ASSERT(IS_PANTHER(cpunodes[aflt->flt_inst].implementation)); 11067c478bd9Sstevel@tonic-gate for (i = 0; i < CH_PCACHE_NWAY; i++) { 11077c478bd9Sstevel@tonic-gate pcp = &ch_flt->parity_data.dpe.cpl_pc[i]; 11087c478bd9Sstevel@tonic-gate if (pcp->pc_logflag == PC_LOGFLAG_MAGIC) { 11097c478bd9Sstevel@tonic-gate bcopy(pcp, &pcdata[ways_logged], 11107c478bd9Sstevel@tonic-gate sizeof (ch_pc_data_t)); 11117c478bd9Sstevel@tonic-gate ways_logged++; 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate /* 11167c478bd9Sstevel@tonic-gate * Add the pcache data to the payload. 11177c478bd9Sstevel@tonic-gate */ 11187c478bd9Sstevel@tonic-gate fm_payload_set(nvl, FM_EREPORT_PAYLOAD_NAME_L1P_WAYS, 11197c478bd9Sstevel@tonic-gate DATA_TYPE_UINT8, (uint8_t)ways_logged, NULL); 11207c478bd9Sstevel@tonic-gate if (ways_logged != 0) { 11217c478bd9Sstevel@tonic-gate nelem = sizeof (ch_pc_data_t) / sizeof (uint64_t) * ways_logged; 11227c478bd9Sstevel@tonic-gate fm_payload_set(nvl, FM_EREPORT_PAYLOAD_NAME_L1P_DATA, 11237c478bd9Sstevel@tonic-gate DATA_TYPE_UINT64_ARRAY, nelem, (uint64_t *)pcdata, NULL); 11247c478bd9Sstevel@tonic-gate } 11257c478bd9Sstevel@tonic-gate } 11267c478bd9Sstevel@tonic-gate 11277c478bd9Sstevel@tonic-gate /* 11287c478bd9Sstevel@tonic-gate * Add TLB diagnostic data to the ereport payload. 11297c478bd9Sstevel@tonic-gate */ 11307c478bd9Sstevel@tonic-gate void 11317c478bd9Sstevel@tonic-gate cpu_payload_add_tlb(struct async_flt *aflt, nvlist_t *nvl) 11327c478bd9Sstevel@tonic-gate { 11337c478bd9Sstevel@tonic-gate ch_async_flt_t *ch_flt = (ch_async_flt_t *)aflt; 11347c478bd9Sstevel@tonic-gate uint8_t num_entries, tlb_data_words; 11357c478bd9Sstevel@tonic-gate 11367c478bd9Sstevel@tonic-gate /* 11377c478bd9Sstevel@tonic-gate * We only capture TLB information if we encountered 11387c478bd9Sstevel@tonic-gate * a TLB parity error and Panther is the only CPU which 11397c478bd9Sstevel@tonic-gate * can detect a TLB parity error. 11407c478bd9Sstevel@tonic-gate */ 11417c478bd9Sstevel@tonic-gate ASSERT(IS_PANTHER(cpunodes[aflt->flt_inst].implementation)); 11427c478bd9Sstevel@tonic-gate ASSERT((ch_flt->flt_type == CPU_ITLB_PARITY) || 11437c478bd9Sstevel@tonic-gate (ch_flt->flt_type == CPU_DTLB_PARITY)); 11447c478bd9Sstevel@tonic-gate 11457c478bd9Sstevel@tonic-gate if (ch_flt->flt_type == CPU_ITLB_PARITY) { 11467c478bd9Sstevel@tonic-gate num_entries = (uint8_t)(PN_ITLB_NWAYS * PN_NUM_512_ITLBS); 11477c478bd9Sstevel@tonic-gate tlb_data_words = sizeof (ch_tte_entry_t) / sizeof (uint64_t) * 11487c478bd9Sstevel@tonic-gate num_entries; 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate /* 11517c478bd9Sstevel@tonic-gate * Add the TLB diagnostic data to the payload 11527c478bd9Sstevel@tonic-gate * if it was collected. 11537c478bd9Sstevel@tonic-gate */ 11547c478bd9Sstevel@tonic-gate if (ch_flt->tlb_diag_data.tlo_logflag == IT_LOGFLAG_MAGIC) { 11557c478bd9Sstevel@tonic-gate fm_payload_set(nvl, 11567c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_NAME_ITLB_ENTRIES, 11577c478bd9Sstevel@tonic-gate DATA_TYPE_UINT8, num_entries, NULL); 11587c478bd9Sstevel@tonic-gate fm_payload_set(nvl, FM_EREPORT_PAYLOAD_NAME_ITLB_DATA, 11597c478bd9Sstevel@tonic-gate DATA_TYPE_UINT64_ARRAY, tlb_data_words, 11607c478bd9Sstevel@tonic-gate (uint64_t *)ch_flt->tlb_diag_data.tlo_itlb_tte, 11617c478bd9Sstevel@tonic-gate NULL); 11627c478bd9Sstevel@tonic-gate } 11637c478bd9Sstevel@tonic-gate } else { 11647c478bd9Sstevel@tonic-gate num_entries = (uint8_t)(PN_DTLB_NWAYS * PN_NUM_512_DTLBS); 11657c478bd9Sstevel@tonic-gate tlb_data_words = sizeof (ch_tte_entry_t) / sizeof (uint64_t) * 11667c478bd9Sstevel@tonic-gate num_entries; 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate fm_payload_set(nvl, FM_EREPORT_PAYLOAD_NAME_VA, 11697c478bd9Sstevel@tonic-gate DATA_TYPE_UINT64, ch_flt->tlb_diag_data.tlo_addr, NULL); 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate /* 11727c478bd9Sstevel@tonic-gate * Add the TLB diagnostic data to the payload 11737c478bd9Sstevel@tonic-gate * if it was collected. 11747c478bd9Sstevel@tonic-gate */ 11757c478bd9Sstevel@tonic-gate if (ch_flt->tlb_diag_data.tlo_logflag == DT_LOGFLAG_MAGIC) { 11767c478bd9Sstevel@tonic-gate fm_payload_set(nvl, 11777c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_NAME_DTLB_ENTRIES, 11787c478bd9Sstevel@tonic-gate DATA_TYPE_UINT8, num_entries, NULL); 11797c478bd9Sstevel@tonic-gate fm_payload_set(nvl, FM_EREPORT_PAYLOAD_NAME_DTLB_DATA, 11807c478bd9Sstevel@tonic-gate DATA_TYPE_UINT64_ARRAY, tlb_data_words, 11817c478bd9Sstevel@tonic-gate (uint64_t *)ch_flt->tlb_diag_data.tlo_dtlb_tte, 11827c478bd9Sstevel@tonic-gate NULL); 11837c478bd9Sstevel@tonic-gate } 11847c478bd9Sstevel@tonic-gate } 11857c478bd9Sstevel@tonic-gate } 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate /* 11887c478bd9Sstevel@tonic-gate * Panther Cache Scrubbing: 11897c478bd9Sstevel@tonic-gate * 11907c478bd9Sstevel@tonic-gate * In Jaguar, the E$ was split between cores, so the scrubber must run on both 11917c478bd9Sstevel@tonic-gate * cores. For Panther, however, the L2$ and L3$ are shared across cores. 11927c478bd9Sstevel@tonic-gate * Therefore, the E$ scrubber only needs to run on one of the two cores. 11937c478bd9Sstevel@tonic-gate * 11947c478bd9Sstevel@tonic-gate * There are four possible states for the E$ scrubber: 11957c478bd9Sstevel@tonic-gate * 11967c478bd9Sstevel@tonic-gate * 0. If both cores are offline, add core 0 to cpu_offline_set so that 11977c478bd9Sstevel@tonic-gate * the offline scrubber will run on it. 11987c478bd9Sstevel@tonic-gate * 1. If core 0 is online and core 1 off, we run the scrubber on core 0. 11997c478bd9Sstevel@tonic-gate * 2. If core 1 is online and core 0 off, we move the scrubber to run 12007c478bd9Sstevel@tonic-gate * on core 1. 12017c478bd9Sstevel@tonic-gate * 3. If both cores are online, only run the scrubber on core 0. 12027c478bd9Sstevel@tonic-gate * 12037c478bd9Sstevel@tonic-gate * These states are enumerated by the SCRUBBER_[BOTH|CORE|NEITHER]_* defines 12047c478bd9Sstevel@tonic-gate * above. One of those values is stored in 12057c478bd9Sstevel@tonic-gate * chpr_scrub_misc->chsm_core_state on each core. 12067c478bd9Sstevel@tonic-gate * 12077c478bd9Sstevel@tonic-gate * Also note that, for Panther, ecache_flush_line() will flush out the L2$ 12087c478bd9Sstevel@tonic-gate * before the E$, so the L2$ will be scrubbed by the E$ scrubber. No 12097c478bd9Sstevel@tonic-gate * additional code is necessary to scrub the L2$. 12107c478bd9Sstevel@tonic-gate * 12117c478bd9Sstevel@tonic-gate * For all cpu types, whenever a cpu or core is offlined, add it to 12127c478bd9Sstevel@tonic-gate * cpu_offline_set so the necessary scrubbers can still run. This is still 12137c478bd9Sstevel@tonic-gate * necessary on Panther so the D$ scrubber can still run. 12147c478bd9Sstevel@tonic-gate */ 12157c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 12167c478bd9Sstevel@tonic-gate int 12177c478bd9Sstevel@tonic-gate cpu_scrub_cpu_setup(cpu_setup_t what, int cpuid, void *arg) 12187c478bd9Sstevel@tonic-gate { 12197c478bd9Sstevel@tonic-gate processorid_t core_0_id; 12207c478bd9Sstevel@tonic-gate cpu_t *core_cpus[2]; 12217c478bd9Sstevel@tonic-gate ch_scrub_misc_t *core_scrub[2]; 12227c478bd9Sstevel@tonic-gate int old_state, i; 12237c478bd9Sstevel@tonic-gate int new_state = SCRUBBER_NEITHER_CORE_ONLINE; 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate switch (what) { 12267c478bd9Sstevel@tonic-gate case CPU_ON: 12277c478bd9Sstevel@tonic-gate case CPU_INIT: 12287c478bd9Sstevel@tonic-gate CPUSET_DEL(cpu_offline_set, cpuid); 12297c478bd9Sstevel@tonic-gate break; 12307c478bd9Sstevel@tonic-gate case CPU_OFF: 12317c478bd9Sstevel@tonic-gate CPUSET_ADD(cpu_offline_set, cpuid); 12327c478bd9Sstevel@tonic-gate break; 12337c478bd9Sstevel@tonic-gate default: 12347c478bd9Sstevel@tonic-gate return (0); 12357c478bd9Sstevel@tonic-gate } 12367c478bd9Sstevel@tonic-gate 12377c478bd9Sstevel@tonic-gate if (!IS_PANTHER(cpunodes[cpuid].implementation)) { 12387c478bd9Sstevel@tonic-gate return (0); 12397c478bd9Sstevel@tonic-gate } 12407c478bd9Sstevel@tonic-gate 12417c478bd9Sstevel@tonic-gate /* 12427c478bd9Sstevel@tonic-gate * Update the chsm_enable[CACHE_SCRUBBER_INFO_E] value 12437c478bd9Sstevel@tonic-gate * if necessary 12447c478bd9Sstevel@tonic-gate */ 12457c478bd9Sstevel@tonic-gate core_0_id = cmp_cpu_to_chip(cpuid); 12467c478bd9Sstevel@tonic-gate core_cpus[0] = cpu_get(core_0_id); 12477c478bd9Sstevel@tonic-gate core_cpus[1] = cpu_get_sibling_core(core_cpus[0]); 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate for (i = 0; i < 2; i++) { 12507c478bd9Sstevel@tonic-gate if (core_cpus[i] == NULL) { 12517c478bd9Sstevel@tonic-gate /* 12523a5a1f38Srscott * This may happen during DR - one core is offlined 12533a5a1f38Srscott * and completely unconfigured before the second 12543a5a1f38Srscott * core is offlined. Give up and return quietly, 12553a5a1f38Srscott * since the second core should quickly be removed 12563a5a1f38Srscott * anyways. 12577c478bd9Sstevel@tonic-gate */ 12587c478bd9Sstevel@tonic-gate return (0); 12597c478bd9Sstevel@tonic-gate } 12607c478bd9Sstevel@tonic-gate core_scrub[i] = CPU_PRIVATE_PTR(core_cpus[i], chpr_scrub_misc); 12617c478bd9Sstevel@tonic-gate } 12627c478bd9Sstevel@tonic-gate 12637c478bd9Sstevel@tonic-gate if (cpuid == (processorid_t)cmp_cpu_to_chip(cpuid)) { 12647c478bd9Sstevel@tonic-gate /* cpuid is core 0 */ 12657c478bd9Sstevel@tonic-gate if (cpu_is_active(core_cpus[1])) { 12667c478bd9Sstevel@tonic-gate new_state |= SCRUBBER_CORE_1_ONLINE; 12677c478bd9Sstevel@tonic-gate } 12687c478bd9Sstevel@tonic-gate if (what != CPU_OFF) { 12697c478bd9Sstevel@tonic-gate new_state |= SCRUBBER_CORE_0_ONLINE; 12707c478bd9Sstevel@tonic-gate } 12717c478bd9Sstevel@tonic-gate } else { 12727c478bd9Sstevel@tonic-gate /* cpuid is core 1 */ 12737c478bd9Sstevel@tonic-gate if (cpu_is_active(core_cpus[0])) { 12747c478bd9Sstevel@tonic-gate new_state |= SCRUBBER_CORE_0_ONLINE; 12757c478bd9Sstevel@tonic-gate } 12767c478bd9Sstevel@tonic-gate if (what != CPU_OFF) { 12777c478bd9Sstevel@tonic-gate new_state |= SCRUBBER_CORE_1_ONLINE; 12787c478bd9Sstevel@tonic-gate } 12797c478bd9Sstevel@tonic-gate } 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate old_state = core_scrub[0]->chsm_core_state; 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate if (old_state == new_state) { 12847c478bd9Sstevel@tonic-gate return (0); 12857c478bd9Sstevel@tonic-gate } 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate if (old_state == SCRUBBER_CORE_1_ONLINE) { 12887c478bd9Sstevel@tonic-gate /* 12897c478bd9Sstevel@tonic-gate * We need to move the scrubber state from core 1 12907c478bd9Sstevel@tonic-gate * back to core 0. This data is not protected by 12917c478bd9Sstevel@tonic-gate * locks, but the worst that can happen is some 12927c478bd9Sstevel@tonic-gate * lines are scrubbed multiple times. chsm_oustanding is 12937c478bd9Sstevel@tonic-gate * set to 0 to make sure an interrupt is scheduled the 12947c478bd9Sstevel@tonic-gate * first time through do_scrub(). 12957c478bd9Sstevel@tonic-gate */ 12967c478bd9Sstevel@tonic-gate core_scrub[0]->chsm_flush_index[CACHE_SCRUBBER_INFO_E] = 12977c478bd9Sstevel@tonic-gate core_scrub[1]->chsm_flush_index[CACHE_SCRUBBER_INFO_E]; 12987c478bd9Sstevel@tonic-gate core_scrub[0]->chsm_outstanding[CACHE_SCRUBBER_INFO_E] = 0; 12997c478bd9Sstevel@tonic-gate } 13007c478bd9Sstevel@tonic-gate 13017c478bd9Sstevel@tonic-gate switch (new_state) { 13027c478bd9Sstevel@tonic-gate case SCRUBBER_NEITHER_CORE_ONLINE: 13037c478bd9Sstevel@tonic-gate case SCRUBBER_BOTH_CORES_ONLINE: 13047c478bd9Sstevel@tonic-gate case SCRUBBER_CORE_0_ONLINE: 13057c478bd9Sstevel@tonic-gate core_scrub[1]->chsm_enable[CACHE_SCRUBBER_INFO_E] = 0; 13067c478bd9Sstevel@tonic-gate core_scrub[0]->chsm_enable[CACHE_SCRUBBER_INFO_E] = 1; 13077c478bd9Sstevel@tonic-gate break; 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate case SCRUBBER_CORE_1_ONLINE: 13107c478bd9Sstevel@tonic-gate default: 13117c478bd9Sstevel@tonic-gate /* 13127c478bd9Sstevel@tonic-gate * We need to move the scrubber state from core 0 13137c478bd9Sstevel@tonic-gate * to core 1. 13147c478bd9Sstevel@tonic-gate */ 13157c478bd9Sstevel@tonic-gate core_scrub[1]->chsm_flush_index[CACHE_SCRUBBER_INFO_E] = 13167c478bd9Sstevel@tonic-gate core_scrub[0]->chsm_flush_index[CACHE_SCRUBBER_INFO_E]; 13177c478bd9Sstevel@tonic-gate core_scrub[1]->chsm_outstanding[CACHE_SCRUBBER_INFO_E] = 0; 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate core_scrub[0]->chsm_enable[CACHE_SCRUBBER_INFO_E] = 0; 13207c478bd9Sstevel@tonic-gate core_scrub[1]->chsm_enable[CACHE_SCRUBBER_INFO_E] = 1; 13217c478bd9Sstevel@tonic-gate break; 13227c478bd9Sstevel@tonic-gate } 13237c478bd9Sstevel@tonic-gate 13247c478bd9Sstevel@tonic-gate core_scrub[0]->chsm_core_state = new_state; 13257c478bd9Sstevel@tonic-gate core_scrub[1]->chsm_core_state = new_state; 13267c478bd9Sstevel@tonic-gate return (0); 13277c478bd9Sstevel@tonic-gate } 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate /* 13307c478bd9Sstevel@tonic-gate * Returns a pointer to the cpu structure of the argument's sibling core. 13317c478bd9Sstevel@tonic-gate * If no sibling core can be found, return NULL. 13327c478bd9Sstevel@tonic-gate */ 13337c478bd9Sstevel@tonic-gate static cpu_t * 13347c478bd9Sstevel@tonic-gate cpu_get_sibling_core(cpu_t *cpup) 13357c478bd9Sstevel@tonic-gate { 13367c478bd9Sstevel@tonic-gate cpu_t *nextp; 1337fb2f18f8Sesaxe pg_t *pg; 1338fb2f18f8Sesaxe pg_cpu_itr_t i; 13397c478bd9Sstevel@tonic-gate 13403a5a1f38Srscott if ((cpup == NULL) || (!cmp_cpu_is_cmp(cpup->cpu_id))) 13417c478bd9Sstevel@tonic-gate return (NULL); 1342fb2f18f8Sesaxe pg = (pg_t *)pghw_find_pg(cpup, PGHW_CHIP); 1343fb2f18f8Sesaxe if (pg == NULL) 1344fb2f18f8Sesaxe return (NULL); 13457c478bd9Sstevel@tonic-gate 1346fb2f18f8Sesaxe /* 1347fb2f18f8Sesaxe * Iterate over the CPUs in the chip PG looking 1348fb2f18f8Sesaxe * for a CPU that isn't cpup 1349fb2f18f8Sesaxe */ 1350fb2f18f8Sesaxe PG_CPU_ITR_INIT(pg, i); 1351fb2f18f8Sesaxe while ((nextp = pg_cpu_next(&i)) != NULL) { 1352fb2f18f8Sesaxe if (nextp != cpup) 1353fb2f18f8Sesaxe break; 1354fb2f18f8Sesaxe } 1355fb2f18f8Sesaxe 1356fb2f18f8Sesaxe if (nextp == NULL) 13577c478bd9Sstevel@tonic-gate return (NULL); 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate return (nextp); 13607c478bd9Sstevel@tonic-gate } 1361