10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 52414Saguzovsk * Common Development and Distribution License (the "License"). 62414Saguzovsk * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 223764Sdp78419 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <sys/types.h> 290Sstevel@tonic-gate #include <sys/systm.h> 300Sstevel@tonic-gate #include <sys/ddi.h> 310Sstevel@tonic-gate #include <sys/sysmacros.h> 320Sstevel@tonic-gate #include <sys/archsystm.h> 330Sstevel@tonic-gate #include <sys/vmsystm.h> 340Sstevel@tonic-gate #include <sys/machparam.h> 350Sstevel@tonic-gate #include <sys/machsystm.h> 360Sstevel@tonic-gate #include <sys/machthread.h> 370Sstevel@tonic-gate #include <sys/cpu.h> 380Sstevel@tonic-gate #include <sys/cmp.h> 390Sstevel@tonic-gate #include <sys/elf_SPARC.h> 400Sstevel@tonic-gate #include <vm/hat_sfmmu.h> 410Sstevel@tonic-gate #include <vm/seg_kmem.h> 420Sstevel@tonic-gate #include <sys/cpuvar.h> 430Sstevel@tonic-gate #include <sys/cheetahregs.h> 440Sstevel@tonic-gate #include <sys/us3_module.h> 450Sstevel@tonic-gate #include <sys/async.h> 460Sstevel@tonic-gate #include <sys/cmn_err.h> 470Sstevel@tonic-gate #include <sys/debug.h> 480Sstevel@tonic-gate #include <sys/dditypes.h> 490Sstevel@tonic-gate #include <sys/prom_debug.h> 500Sstevel@tonic-gate #include <sys/prom_plat.h> 510Sstevel@tonic-gate #include <sys/cpu_module.h> 520Sstevel@tonic-gate #include <sys/sysmacros.h> 530Sstevel@tonic-gate #include <sys/intreg.h> 540Sstevel@tonic-gate #include <sys/clock.h> 550Sstevel@tonic-gate #include <sys/platform_module.h> 560Sstevel@tonic-gate #include <sys/machtrap.h> 570Sstevel@tonic-gate #include <sys/ontrap.h> 580Sstevel@tonic-gate #include <sys/panic.h> 590Sstevel@tonic-gate #include <sys/memlist.h> 600Sstevel@tonic-gate #include <sys/bootconf.h> 610Sstevel@tonic-gate #include <sys/ivintr.h> 620Sstevel@tonic-gate #include <sys/atomic.h> 630Sstevel@tonic-gate #include <sys/fm/protocol.h> 640Sstevel@tonic-gate #include <sys/fm/cpu/UltraSPARC-III.h> 650Sstevel@tonic-gate #include <vm/vm_dep.h> 660Sstevel@tonic-gate 670Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 680Sstevel@tonic-gate #include <sys/cyclic.h> 690Sstevel@tonic-gate #endif /* CHEETAHPLUS_ERRATUM_25 */ 700Sstevel@tonic-gate 710Sstevel@tonic-gate /* 722991Ssusans * Note that 'Cheetah PRM' refers to: 732991Ssusans * SPARC V9 JPS1 Implementation Supplement: Sun UltraSPARC-III 742991Ssusans */ 752991Ssusans 762991Ssusans /* 770Sstevel@tonic-gate * Setup trap handlers. 780Sstevel@tonic-gate */ 790Sstevel@tonic-gate void 800Sstevel@tonic-gate cpu_init_trap(void) 810Sstevel@tonic-gate { 820Sstevel@tonic-gate CH_SET_TRAP(tt_pil15, ch_pil15_interrupt_instr); 830Sstevel@tonic-gate 840Sstevel@tonic-gate CH_SET_TRAP(tt0_fecc, fecc_err_instr); 850Sstevel@tonic-gate CH_SET_TRAP(tt1_fecc, fecc_err_tl1_instr); 860Sstevel@tonic-gate CH_SET_TRAP(tt1_swtrap0, fecc_err_tl1_cont_instr); 870Sstevel@tonic-gate } 880Sstevel@tonic-gate 890Sstevel@tonic-gate static int 90789Sahrens getintprop(pnode_t node, char *name, int deflt) 910Sstevel@tonic-gate { 920Sstevel@tonic-gate int value; 930Sstevel@tonic-gate 940Sstevel@tonic-gate switch (prom_getproplen(node, name)) { 950Sstevel@tonic-gate case sizeof (int): 960Sstevel@tonic-gate (void) prom_getprop(node, name, (caddr_t)&value); 970Sstevel@tonic-gate break; 980Sstevel@tonic-gate 990Sstevel@tonic-gate default: 1000Sstevel@tonic-gate value = deflt; 1010Sstevel@tonic-gate break; 1020Sstevel@tonic-gate } 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate return (value); 1050Sstevel@tonic-gate } 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate /* 1080Sstevel@tonic-gate * Set the magic constants of the implementation. 1090Sstevel@tonic-gate */ 1100Sstevel@tonic-gate /*ARGSUSED*/ 1110Sstevel@tonic-gate void 112789Sahrens cpu_fiximp(pnode_t dnode) 1130Sstevel@tonic-gate { 1140Sstevel@tonic-gate int i, a; 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate static struct { 1170Sstevel@tonic-gate char *name; 1180Sstevel@tonic-gate int *var; 1190Sstevel@tonic-gate int defval; 1200Sstevel@tonic-gate } prop[] = { 1210Sstevel@tonic-gate "dcache-size", &dcache_size, CH_DCACHE_SIZE, 1220Sstevel@tonic-gate "dcache-line-size", &dcache_linesize, CH_DCACHE_LSIZE, 1230Sstevel@tonic-gate "icache-size", &icache_size, CH_ICACHE_SIZE, 1240Sstevel@tonic-gate "icache-line-size", &icache_linesize, CH_ICACHE_LSIZE, 1250Sstevel@tonic-gate "ecache-size", &ecache_size, CH_ECACHE_MAX_SIZE, 1260Sstevel@tonic-gate "ecache-line-size", &ecache_alignsize, CH_ECACHE_MAX_LSIZE, 1270Sstevel@tonic-gate "ecache-associativity", &ecache_associativity, CH_ECACHE_NWAY 1280Sstevel@tonic-gate }; 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate for (i = 0; i < sizeof (prop) / sizeof (prop[0]); i++) 1310Sstevel@tonic-gate *prop[i].var = getintprop(dnode, prop[i].name, prop[i].defval); 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate ecache_setsize = ecache_size / ecache_associativity; 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate vac_size = CH_VAC_SIZE; 1360Sstevel@tonic-gate vac_mask = MMU_PAGEMASK & (vac_size - 1); 1370Sstevel@tonic-gate i = 0; a = vac_size; 1380Sstevel@tonic-gate while (a >>= 1) 1390Sstevel@tonic-gate ++i; 1400Sstevel@tonic-gate vac_shift = i; 1410Sstevel@tonic-gate shm_alignment = vac_size; 1420Sstevel@tonic-gate vac = 1; 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate /* 1450Sstevel@tonic-gate * Cheetah's large page support has problems with large numbers of 1460Sstevel@tonic-gate * large pages, so just disable large pages out-of-the-box. 1472991Ssusans * Note that the other defaults are set in sun4u/vm/mach_vm_dep.c. 1480Sstevel@tonic-gate */ 1492991Ssusans max_uheap_lpsize = MMU_PAGESIZE; 1502991Ssusans max_ustack_lpsize = MMU_PAGESIZE; 1512991Ssusans max_privmap_lpsize = MMU_PAGESIZE; 1522991Ssusans max_utext_lpsize = MMU_PAGESIZE; 1532414Saguzovsk max_shm_lpsize = MMU_PAGESIZE; 1543764Sdp78419 max_bootlp_tteszc = TTE8K; 1550Sstevel@tonic-gate } 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate void 1580Sstevel@tonic-gate send_mondo_set(cpuset_t set) 1590Sstevel@tonic-gate { 1600Sstevel@tonic-gate int lo, busy, nack, shipped = 0; 1610Sstevel@tonic-gate uint16_t i, cpuids[IDSR_BN_SETS]; 1620Sstevel@tonic-gate uint64_t idsr, nackmask = 0, busymask, curnack, curbusy; 1630Sstevel@tonic-gate uint64_t starttick, endtick, tick, lasttick; 1640Sstevel@tonic-gate #if (NCPU > IDSR_BN_SETS) 1650Sstevel@tonic-gate int index = 0; 1660Sstevel@tonic-gate int ncpuids = 0; 1670Sstevel@tonic-gate #endif 1680Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 1690Sstevel@tonic-gate int recovered = 0; 1700Sstevel@tonic-gate int cpuid; 1710Sstevel@tonic-gate #endif 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate ASSERT(!CPUSET_ISNULL(set)); 1740Sstevel@tonic-gate starttick = lasttick = gettick(); 1750Sstevel@tonic-gate 1760Sstevel@tonic-gate #if (NCPU <= IDSR_BN_SETS) 1770Sstevel@tonic-gate for (i = 0; i < NCPU; i++) 1780Sstevel@tonic-gate if (CPU_IN_SET(set, i)) { 1790Sstevel@tonic-gate shipit(i, shipped); 1800Sstevel@tonic-gate nackmask |= IDSR_NACK_BIT(shipped); 1810Sstevel@tonic-gate cpuids[shipped++] = i; 1820Sstevel@tonic-gate CPUSET_DEL(set, i); 1830Sstevel@tonic-gate if (CPUSET_ISNULL(set)) 1840Sstevel@tonic-gate break; 1850Sstevel@tonic-gate } 1860Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, xcalls, shipped); 1870Sstevel@tonic-gate #else 1880Sstevel@tonic-gate for (i = 0; i < NCPU; i++) 1890Sstevel@tonic-gate if (CPU_IN_SET(set, i)) { 1900Sstevel@tonic-gate ncpuids++; 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate /* 1930Sstevel@tonic-gate * Ship only to the first (IDSR_BN_SETS) CPUs. If we 1940Sstevel@tonic-gate * find we have shipped to more than (IDSR_BN_SETS) 1950Sstevel@tonic-gate * CPUs, set "index" to the highest numbered CPU in 1960Sstevel@tonic-gate * the set so we can ship to other CPUs a bit later on. 1970Sstevel@tonic-gate */ 1980Sstevel@tonic-gate if (shipped < IDSR_BN_SETS) { 1990Sstevel@tonic-gate shipit(i, shipped); 2000Sstevel@tonic-gate nackmask |= IDSR_NACK_BIT(shipped); 2010Sstevel@tonic-gate cpuids[shipped++] = i; 2020Sstevel@tonic-gate CPUSET_DEL(set, i); 2030Sstevel@tonic-gate if (CPUSET_ISNULL(set)) 2040Sstevel@tonic-gate break; 2050Sstevel@tonic-gate } else 2060Sstevel@tonic-gate index = (int)i; 2070Sstevel@tonic-gate } 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, xcalls, ncpuids); 2100Sstevel@tonic-gate #endif 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate busymask = IDSR_NACK_TO_BUSY(nackmask); 2130Sstevel@tonic-gate busy = nack = 0; 2140Sstevel@tonic-gate endtick = starttick + xc_tick_limit; 2150Sstevel@tonic-gate for (;;) { 2160Sstevel@tonic-gate idsr = getidsr(); 2170Sstevel@tonic-gate #if (NCPU <= IDSR_BN_SETS) 2180Sstevel@tonic-gate if (idsr == 0) 2190Sstevel@tonic-gate break; 2200Sstevel@tonic-gate #else 2210Sstevel@tonic-gate if (idsr == 0 && shipped == ncpuids) 2220Sstevel@tonic-gate break; 2230Sstevel@tonic-gate #endif 2240Sstevel@tonic-gate tick = gettick(); 2250Sstevel@tonic-gate /* 2260Sstevel@tonic-gate * If there is a big jump between the current tick 2270Sstevel@tonic-gate * count and lasttick, we have probably hit a break 2280Sstevel@tonic-gate * point. Adjust endtick accordingly to avoid panic. 2290Sstevel@tonic-gate */ 2300Sstevel@tonic-gate if (tick > (lasttick + xc_tick_jump_limit)) 2310Sstevel@tonic-gate endtick += (tick - lasttick); 2320Sstevel@tonic-gate lasttick = tick; 2330Sstevel@tonic-gate if (tick > endtick) { 2340Sstevel@tonic-gate if (panic_quiesce) 2350Sstevel@tonic-gate return; 2360Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 2370Sstevel@tonic-gate cpuid = -1; 2380Sstevel@tonic-gate for (i = 0; i < IDSR_BN_SETS; i++) { 2390Sstevel@tonic-gate if (idsr & (IDSR_NACK_BIT(i) | 2400Sstevel@tonic-gate IDSR_BUSY_BIT(i))) { 2410Sstevel@tonic-gate cpuid = cpuids[i]; 2420Sstevel@tonic-gate break; 2430Sstevel@tonic-gate } 2440Sstevel@tonic-gate } 2450Sstevel@tonic-gate if (cheetah_sendmondo_recover && cpuid != -1 && 2460Sstevel@tonic-gate recovered == 0) { 2470Sstevel@tonic-gate if (mondo_recover(cpuid, i)) { 2480Sstevel@tonic-gate /* 2490Sstevel@tonic-gate * We claimed the whole memory or 2500Sstevel@tonic-gate * full scan is disabled. 2510Sstevel@tonic-gate */ 2520Sstevel@tonic-gate recovered++; 2530Sstevel@tonic-gate } 2540Sstevel@tonic-gate tick = gettick(); 2550Sstevel@tonic-gate endtick = tick + xc_tick_limit; 2560Sstevel@tonic-gate lasttick = tick; 2570Sstevel@tonic-gate /* 2580Sstevel@tonic-gate * Recheck idsr 2590Sstevel@tonic-gate */ 2600Sstevel@tonic-gate continue; 2610Sstevel@tonic-gate } else 2620Sstevel@tonic-gate #endif /* CHEETAHPLUS_ERRATUM_25 */ 2630Sstevel@tonic-gate { 2640Sstevel@tonic-gate cmn_err(CE_CONT, "send mondo timeout " 2650Sstevel@tonic-gate "[%d NACK %d BUSY]\nIDSR 0x%" 2660Sstevel@tonic-gate "" PRIx64 " cpuids:", nack, busy, idsr); 2670Sstevel@tonic-gate for (i = 0; i < IDSR_BN_SETS; i++) { 2680Sstevel@tonic-gate if (idsr & (IDSR_NACK_BIT(i) | 2690Sstevel@tonic-gate IDSR_BUSY_BIT(i))) { 2700Sstevel@tonic-gate cmn_err(CE_CONT, " 0x%x", 2710Sstevel@tonic-gate cpuids[i]); 2720Sstevel@tonic-gate } 2730Sstevel@tonic-gate } 2740Sstevel@tonic-gate cmn_err(CE_CONT, "\n"); 2750Sstevel@tonic-gate cmn_err(CE_PANIC, "send_mondo_set: timeout"); 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate } 2780Sstevel@tonic-gate curnack = idsr & nackmask; 2790Sstevel@tonic-gate curbusy = idsr & busymask; 2800Sstevel@tonic-gate #if (NCPU > IDSR_BN_SETS) 2810Sstevel@tonic-gate if (shipped < ncpuids) { 2820Sstevel@tonic-gate uint64_t cpus_left; 2830Sstevel@tonic-gate uint16_t next = (uint16_t)index; 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate cpus_left = ~(IDSR_NACK_TO_BUSY(curnack) | curbusy) & 2860Sstevel@tonic-gate busymask; 2870Sstevel@tonic-gate 2880Sstevel@tonic-gate if (cpus_left) { 2890Sstevel@tonic-gate do { 2900Sstevel@tonic-gate /* 2910Sstevel@tonic-gate * Sequence through and ship to the 2920Sstevel@tonic-gate * remainder of the CPUs in the system 2930Sstevel@tonic-gate * (e.g. other than the first 2940Sstevel@tonic-gate * (IDSR_BN_SETS)) in reverse order. 2950Sstevel@tonic-gate */ 2960Sstevel@tonic-gate lo = lowbit(cpus_left) - 1; 2970Sstevel@tonic-gate i = IDSR_BUSY_IDX(lo); 2980Sstevel@tonic-gate shipit(next, i); 2990Sstevel@tonic-gate shipped++; 3000Sstevel@tonic-gate cpuids[i] = next; 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate /* 3030Sstevel@tonic-gate * If we've processed all the CPUs, 3040Sstevel@tonic-gate * exit the loop now and save 3050Sstevel@tonic-gate * instructions. 3060Sstevel@tonic-gate */ 3070Sstevel@tonic-gate if (shipped == ncpuids) 3080Sstevel@tonic-gate break; 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate for ((index = ((int)next - 1)); 3110Sstevel@tonic-gate index >= 0; index--) 3120Sstevel@tonic-gate if (CPU_IN_SET(set, index)) { 3130Sstevel@tonic-gate next = (uint16_t)index; 3140Sstevel@tonic-gate break; 3150Sstevel@tonic-gate } 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate cpus_left &= ~(1ull << lo); 3180Sstevel@tonic-gate } while (cpus_left); 3190Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 3200Sstevel@tonic-gate /* 3210Sstevel@tonic-gate * Clear recovered because we are sending to 3220Sstevel@tonic-gate * a new set of targets. 3230Sstevel@tonic-gate */ 3240Sstevel@tonic-gate recovered = 0; 3250Sstevel@tonic-gate #endif 3260Sstevel@tonic-gate continue; 3270Sstevel@tonic-gate } 3280Sstevel@tonic-gate } 3290Sstevel@tonic-gate #endif 3300Sstevel@tonic-gate if (curbusy) { 3310Sstevel@tonic-gate busy++; 3320Sstevel@tonic-gate continue; 3330Sstevel@tonic-gate } 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate #ifdef SEND_MONDO_STATS 3360Sstevel@tonic-gate { 3370Sstevel@tonic-gate int n = gettick() - starttick; 3380Sstevel@tonic-gate if (n < 8192) 3390Sstevel@tonic-gate x_nack_stimes[n >> 7]++; 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate #endif 3420Sstevel@tonic-gate while (gettick() < (tick + sys_clock_mhz)) 3430Sstevel@tonic-gate ; 3440Sstevel@tonic-gate do { 3450Sstevel@tonic-gate lo = lowbit(curnack) - 1; 3460Sstevel@tonic-gate i = IDSR_NACK_IDX(lo); 3470Sstevel@tonic-gate shipit(cpuids[i], i); 3480Sstevel@tonic-gate curnack &= ~(1ull << lo); 3490Sstevel@tonic-gate } while (curnack); 3500Sstevel@tonic-gate nack++; 3510Sstevel@tonic-gate busy = 0; 3520Sstevel@tonic-gate } 3530Sstevel@tonic-gate #ifdef SEND_MONDO_STATS 3540Sstevel@tonic-gate { 3550Sstevel@tonic-gate int n = gettick() - starttick; 3560Sstevel@tonic-gate if (n < 8192) 3570Sstevel@tonic-gate x_set_stimes[n >> 7]++; 3580Sstevel@tonic-gate else 3590Sstevel@tonic-gate x_set_ltimes[(n >> 13) & 0xf]++; 3600Sstevel@tonic-gate } 3610Sstevel@tonic-gate x_set_cpus[shipped]++; 3620Sstevel@tonic-gate #endif 3630Sstevel@tonic-gate } 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate /* 3660Sstevel@tonic-gate * Handles error logging for implementation specific error types. 3670Sstevel@tonic-gate */ 3680Sstevel@tonic-gate /*ARGSUSED*/ 3690Sstevel@tonic-gate int 3700Sstevel@tonic-gate cpu_impl_async_log_err(void *flt, errorq_elem_t *eqep) 3710Sstevel@tonic-gate { 3720Sstevel@tonic-gate /* There aren't any error types which are specific to cheetah only */ 3730Sstevel@tonic-gate return (CH_ASYNC_LOG_UNKNOWN); 3740Sstevel@tonic-gate } 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate /* 3770Sstevel@tonic-gate * Figure out if Ecache is direct-mapped (Cheetah or Cheetah+ with Ecache 3780Sstevel@tonic-gate * control ECCR_ASSOC bit off or 2-way (Cheetah+ with ECCR_ASSOC on). 3790Sstevel@tonic-gate * We need to do this on the fly because we may have mixed Cheetah+'s with 3800Sstevel@tonic-gate * both direct and 2-way Ecaches. 3810Sstevel@tonic-gate */ 3820Sstevel@tonic-gate int 3830Sstevel@tonic-gate cpu_ecache_nway(void) 3840Sstevel@tonic-gate { 3850Sstevel@tonic-gate return (CH_ECACHE_NWAY); 3860Sstevel@tonic-gate } 3870Sstevel@tonic-gate 3880Sstevel@tonic-gate /* 3890Sstevel@tonic-gate * Note that these are entered into the table: Fatal Errors (PERR, IERR, 3900Sstevel@tonic-gate * ISAP, EMU) first, orphaned UCU/UCC, AFAR Overwrite policy, finally IVU, IVC. 3910Sstevel@tonic-gate * Afar overwrite policy is: 3920Sstevel@tonic-gate * UCU,UCC > UE,EDU,WDU,CPU > CE,EDC,EMC,WDC,CPC > TO,BERR 3930Sstevel@tonic-gate */ 3940Sstevel@tonic-gate ecc_type_to_info_t ecc_type_to_info[] = { 3950Sstevel@tonic-gate 3960Sstevel@tonic-gate /* Fatal Errors */ 3970Sstevel@tonic-gate C_AFSR_PERR, "PERR ", ECC_ALL_TRAPS, CPU_FATAL, 3980Sstevel@tonic-gate "PERR Fatal", 3990Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM2, 4000Sstevel@tonic-gate FM_EREPORT_CPU_USIII_PERR, 4010Sstevel@tonic-gate C_AFSR_IERR, "IERR ", ECC_ALL_TRAPS, CPU_FATAL, 4020Sstevel@tonic-gate "IERR Fatal", 4030Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM2, 4040Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IERR, 4050Sstevel@tonic-gate C_AFSR_ISAP, "ISAP ", ECC_ALL_TRAPS, CPU_FATAL, 4060Sstevel@tonic-gate "ISAP Fatal", 4070Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 4080Sstevel@tonic-gate FM_EREPORT_CPU_USIII_ISAP, 4090Sstevel@tonic-gate C_AFSR_EMU, "EMU ", ECC_ASYNC_TRAPS, CPU_FATAL, 4100Sstevel@tonic-gate "EMU Fatal", 4110Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 4120Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EMU, 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate /* Orphaned UCC/UCU Errors */ 4150Sstevel@tonic-gate C_AFSR_UCU, "OUCU ", ECC_ORPH_TRAPS, CPU_ORPH, 4160Sstevel@tonic-gate "Orphaned UCU", 4170Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4180Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCU, 4190Sstevel@tonic-gate C_AFSR_UCC, "OUCC ", ECC_ORPH_TRAPS, CPU_ORPH, 4200Sstevel@tonic-gate "Orphaned UCC", 4210Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4220Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCC, 4230Sstevel@tonic-gate 4240Sstevel@tonic-gate /* UCU, UCC */ 4250Sstevel@tonic-gate C_AFSR_UCU, "UCU ", ECC_F_TRAP, CPU_UE_ECACHE, 4260Sstevel@tonic-gate "UCU", 4270Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4280Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCU, 4290Sstevel@tonic-gate C_AFSR_UCC, "UCC ", ECC_F_TRAP, CPU_CE_ECACHE, 4300Sstevel@tonic-gate "UCC", 4310Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4320Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCC, 4330Sstevel@tonic-gate 4340Sstevel@tonic-gate /* UE, EDU:ST, EDU:BLD, WDU, CPU */ 4350Sstevel@tonic-gate C_AFSR_UE, "UE ", ECC_ASYNC_TRAPS, CPU_UE, 4360Sstevel@tonic-gate "Uncorrectable system bus (UE)", 4370Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 4380Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UE, 4390Sstevel@tonic-gate C_AFSR_EDU, "EDU ", ECC_C_TRAP, CPU_UE_ECACHE_RETIRE, 4400Sstevel@tonic-gate "EDU:ST", 4410Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4420Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EDUST, 4430Sstevel@tonic-gate C_AFSR_EDU, "EDU ", ECC_D_TRAP, CPU_UE_ECACHE_RETIRE, 4440Sstevel@tonic-gate "EDU:BLD", 4450Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4460Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EDUBL, 4470Sstevel@tonic-gate C_AFSR_WDU, "WDU ", ECC_C_TRAP, CPU_UE_ECACHE_RETIRE, 4480Sstevel@tonic-gate "WDU", 4490Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4500Sstevel@tonic-gate FM_EREPORT_CPU_USIII_WDU, 4510Sstevel@tonic-gate C_AFSR_CPU, "CPU ", ECC_C_TRAP, CPU_UE_ECACHE, 4520Sstevel@tonic-gate "CPU", 4530Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4540Sstevel@tonic-gate FM_EREPORT_CPU_USIII_CPU, 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate /* CE, EDC, EMC, WDC, CPC */ 4570Sstevel@tonic-gate C_AFSR_CE, "CE ", ECC_C_TRAP, CPU_CE, 4580Sstevel@tonic-gate "Corrected system bus (CE)", 4590Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 4600Sstevel@tonic-gate FM_EREPORT_CPU_USIII_CE, 4610Sstevel@tonic-gate C_AFSR_EDC, "EDC ", ECC_C_TRAP, CPU_CE_ECACHE, 4620Sstevel@tonic-gate "EDC", 4630Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4640Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EDC, 4650Sstevel@tonic-gate C_AFSR_EMC, "EMC ", ECC_C_TRAP, CPU_EMC, 4660Sstevel@tonic-gate "EMC", 4670Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 4680Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EMC, 4690Sstevel@tonic-gate C_AFSR_WDC, "WDC ", ECC_C_TRAP, CPU_CE_ECACHE, 4700Sstevel@tonic-gate "WDC", 4710Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4720Sstevel@tonic-gate FM_EREPORT_CPU_USIII_WDC, 4730Sstevel@tonic-gate C_AFSR_CPC, "CPC ", ECC_C_TRAP, CPU_CE_ECACHE, 4740Sstevel@tonic-gate "CPC", 4750Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4760Sstevel@tonic-gate FM_EREPORT_CPU_USIII_CPC, 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate /* TO, BERR */ 4790Sstevel@tonic-gate C_AFSR_TO, "TO ", ECC_ASYNC_TRAPS, CPU_TO, 4800Sstevel@tonic-gate "Timeout (TO)", 4810Sstevel@tonic-gate FM_EREPORT_PAYLOAD_IO, 4820Sstevel@tonic-gate FM_EREPORT_CPU_USIII_TO, 4830Sstevel@tonic-gate C_AFSR_BERR, "BERR ", ECC_ASYNC_TRAPS, CPU_BERR, 4840Sstevel@tonic-gate "Bus Error (BERR)", 4850Sstevel@tonic-gate FM_EREPORT_PAYLOAD_IO, 4860Sstevel@tonic-gate FM_EREPORT_CPU_USIII_BERR, 4870Sstevel@tonic-gate 4880Sstevel@tonic-gate /* IVU, IVC */ 4890Sstevel@tonic-gate C_AFSR_IVU, "IVU ", ECC_C_TRAP, CPU_IV, 4900Sstevel@tonic-gate "IVU", 4910Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 4920Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IVU, 4930Sstevel@tonic-gate C_AFSR_IVC, "IVC ", ECC_C_TRAP, CPU_IV, 4940Sstevel@tonic-gate "IVC", 4950Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 4960Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IVC, 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate 0, NULL, 0, 0, 4990Sstevel@tonic-gate NULL, 5000Sstevel@tonic-gate FM_EREPORT_PAYLOAD_UNKNOWN, 5010Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UNKNOWN, 5020Sstevel@tonic-gate }; 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate /* 5050Sstevel@tonic-gate * Prioritized list of Error bits for AFAR overwrite. 5060Sstevel@tonic-gate * See Cheetah PRM P.6.1 5070Sstevel@tonic-gate * Class 4: UCC, UCU 5080Sstevel@tonic-gate * Class 3: UE, EDU, EMU, WDU, CPU 5090Sstevel@tonic-gate * Class 2: CE, EDC, EMC, WDC, CPC 5100Sstevel@tonic-gate * Class 1: TO, BERR 5110Sstevel@tonic-gate */ 5120Sstevel@tonic-gate uint64_t afar_overwrite[] = { 5130Sstevel@tonic-gate C_AFSR_UCC | C_AFSR_UCU, 5140Sstevel@tonic-gate C_AFSR_UE | C_AFSR_EDU | C_AFSR_EMU | C_AFSR_WDU | C_AFSR_CPU, 5150Sstevel@tonic-gate C_AFSR_CE | C_AFSR_EDC | C_AFSR_EMC | C_AFSR_WDC | C_AFSR_CPC, 5160Sstevel@tonic-gate C_AFSR_TO | C_AFSR_BERR, 5170Sstevel@tonic-gate 0 5180Sstevel@tonic-gate }; 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate /* 5210Sstevel@tonic-gate * Prioritized list of Error bits for ESYND overwrite. 5220Sstevel@tonic-gate * See Cheetah PRM P.6.2 5230Sstevel@tonic-gate * Class 2: UE, IVU, EDU, WDU, UCU, CPU 5240Sstevel@tonic-gate * Class 1: CE, IVC, EDC, WDC, UCC, CPC 5250Sstevel@tonic-gate */ 5260Sstevel@tonic-gate uint64_t esynd_overwrite[] = { 5270Sstevel@tonic-gate C_AFSR_UE | C_AFSR_IVU | C_AFSR_EDU | C_AFSR_WDU | C_AFSR_UCU | 5280Sstevel@tonic-gate C_AFSR_CPU, 5290Sstevel@tonic-gate C_AFSR_CE | C_AFSR_IVC | C_AFSR_EDC | C_AFSR_WDC | C_AFSR_UCC | 5300Sstevel@tonic-gate C_AFSR_CPC, 5310Sstevel@tonic-gate 0 5320Sstevel@tonic-gate }; 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate /* 5350Sstevel@tonic-gate * Prioritized list of Error bits for MSYND overwrite. 5360Sstevel@tonic-gate * See Cheetah PRM P.6.3 5370Sstevel@tonic-gate * Class 2: EMU 5380Sstevel@tonic-gate * Class 1: EMC 5390Sstevel@tonic-gate */ 5400Sstevel@tonic-gate uint64_t msynd_overwrite[] = { 5410Sstevel@tonic-gate C_AFSR_EMU, 5420Sstevel@tonic-gate C_AFSR_EMC, 5430Sstevel@tonic-gate 0 5440Sstevel@tonic-gate }; 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate /* 5470Sstevel@tonic-gate * change cpu speed bits -- new speed will be normal-speed/divisor. 5480Sstevel@tonic-gate * 5490Sstevel@tonic-gate * The Jalapeno memory controllers are required to drain outstanding 5500Sstevel@tonic-gate * memory transactions within 32 JBus clocks in order to be ready 5510Sstevel@tonic-gate * to enter Estar mode. In some corner cases however, that time 5520Sstevel@tonic-gate * fell short. 5530Sstevel@tonic-gate * 5540Sstevel@tonic-gate * A safe software solution is to force MCU to act like in Estar mode, 5550Sstevel@tonic-gate * then delay 1us (in ppm code) prior to assert J_CHNG_L signal. 5560Sstevel@tonic-gate * To reverse the effect, upon exiting Estar, software restores the 5570Sstevel@tonic-gate * MCU to its original state. 5580Sstevel@tonic-gate */ 5590Sstevel@tonic-gate /* ARGSUSED1 */ 5600Sstevel@tonic-gate void 5610Sstevel@tonic-gate cpu_change_speed(uint64_t divisor, uint64_t arg2) 5620Sstevel@tonic-gate { 563*4667Smh27603 bus_config_eclk_t *bceclk; 5640Sstevel@tonic-gate uint64_t reg; 565*4667Smh27603 processor_info_t *pi = &(CPU->cpu_type_info); 5660Sstevel@tonic-gate 5670Sstevel@tonic-gate for (bceclk = bus_config_eclk; bceclk->divisor; bceclk++) { 5680Sstevel@tonic-gate if (bceclk->divisor != divisor) 5690Sstevel@tonic-gate continue; 5700Sstevel@tonic-gate reg = get_safari_config(); 5710Sstevel@tonic-gate reg &= ~SAFARI_CONFIG_ECLK_MASK; 5720Sstevel@tonic-gate reg |= bceclk->mask; 5730Sstevel@tonic-gate set_safari_config(reg); 5740Sstevel@tonic-gate CPU->cpu_m.divisor = (uchar_t)divisor; 575*4667Smh27603 pi->pi_curr_clock = 576*4667Smh27603 (((uint64_t)pi->pi_clock * 1000000) / divisor); 5770Sstevel@tonic-gate return; 5780Sstevel@tonic-gate } 5790Sstevel@tonic-gate /* 5800Sstevel@tonic-gate * We will reach here only if OBP and kernel don't agree on 5810Sstevel@tonic-gate * the speeds supported by the CPU. 5820Sstevel@tonic-gate */ 5830Sstevel@tonic-gate cmn_err(CE_WARN, "cpu_change_speed: bad divisor %" PRIu64, divisor); 5840Sstevel@tonic-gate } 5850Sstevel@tonic-gate 5860Sstevel@tonic-gate /* 5870Sstevel@tonic-gate * Cpu private initialization. This includes allocating the cpu_private 5880Sstevel@tonic-gate * data structure, initializing it, and initializing the scrubber for this 5890Sstevel@tonic-gate * cpu. This function calls cpu_init_ecache_scrub_dr to init the scrubber. 5900Sstevel@tonic-gate * We use kmem_cache_create for the cheetah private data structure because 5910Sstevel@tonic-gate * it needs to be allocated on a PAGESIZE (8192) byte boundary. 5920Sstevel@tonic-gate */ 5930Sstevel@tonic-gate void 5940Sstevel@tonic-gate cpu_init_private(struct cpu *cp) 5950Sstevel@tonic-gate { 5960Sstevel@tonic-gate cheetah_private_t *chprp; 5970Sstevel@tonic-gate int i; 5980Sstevel@tonic-gate 5990Sstevel@tonic-gate ASSERT(CPU_PRIVATE(cp) == NULL); 6000Sstevel@tonic-gate 6010Sstevel@tonic-gate /* LINTED: E_TRUE_LOGICAL_EXPR */ 6020Sstevel@tonic-gate ASSERT((offsetof(cheetah_private_t, chpr_tl1_err_data) + 6030Sstevel@tonic-gate sizeof (ch_err_tl1_data_t) * CH_ERR_TL1_TLMAX) <= PAGESIZE); 6040Sstevel@tonic-gate 6050Sstevel@tonic-gate /* 6060Sstevel@tonic-gate * Running with a Cheetah+, Jaguar, or Panther on a Cheetah CPU 6070Sstevel@tonic-gate * machine is not a supported configuration. Attempting to do so 6080Sstevel@tonic-gate * may result in unpredictable failures (e.g. running Cheetah+ 6090Sstevel@tonic-gate * CPUs with Cheetah E$ disp flush) so don't allow it. 6100Sstevel@tonic-gate * 6110Sstevel@tonic-gate * This is just defensive code since this configuration mismatch 6120Sstevel@tonic-gate * should have been caught prior to OS execution. 6130Sstevel@tonic-gate */ 6140Sstevel@tonic-gate if (!IS_CHEETAH(cpunodes[cp->cpu_id].implementation)) { 6150Sstevel@tonic-gate cmn_err(CE_PANIC, "CPU%d: UltraSPARC-III+/IV/IV+ not" 6160Sstevel@tonic-gate " supported on UltraSPARC-III code\n", cp->cpu_id); 6170Sstevel@tonic-gate } 6180Sstevel@tonic-gate 6190Sstevel@tonic-gate /* 6200Sstevel@tonic-gate * If the ch_private_cache has not been created, create it. 6210Sstevel@tonic-gate */ 6220Sstevel@tonic-gate if (ch_private_cache == NULL) { 6230Sstevel@tonic-gate ch_private_cache = kmem_cache_create("ch_private_cache", 6240Sstevel@tonic-gate sizeof (cheetah_private_t), PAGESIZE, NULL, NULL, 6250Sstevel@tonic-gate NULL, NULL, static_arena, 0); 6260Sstevel@tonic-gate } 6270Sstevel@tonic-gate 6280Sstevel@tonic-gate chprp = CPU_PRIVATE(cp) = kmem_cache_alloc(ch_private_cache, KM_SLEEP); 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate bzero(chprp, sizeof (cheetah_private_t)); 6310Sstevel@tonic-gate chprp->chpr_fecctl0_logout.clo_data.chd_afar = LOGOUT_INVALID; 6320Sstevel@tonic-gate chprp->chpr_cecc_logout.clo_data.chd_afar = LOGOUT_INVALID; 6330Sstevel@tonic-gate chprp->chpr_async_logout.clo_data.chd_afar = LOGOUT_INVALID; 6340Sstevel@tonic-gate for (i = 0; i < CH_ERR_TL1_TLMAX; i++) 6350Sstevel@tonic-gate chprp->chpr_tl1_err_data[i].ch_err_tl1_logout.clo_data.chd_afar 6360Sstevel@tonic-gate = LOGOUT_INVALID; 6370Sstevel@tonic-gate 6380Sstevel@tonic-gate chprp->chpr_icache_size = CH_ICACHE_SIZE; 6390Sstevel@tonic-gate chprp->chpr_icache_linesize = CH_ICACHE_LSIZE; 6400Sstevel@tonic-gate 6410Sstevel@tonic-gate cpu_init_ecache_scrub_dr(cp); 6420Sstevel@tonic-gate 6430Sstevel@tonic-gate chprp->chpr_ec_set_size = cpunodes[cp->cpu_id].ecache_size / 6440Sstevel@tonic-gate cpu_ecache_nway(); 6450Sstevel@tonic-gate 6460Sstevel@tonic-gate adjust_hw_copy_limits(cpunodes[cp->cpu_id].ecache_size); 6470Sstevel@tonic-gate ch_err_tl1_paddrs[cp->cpu_id] = va_to_pa(chprp); 6480Sstevel@tonic-gate ASSERT(ch_err_tl1_paddrs[cp->cpu_id] != -1); 6490Sstevel@tonic-gate } 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate /* 6520Sstevel@tonic-gate * Clear the error state registers for this CPU. 6530Sstevel@tonic-gate * For Cheetah, just clear the AFSR 6540Sstevel@tonic-gate */ 6550Sstevel@tonic-gate void 6560Sstevel@tonic-gate set_cpu_error_state(ch_cpu_errors_t *cpu_error_regs) 6570Sstevel@tonic-gate { 6580Sstevel@tonic-gate set_asyncflt(cpu_error_regs->afsr & ~C_AFSR_FATAL_ERRS); 6590Sstevel@tonic-gate } 6600Sstevel@tonic-gate 6610Sstevel@tonic-gate /* 6620Sstevel@tonic-gate * For Cheetah, the error recovery code uses an alternate flush area in the 6630Sstevel@tonic-gate * TL>0 fast ECC handler. ecache_tl1_flushaddr is the physical address of 6640Sstevel@tonic-gate * this exclusive displacement flush area. 6650Sstevel@tonic-gate */ 6660Sstevel@tonic-gate uint64_t ecache_tl1_flushaddr = (uint64_t)-1; /* physaddr for E$ flushing */ 6670Sstevel@tonic-gate 6680Sstevel@tonic-gate /* 6690Sstevel@tonic-gate * Allocate and initialize the exclusive displacement flush area. 6703764Sdp78419 * Called twice. The first time allocates virtual address. The second 6713764Sdp78419 * call looks up the physical address. 6720Sstevel@tonic-gate */ 6730Sstevel@tonic-gate caddr_t 6740Sstevel@tonic-gate ecache_init_scrub_flush_area(caddr_t alloc_base) 6750Sstevel@tonic-gate { 6763764Sdp78419 static caddr_t ecache_tl1_virtaddr; 6770Sstevel@tonic-gate 6783764Sdp78419 if (alloc_base != NULL) { 6793764Sdp78419 /* 6803764Sdp78419 * Need to allocate an exclusive flush area that is twice the 6813764Sdp78419 * largest supported E$ size, physically contiguous, and 6823764Sdp78419 * aligned on twice the largest E$ size boundary. 6833764Sdp78419 */ 6843764Sdp78419 unsigned size = 2 * CH_ECACHE_8M_SIZE; 6853764Sdp78419 caddr_t va = (caddr_t)roundup((uintptr_t)alloc_base, size); 6860Sstevel@tonic-gate 6873764Sdp78419 ecache_tl1_virtaddr = va; 6883764Sdp78419 alloc_base = va + size; 6890Sstevel@tonic-gate 6900Sstevel@tonic-gate } else { 6913764Sdp78419 /* 6923764Sdp78419 * Get the physical address of the exclusive flush area. 6933764Sdp78419 */ 6943764Sdp78419 ASSERT(ecache_tl1_virtaddr != NULL); 6953764Sdp78419 ecache_tl1_flushaddr = va_to_pa(ecache_tl1_virtaddr); 6963764Sdp78419 ASSERT(ecache_tl1_flushaddr != ((uint64_t)-1)); 6970Sstevel@tonic-gate } 6980Sstevel@tonic-gate 6993764Sdp78419 return (alloc_base); 7000Sstevel@tonic-gate } 7010Sstevel@tonic-gate 7020Sstevel@tonic-gate /* 7030Sstevel@tonic-gate * Update cpu_offline_set so the scrubber knows which cpus are offline 7040Sstevel@tonic-gate */ 7050Sstevel@tonic-gate /*ARGSUSED*/ 7060Sstevel@tonic-gate int 7070Sstevel@tonic-gate cpu_scrub_cpu_setup(cpu_setup_t what, int cpuid, void *arg) 7080Sstevel@tonic-gate { 7090Sstevel@tonic-gate switch (what) { 7100Sstevel@tonic-gate case CPU_ON: 7110Sstevel@tonic-gate case CPU_INIT: 7120Sstevel@tonic-gate CPUSET_DEL(cpu_offline_set, cpuid); 7130Sstevel@tonic-gate break; 7140Sstevel@tonic-gate case CPU_OFF: 7150Sstevel@tonic-gate CPUSET_ADD(cpu_offline_set, cpuid); 7160Sstevel@tonic-gate break; 7170Sstevel@tonic-gate default: 7180Sstevel@tonic-gate break; 7190Sstevel@tonic-gate } 7200Sstevel@tonic-gate return (0); 7210Sstevel@tonic-gate } 722