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 5*2414Saguzovsk * Common Development and Distribution License (the "License"). 6*2414Saguzovsk * 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 /* 22*2414Saguzovsk * Copyright 2006 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 /* 720Sstevel@tonic-gate * Setup trap handlers. 730Sstevel@tonic-gate */ 740Sstevel@tonic-gate void 750Sstevel@tonic-gate cpu_init_trap(void) 760Sstevel@tonic-gate { 770Sstevel@tonic-gate CH_SET_TRAP(tt_pil15, ch_pil15_interrupt_instr); 780Sstevel@tonic-gate 790Sstevel@tonic-gate CH_SET_TRAP(tt0_fecc, fecc_err_instr); 800Sstevel@tonic-gate CH_SET_TRAP(tt1_fecc, fecc_err_tl1_instr); 810Sstevel@tonic-gate CH_SET_TRAP(tt1_swtrap0, fecc_err_tl1_cont_instr); 820Sstevel@tonic-gate } 830Sstevel@tonic-gate 840Sstevel@tonic-gate static int 85789Sahrens getintprop(pnode_t node, char *name, int deflt) 860Sstevel@tonic-gate { 870Sstevel@tonic-gate int value; 880Sstevel@tonic-gate 890Sstevel@tonic-gate switch (prom_getproplen(node, name)) { 900Sstevel@tonic-gate case sizeof (int): 910Sstevel@tonic-gate (void) prom_getprop(node, name, (caddr_t)&value); 920Sstevel@tonic-gate break; 930Sstevel@tonic-gate 940Sstevel@tonic-gate default: 950Sstevel@tonic-gate value = deflt; 960Sstevel@tonic-gate break; 970Sstevel@tonic-gate } 980Sstevel@tonic-gate 990Sstevel@tonic-gate return (value); 1000Sstevel@tonic-gate } 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate /* 1030Sstevel@tonic-gate * Set the magic constants of the implementation. 1040Sstevel@tonic-gate */ 1050Sstevel@tonic-gate /*ARGSUSED*/ 1060Sstevel@tonic-gate void 107789Sahrens cpu_fiximp(pnode_t dnode) 1080Sstevel@tonic-gate { 1090Sstevel@tonic-gate int i, a; 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate static struct { 1120Sstevel@tonic-gate char *name; 1130Sstevel@tonic-gate int *var; 1140Sstevel@tonic-gate int defval; 1150Sstevel@tonic-gate } prop[] = { 1160Sstevel@tonic-gate "dcache-size", &dcache_size, CH_DCACHE_SIZE, 1170Sstevel@tonic-gate "dcache-line-size", &dcache_linesize, CH_DCACHE_LSIZE, 1180Sstevel@tonic-gate "icache-size", &icache_size, CH_ICACHE_SIZE, 1190Sstevel@tonic-gate "icache-line-size", &icache_linesize, CH_ICACHE_LSIZE, 1200Sstevel@tonic-gate "ecache-size", &ecache_size, CH_ECACHE_MAX_SIZE, 1210Sstevel@tonic-gate "ecache-line-size", &ecache_alignsize, CH_ECACHE_MAX_LSIZE, 1220Sstevel@tonic-gate "ecache-associativity", &ecache_associativity, CH_ECACHE_NWAY 1230Sstevel@tonic-gate }; 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate extern int exec_lpg_disable, use_brk_lpg, use_stk_lpg, use_zmap_lpg; 126*2414Saguzovsk extern size_t max_shm_lpsize; 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate for (i = 0; i < sizeof (prop) / sizeof (prop[0]); i++) 1300Sstevel@tonic-gate *prop[i].var = getintprop(dnode, prop[i].name, prop[i].defval); 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate ecache_setsize = ecache_size / ecache_associativity; 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate vac_size = CH_VAC_SIZE; 1350Sstevel@tonic-gate vac_mask = MMU_PAGEMASK & (vac_size - 1); 1360Sstevel@tonic-gate i = 0; a = vac_size; 1370Sstevel@tonic-gate while (a >>= 1) 1380Sstevel@tonic-gate ++i; 1390Sstevel@tonic-gate vac_shift = i; 1400Sstevel@tonic-gate shm_alignment = vac_size; 1410Sstevel@tonic-gate vac = 1; 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate /* 1440Sstevel@tonic-gate * Cheetah's large page support has problems with large numbers of 1450Sstevel@tonic-gate * large pages, so just disable large pages out-of-the-box. 1460Sstevel@tonic-gate */ 1470Sstevel@tonic-gate exec_lpg_disable = 1; 1480Sstevel@tonic-gate use_brk_lpg = 0; 1490Sstevel@tonic-gate use_stk_lpg = 0; 1500Sstevel@tonic-gate use_zmap_lpg = 0; 151*2414Saguzovsk max_shm_lpsize = MMU_PAGESIZE; 1520Sstevel@tonic-gate } 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate void 1550Sstevel@tonic-gate send_mondo_set(cpuset_t set) 1560Sstevel@tonic-gate { 1570Sstevel@tonic-gate int lo, busy, nack, shipped = 0; 1580Sstevel@tonic-gate uint16_t i, cpuids[IDSR_BN_SETS]; 1590Sstevel@tonic-gate uint64_t idsr, nackmask = 0, busymask, curnack, curbusy; 1600Sstevel@tonic-gate uint64_t starttick, endtick, tick, lasttick; 1610Sstevel@tonic-gate #if (NCPU > IDSR_BN_SETS) 1620Sstevel@tonic-gate int index = 0; 1630Sstevel@tonic-gate int ncpuids = 0; 1640Sstevel@tonic-gate #endif 1650Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 1660Sstevel@tonic-gate int recovered = 0; 1670Sstevel@tonic-gate int cpuid; 1680Sstevel@tonic-gate #endif 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate ASSERT(!CPUSET_ISNULL(set)); 1710Sstevel@tonic-gate starttick = lasttick = gettick(); 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate #if (NCPU <= IDSR_BN_SETS) 1740Sstevel@tonic-gate for (i = 0; i < NCPU; i++) 1750Sstevel@tonic-gate if (CPU_IN_SET(set, i)) { 1760Sstevel@tonic-gate shipit(i, shipped); 1770Sstevel@tonic-gate nackmask |= IDSR_NACK_BIT(shipped); 1780Sstevel@tonic-gate cpuids[shipped++] = i; 1790Sstevel@tonic-gate CPUSET_DEL(set, i); 1800Sstevel@tonic-gate if (CPUSET_ISNULL(set)) 1810Sstevel@tonic-gate break; 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, xcalls, shipped); 1840Sstevel@tonic-gate #else 1850Sstevel@tonic-gate for (i = 0; i < NCPU; i++) 1860Sstevel@tonic-gate if (CPU_IN_SET(set, i)) { 1870Sstevel@tonic-gate ncpuids++; 1880Sstevel@tonic-gate 1890Sstevel@tonic-gate /* 1900Sstevel@tonic-gate * Ship only to the first (IDSR_BN_SETS) CPUs. If we 1910Sstevel@tonic-gate * find we have shipped to more than (IDSR_BN_SETS) 1920Sstevel@tonic-gate * CPUs, set "index" to the highest numbered CPU in 1930Sstevel@tonic-gate * the set so we can ship to other CPUs a bit later on. 1940Sstevel@tonic-gate */ 1950Sstevel@tonic-gate if (shipped < IDSR_BN_SETS) { 1960Sstevel@tonic-gate shipit(i, shipped); 1970Sstevel@tonic-gate nackmask |= IDSR_NACK_BIT(shipped); 1980Sstevel@tonic-gate cpuids[shipped++] = i; 1990Sstevel@tonic-gate CPUSET_DEL(set, i); 2000Sstevel@tonic-gate if (CPUSET_ISNULL(set)) 2010Sstevel@tonic-gate break; 2020Sstevel@tonic-gate } else 2030Sstevel@tonic-gate index = (int)i; 2040Sstevel@tonic-gate } 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, xcalls, ncpuids); 2070Sstevel@tonic-gate #endif 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate busymask = IDSR_NACK_TO_BUSY(nackmask); 2100Sstevel@tonic-gate busy = nack = 0; 2110Sstevel@tonic-gate endtick = starttick + xc_tick_limit; 2120Sstevel@tonic-gate for (;;) { 2130Sstevel@tonic-gate idsr = getidsr(); 2140Sstevel@tonic-gate #if (NCPU <= IDSR_BN_SETS) 2150Sstevel@tonic-gate if (idsr == 0) 2160Sstevel@tonic-gate break; 2170Sstevel@tonic-gate #else 2180Sstevel@tonic-gate if (idsr == 0 && shipped == ncpuids) 2190Sstevel@tonic-gate break; 2200Sstevel@tonic-gate #endif 2210Sstevel@tonic-gate tick = gettick(); 2220Sstevel@tonic-gate /* 2230Sstevel@tonic-gate * If there is a big jump between the current tick 2240Sstevel@tonic-gate * count and lasttick, we have probably hit a break 2250Sstevel@tonic-gate * point. Adjust endtick accordingly to avoid panic. 2260Sstevel@tonic-gate */ 2270Sstevel@tonic-gate if (tick > (lasttick + xc_tick_jump_limit)) 2280Sstevel@tonic-gate endtick += (tick - lasttick); 2290Sstevel@tonic-gate lasttick = tick; 2300Sstevel@tonic-gate if (tick > endtick) { 2310Sstevel@tonic-gate if (panic_quiesce) 2320Sstevel@tonic-gate return; 2330Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 2340Sstevel@tonic-gate cpuid = -1; 2350Sstevel@tonic-gate for (i = 0; i < IDSR_BN_SETS; i++) { 2360Sstevel@tonic-gate if (idsr & (IDSR_NACK_BIT(i) | 2370Sstevel@tonic-gate IDSR_BUSY_BIT(i))) { 2380Sstevel@tonic-gate cpuid = cpuids[i]; 2390Sstevel@tonic-gate break; 2400Sstevel@tonic-gate } 2410Sstevel@tonic-gate } 2420Sstevel@tonic-gate if (cheetah_sendmondo_recover && cpuid != -1 && 2430Sstevel@tonic-gate recovered == 0) { 2440Sstevel@tonic-gate if (mondo_recover(cpuid, i)) { 2450Sstevel@tonic-gate /* 2460Sstevel@tonic-gate * We claimed the whole memory or 2470Sstevel@tonic-gate * full scan is disabled. 2480Sstevel@tonic-gate */ 2490Sstevel@tonic-gate recovered++; 2500Sstevel@tonic-gate } 2510Sstevel@tonic-gate tick = gettick(); 2520Sstevel@tonic-gate endtick = tick + xc_tick_limit; 2530Sstevel@tonic-gate lasttick = tick; 2540Sstevel@tonic-gate /* 2550Sstevel@tonic-gate * Recheck idsr 2560Sstevel@tonic-gate */ 2570Sstevel@tonic-gate continue; 2580Sstevel@tonic-gate } else 2590Sstevel@tonic-gate #endif /* CHEETAHPLUS_ERRATUM_25 */ 2600Sstevel@tonic-gate { 2610Sstevel@tonic-gate cmn_err(CE_CONT, "send mondo timeout " 2620Sstevel@tonic-gate "[%d NACK %d BUSY]\nIDSR 0x%" 2630Sstevel@tonic-gate "" PRIx64 " cpuids:", nack, busy, idsr); 2640Sstevel@tonic-gate for (i = 0; i < IDSR_BN_SETS; i++) { 2650Sstevel@tonic-gate if (idsr & (IDSR_NACK_BIT(i) | 2660Sstevel@tonic-gate IDSR_BUSY_BIT(i))) { 2670Sstevel@tonic-gate cmn_err(CE_CONT, " 0x%x", 2680Sstevel@tonic-gate cpuids[i]); 2690Sstevel@tonic-gate } 2700Sstevel@tonic-gate } 2710Sstevel@tonic-gate cmn_err(CE_CONT, "\n"); 2720Sstevel@tonic-gate cmn_err(CE_PANIC, "send_mondo_set: timeout"); 2730Sstevel@tonic-gate } 2740Sstevel@tonic-gate } 2750Sstevel@tonic-gate curnack = idsr & nackmask; 2760Sstevel@tonic-gate curbusy = idsr & busymask; 2770Sstevel@tonic-gate #if (NCPU > IDSR_BN_SETS) 2780Sstevel@tonic-gate if (shipped < ncpuids) { 2790Sstevel@tonic-gate uint64_t cpus_left; 2800Sstevel@tonic-gate uint16_t next = (uint16_t)index; 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate cpus_left = ~(IDSR_NACK_TO_BUSY(curnack) | curbusy) & 2830Sstevel@tonic-gate busymask; 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate if (cpus_left) { 2860Sstevel@tonic-gate do { 2870Sstevel@tonic-gate /* 2880Sstevel@tonic-gate * Sequence through and ship to the 2890Sstevel@tonic-gate * remainder of the CPUs in the system 2900Sstevel@tonic-gate * (e.g. other than the first 2910Sstevel@tonic-gate * (IDSR_BN_SETS)) in reverse order. 2920Sstevel@tonic-gate */ 2930Sstevel@tonic-gate lo = lowbit(cpus_left) - 1; 2940Sstevel@tonic-gate i = IDSR_BUSY_IDX(lo); 2950Sstevel@tonic-gate shipit(next, i); 2960Sstevel@tonic-gate shipped++; 2970Sstevel@tonic-gate cpuids[i] = next; 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate /* 3000Sstevel@tonic-gate * If we've processed all the CPUs, 3010Sstevel@tonic-gate * exit the loop now and save 3020Sstevel@tonic-gate * instructions. 3030Sstevel@tonic-gate */ 3040Sstevel@tonic-gate if (shipped == ncpuids) 3050Sstevel@tonic-gate break; 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate for ((index = ((int)next - 1)); 3080Sstevel@tonic-gate index >= 0; index--) 3090Sstevel@tonic-gate if (CPU_IN_SET(set, index)) { 3100Sstevel@tonic-gate next = (uint16_t)index; 3110Sstevel@tonic-gate break; 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate cpus_left &= ~(1ull << lo); 3150Sstevel@tonic-gate } while (cpus_left); 3160Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 3170Sstevel@tonic-gate /* 3180Sstevel@tonic-gate * Clear recovered because we are sending to 3190Sstevel@tonic-gate * a new set of targets. 3200Sstevel@tonic-gate */ 3210Sstevel@tonic-gate recovered = 0; 3220Sstevel@tonic-gate #endif 3230Sstevel@tonic-gate continue; 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate } 3260Sstevel@tonic-gate #endif 3270Sstevel@tonic-gate if (curbusy) { 3280Sstevel@tonic-gate busy++; 3290Sstevel@tonic-gate continue; 3300Sstevel@tonic-gate } 3310Sstevel@tonic-gate 3320Sstevel@tonic-gate #ifdef SEND_MONDO_STATS 3330Sstevel@tonic-gate { 3340Sstevel@tonic-gate int n = gettick() - starttick; 3350Sstevel@tonic-gate if (n < 8192) 3360Sstevel@tonic-gate x_nack_stimes[n >> 7]++; 3370Sstevel@tonic-gate } 3380Sstevel@tonic-gate #endif 3390Sstevel@tonic-gate while (gettick() < (tick + sys_clock_mhz)) 3400Sstevel@tonic-gate ; 3410Sstevel@tonic-gate do { 3420Sstevel@tonic-gate lo = lowbit(curnack) - 1; 3430Sstevel@tonic-gate i = IDSR_NACK_IDX(lo); 3440Sstevel@tonic-gate shipit(cpuids[i], i); 3450Sstevel@tonic-gate curnack &= ~(1ull << lo); 3460Sstevel@tonic-gate } while (curnack); 3470Sstevel@tonic-gate nack++; 3480Sstevel@tonic-gate busy = 0; 3490Sstevel@tonic-gate } 3500Sstevel@tonic-gate #ifdef SEND_MONDO_STATS 3510Sstevel@tonic-gate { 3520Sstevel@tonic-gate int n = gettick() - starttick; 3530Sstevel@tonic-gate if (n < 8192) 3540Sstevel@tonic-gate x_set_stimes[n >> 7]++; 3550Sstevel@tonic-gate else 3560Sstevel@tonic-gate x_set_ltimes[(n >> 13) & 0xf]++; 3570Sstevel@tonic-gate } 3580Sstevel@tonic-gate x_set_cpus[shipped]++; 3590Sstevel@tonic-gate #endif 3600Sstevel@tonic-gate } 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate /* 3630Sstevel@tonic-gate * Handles error logging for implementation specific error types. 3640Sstevel@tonic-gate */ 3650Sstevel@tonic-gate /*ARGSUSED*/ 3660Sstevel@tonic-gate int 3670Sstevel@tonic-gate cpu_impl_async_log_err(void *flt, errorq_elem_t *eqep) 3680Sstevel@tonic-gate { 3690Sstevel@tonic-gate /* There aren't any error types which are specific to cheetah only */ 3700Sstevel@tonic-gate return (CH_ASYNC_LOG_UNKNOWN); 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate /* 3740Sstevel@tonic-gate * Figure out if Ecache is direct-mapped (Cheetah or Cheetah+ with Ecache 3750Sstevel@tonic-gate * control ECCR_ASSOC bit off or 2-way (Cheetah+ with ECCR_ASSOC on). 3760Sstevel@tonic-gate * We need to do this on the fly because we may have mixed Cheetah+'s with 3770Sstevel@tonic-gate * both direct and 2-way Ecaches. 3780Sstevel@tonic-gate */ 3790Sstevel@tonic-gate int 3800Sstevel@tonic-gate cpu_ecache_nway(void) 3810Sstevel@tonic-gate { 3820Sstevel@tonic-gate return (CH_ECACHE_NWAY); 3830Sstevel@tonic-gate } 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate /* 3860Sstevel@tonic-gate * Note that these are entered into the table: Fatal Errors (PERR, IERR, 3870Sstevel@tonic-gate * ISAP, EMU) first, orphaned UCU/UCC, AFAR Overwrite policy, finally IVU, IVC. 3880Sstevel@tonic-gate * Afar overwrite policy is: 3890Sstevel@tonic-gate * UCU,UCC > UE,EDU,WDU,CPU > CE,EDC,EMC,WDC,CPC > TO,BERR 3900Sstevel@tonic-gate */ 3910Sstevel@tonic-gate ecc_type_to_info_t ecc_type_to_info[] = { 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate /* Fatal Errors */ 3940Sstevel@tonic-gate C_AFSR_PERR, "PERR ", ECC_ALL_TRAPS, CPU_FATAL, 3950Sstevel@tonic-gate "PERR Fatal", 3960Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM2, 3970Sstevel@tonic-gate FM_EREPORT_CPU_USIII_PERR, 3980Sstevel@tonic-gate C_AFSR_IERR, "IERR ", ECC_ALL_TRAPS, CPU_FATAL, 3990Sstevel@tonic-gate "IERR Fatal", 4000Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM2, 4010Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IERR, 4020Sstevel@tonic-gate C_AFSR_ISAP, "ISAP ", ECC_ALL_TRAPS, CPU_FATAL, 4030Sstevel@tonic-gate "ISAP Fatal", 4040Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 4050Sstevel@tonic-gate FM_EREPORT_CPU_USIII_ISAP, 4060Sstevel@tonic-gate C_AFSR_EMU, "EMU ", ECC_ASYNC_TRAPS, CPU_FATAL, 4070Sstevel@tonic-gate "EMU Fatal", 4080Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 4090Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EMU, 4100Sstevel@tonic-gate 4110Sstevel@tonic-gate /* Orphaned UCC/UCU Errors */ 4120Sstevel@tonic-gate C_AFSR_UCU, "OUCU ", ECC_ORPH_TRAPS, CPU_ORPH, 4130Sstevel@tonic-gate "Orphaned UCU", 4140Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4150Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCU, 4160Sstevel@tonic-gate C_AFSR_UCC, "OUCC ", ECC_ORPH_TRAPS, CPU_ORPH, 4170Sstevel@tonic-gate "Orphaned UCC", 4180Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4190Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCC, 4200Sstevel@tonic-gate 4210Sstevel@tonic-gate /* UCU, UCC */ 4220Sstevel@tonic-gate C_AFSR_UCU, "UCU ", ECC_F_TRAP, CPU_UE_ECACHE, 4230Sstevel@tonic-gate "UCU", 4240Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4250Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCU, 4260Sstevel@tonic-gate C_AFSR_UCC, "UCC ", ECC_F_TRAP, CPU_CE_ECACHE, 4270Sstevel@tonic-gate "UCC", 4280Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4290Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCC, 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate /* UE, EDU:ST, EDU:BLD, WDU, CPU */ 4320Sstevel@tonic-gate C_AFSR_UE, "UE ", ECC_ASYNC_TRAPS, CPU_UE, 4330Sstevel@tonic-gate "Uncorrectable system bus (UE)", 4340Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 4350Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UE, 4360Sstevel@tonic-gate C_AFSR_EDU, "EDU ", ECC_C_TRAP, CPU_UE_ECACHE_RETIRE, 4370Sstevel@tonic-gate "EDU:ST", 4380Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4390Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EDUST, 4400Sstevel@tonic-gate C_AFSR_EDU, "EDU ", ECC_D_TRAP, CPU_UE_ECACHE_RETIRE, 4410Sstevel@tonic-gate "EDU:BLD", 4420Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4430Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EDUBL, 4440Sstevel@tonic-gate C_AFSR_WDU, "WDU ", ECC_C_TRAP, CPU_UE_ECACHE_RETIRE, 4450Sstevel@tonic-gate "WDU", 4460Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4470Sstevel@tonic-gate FM_EREPORT_CPU_USIII_WDU, 4480Sstevel@tonic-gate C_AFSR_CPU, "CPU ", ECC_C_TRAP, CPU_UE_ECACHE, 4490Sstevel@tonic-gate "CPU", 4500Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4510Sstevel@tonic-gate FM_EREPORT_CPU_USIII_CPU, 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate /* CE, EDC, EMC, WDC, CPC */ 4540Sstevel@tonic-gate C_AFSR_CE, "CE ", ECC_C_TRAP, CPU_CE, 4550Sstevel@tonic-gate "Corrected system bus (CE)", 4560Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 4570Sstevel@tonic-gate FM_EREPORT_CPU_USIII_CE, 4580Sstevel@tonic-gate C_AFSR_EDC, "EDC ", ECC_C_TRAP, CPU_CE_ECACHE, 4590Sstevel@tonic-gate "EDC", 4600Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4610Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EDC, 4620Sstevel@tonic-gate C_AFSR_EMC, "EMC ", ECC_C_TRAP, CPU_EMC, 4630Sstevel@tonic-gate "EMC", 4640Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 4650Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EMC, 4660Sstevel@tonic-gate C_AFSR_WDC, "WDC ", ECC_C_TRAP, CPU_CE_ECACHE, 4670Sstevel@tonic-gate "WDC", 4680Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4690Sstevel@tonic-gate FM_EREPORT_CPU_USIII_WDC, 4700Sstevel@tonic-gate C_AFSR_CPC, "CPC ", ECC_C_TRAP, CPU_CE_ECACHE, 4710Sstevel@tonic-gate "CPC", 4720Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4730Sstevel@tonic-gate FM_EREPORT_CPU_USIII_CPC, 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate /* TO, BERR */ 4760Sstevel@tonic-gate C_AFSR_TO, "TO ", ECC_ASYNC_TRAPS, CPU_TO, 4770Sstevel@tonic-gate "Timeout (TO)", 4780Sstevel@tonic-gate FM_EREPORT_PAYLOAD_IO, 4790Sstevel@tonic-gate FM_EREPORT_CPU_USIII_TO, 4800Sstevel@tonic-gate C_AFSR_BERR, "BERR ", ECC_ASYNC_TRAPS, CPU_BERR, 4810Sstevel@tonic-gate "Bus Error (BERR)", 4820Sstevel@tonic-gate FM_EREPORT_PAYLOAD_IO, 4830Sstevel@tonic-gate FM_EREPORT_CPU_USIII_BERR, 4840Sstevel@tonic-gate 4850Sstevel@tonic-gate /* IVU, IVC */ 4860Sstevel@tonic-gate C_AFSR_IVU, "IVU ", ECC_C_TRAP, CPU_IV, 4870Sstevel@tonic-gate "IVU", 4880Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 4890Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IVU, 4900Sstevel@tonic-gate C_AFSR_IVC, "IVC ", ECC_C_TRAP, CPU_IV, 4910Sstevel@tonic-gate "IVC", 4920Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 4930Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IVC, 4940Sstevel@tonic-gate 4950Sstevel@tonic-gate 0, NULL, 0, 0, 4960Sstevel@tonic-gate NULL, 4970Sstevel@tonic-gate FM_EREPORT_PAYLOAD_UNKNOWN, 4980Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UNKNOWN, 4990Sstevel@tonic-gate }; 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate /* 5020Sstevel@tonic-gate * Prioritized list of Error bits for AFAR overwrite. 5030Sstevel@tonic-gate * See Cheetah PRM P.6.1 5040Sstevel@tonic-gate * Class 4: UCC, UCU 5050Sstevel@tonic-gate * Class 3: UE, EDU, EMU, WDU, CPU 5060Sstevel@tonic-gate * Class 2: CE, EDC, EMC, WDC, CPC 5070Sstevel@tonic-gate * Class 1: TO, BERR 5080Sstevel@tonic-gate */ 5090Sstevel@tonic-gate uint64_t afar_overwrite[] = { 5100Sstevel@tonic-gate C_AFSR_UCC | C_AFSR_UCU, 5110Sstevel@tonic-gate C_AFSR_UE | C_AFSR_EDU | C_AFSR_EMU | C_AFSR_WDU | C_AFSR_CPU, 5120Sstevel@tonic-gate C_AFSR_CE | C_AFSR_EDC | C_AFSR_EMC | C_AFSR_WDC | C_AFSR_CPC, 5130Sstevel@tonic-gate C_AFSR_TO | C_AFSR_BERR, 5140Sstevel@tonic-gate 0 5150Sstevel@tonic-gate }; 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate /* 5180Sstevel@tonic-gate * Prioritized list of Error bits for ESYND overwrite. 5190Sstevel@tonic-gate * See Cheetah PRM P.6.2 5200Sstevel@tonic-gate * Class 2: UE, IVU, EDU, WDU, UCU, CPU 5210Sstevel@tonic-gate * Class 1: CE, IVC, EDC, WDC, UCC, CPC 5220Sstevel@tonic-gate */ 5230Sstevel@tonic-gate uint64_t esynd_overwrite[] = { 5240Sstevel@tonic-gate C_AFSR_UE | C_AFSR_IVU | C_AFSR_EDU | C_AFSR_WDU | C_AFSR_UCU | 5250Sstevel@tonic-gate C_AFSR_CPU, 5260Sstevel@tonic-gate C_AFSR_CE | C_AFSR_IVC | C_AFSR_EDC | C_AFSR_WDC | C_AFSR_UCC | 5270Sstevel@tonic-gate C_AFSR_CPC, 5280Sstevel@tonic-gate 0 5290Sstevel@tonic-gate }; 5300Sstevel@tonic-gate 5310Sstevel@tonic-gate /* 5320Sstevel@tonic-gate * Prioritized list of Error bits for MSYND overwrite. 5330Sstevel@tonic-gate * See Cheetah PRM P.6.3 5340Sstevel@tonic-gate * Class 2: EMU 5350Sstevel@tonic-gate * Class 1: EMC 5360Sstevel@tonic-gate */ 5370Sstevel@tonic-gate uint64_t msynd_overwrite[] = { 5380Sstevel@tonic-gate C_AFSR_EMU, 5390Sstevel@tonic-gate C_AFSR_EMC, 5400Sstevel@tonic-gate 0 5410Sstevel@tonic-gate }; 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate /* 5440Sstevel@tonic-gate * change cpu speed bits -- new speed will be normal-speed/divisor. 5450Sstevel@tonic-gate * 5460Sstevel@tonic-gate * The Jalapeno memory controllers are required to drain outstanding 5470Sstevel@tonic-gate * memory transactions within 32 JBus clocks in order to be ready 5480Sstevel@tonic-gate * to enter Estar mode. In some corner cases however, that time 5490Sstevel@tonic-gate * fell short. 5500Sstevel@tonic-gate * 5510Sstevel@tonic-gate * A safe software solution is to force MCU to act like in Estar mode, 5520Sstevel@tonic-gate * then delay 1us (in ppm code) prior to assert J_CHNG_L signal. 5530Sstevel@tonic-gate * To reverse the effect, upon exiting Estar, software restores the 5540Sstevel@tonic-gate * MCU to its original state. 5550Sstevel@tonic-gate */ 5560Sstevel@tonic-gate /* ARGSUSED1 */ 5570Sstevel@tonic-gate void 5580Sstevel@tonic-gate cpu_change_speed(uint64_t divisor, uint64_t arg2) 5590Sstevel@tonic-gate { 5600Sstevel@tonic-gate bus_config_eclk_t *bceclk; 5610Sstevel@tonic-gate uint64_t reg; 5620Sstevel@tonic-gate 5630Sstevel@tonic-gate for (bceclk = bus_config_eclk; bceclk->divisor; bceclk++) { 5640Sstevel@tonic-gate if (bceclk->divisor != divisor) 5650Sstevel@tonic-gate continue; 5660Sstevel@tonic-gate reg = get_safari_config(); 5670Sstevel@tonic-gate reg &= ~SAFARI_CONFIG_ECLK_MASK; 5680Sstevel@tonic-gate reg |= bceclk->mask; 5690Sstevel@tonic-gate set_safari_config(reg); 5700Sstevel@tonic-gate CPU->cpu_m.divisor = (uchar_t)divisor; 5710Sstevel@tonic-gate return; 5720Sstevel@tonic-gate } 5730Sstevel@tonic-gate /* 5740Sstevel@tonic-gate * We will reach here only if OBP and kernel don't agree on 5750Sstevel@tonic-gate * the speeds supported by the CPU. 5760Sstevel@tonic-gate */ 5770Sstevel@tonic-gate cmn_err(CE_WARN, "cpu_change_speed: bad divisor %" PRIu64, divisor); 5780Sstevel@tonic-gate } 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate /* 5810Sstevel@tonic-gate * Cpu private initialization. This includes allocating the cpu_private 5820Sstevel@tonic-gate * data structure, initializing it, and initializing the scrubber for this 5830Sstevel@tonic-gate * cpu. This function calls cpu_init_ecache_scrub_dr to init the scrubber. 5840Sstevel@tonic-gate * We use kmem_cache_create for the cheetah private data structure because 5850Sstevel@tonic-gate * it needs to be allocated on a PAGESIZE (8192) byte boundary. 5860Sstevel@tonic-gate */ 5870Sstevel@tonic-gate void 5880Sstevel@tonic-gate cpu_init_private(struct cpu *cp) 5890Sstevel@tonic-gate { 5900Sstevel@tonic-gate cheetah_private_t *chprp; 5910Sstevel@tonic-gate int i; 5920Sstevel@tonic-gate 5930Sstevel@tonic-gate ASSERT(CPU_PRIVATE(cp) == NULL); 5940Sstevel@tonic-gate 5950Sstevel@tonic-gate /* LINTED: E_TRUE_LOGICAL_EXPR */ 5960Sstevel@tonic-gate ASSERT((offsetof(cheetah_private_t, chpr_tl1_err_data) + 5970Sstevel@tonic-gate sizeof (ch_err_tl1_data_t) * CH_ERR_TL1_TLMAX) <= PAGESIZE); 5980Sstevel@tonic-gate 5990Sstevel@tonic-gate /* 6000Sstevel@tonic-gate * Running with a Cheetah+, Jaguar, or Panther on a Cheetah CPU 6010Sstevel@tonic-gate * machine is not a supported configuration. Attempting to do so 6020Sstevel@tonic-gate * may result in unpredictable failures (e.g. running Cheetah+ 6030Sstevel@tonic-gate * CPUs with Cheetah E$ disp flush) so don't allow it. 6040Sstevel@tonic-gate * 6050Sstevel@tonic-gate * This is just defensive code since this configuration mismatch 6060Sstevel@tonic-gate * should have been caught prior to OS execution. 6070Sstevel@tonic-gate */ 6080Sstevel@tonic-gate if (!IS_CHEETAH(cpunodes[cp->cpu_id].implementation)) { 6090Sstevel@tonic-gate cmn_err(CE_PANIC, "CPU%d: UltraSPARC-III+/IV/IV+ not" 6100Sstevel@tonic-gate " supported on UltraSPARC-III code\n", cp->cpu_id); 6110Sstevel@tonic-gate } 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate /* 6140Sstevel@tonic-gate * If the ch_private_cache has not been created, create it. 6150Sstevel@tonic-gate */ 6160Sstevel@tonic-gate if (ch_private_cache == NULL) { 6170Sstevel@tonic-gate ch_private_cache = kmem_cache_create("ch_private_cache", 6180Sstevel@tonic-gate sizeof (cheetah_private_t), PAGESIZE, NULL, NULL, 6190Sstevel@tonic-gate NULL, NULL, static_arena, 0); 6200Sstevel@tonic-gate } 6210Sstevel@tonic-gate 6220Sstevel@tonic-gate chprp = CPU_PRIVATE(cp) = kmem_cache_alloc(ch_private_cache, KM_SLEEP); 6230Sstevel@tonic-gate 6240Sstevel@tonic-gate bzero(chprp, sizeof (cheetah_private_t)); 6250Sstevel@tonic-gate chprp->chpr_fecctl0_logout.clo_data.chd_afar = LOGOUT_INVALID; 6260Sstevel@tonic-gate chprp->chpr_cecc_logout.clo_data.chd_afar = LOGOUT_INVALID; 6270Sstevel@tonic-gate chprp->chpr_async_logout.clo_data.chd_afar = LOGOUT_INVALID; 6280Sstevel@tonic-gate for (i = 0; i < CH_ERR_TL1_TLMAX; i++) 6290Sstevel@tonic-gate chprp->chpr_tl1_err_data[i].ch_err_tl1_logout.clo_data.chd_afar 6300Sstevel@tonic-gate = LOGOUT_INVALID; 6310Sstevel@tonic-gate 6320Sstevel@tonic-gate chprp->chpr_icache_size = CH_ICACHE_SIZE; 6330Sstevel@tonic-gate chprp->chpr_icache_linesize = CH_ICACHE_LSIZE; 6340Sstevel@tonic-gate 6350Sstevel@tonic-gate cpu_init_ecache_scrub_dr(cp); 6360Sstevel@tonic-gate 6370Sstevel@tonic-gate chprp->chpr_ec_set_size = cpunodes[cp->cpu_id].ecache_size / 6380Sstevel@tonic-gate cpu_ecache_nway(); 6390Sstevel@tonic-gate 6400Sstevel@tonic-gate adjust_hw_copy_limits(cpunodes[cp->cpu_id].ecache_size); 6410Sstevel@tonic-gate ch_err_tl1_paddrs[cp->cpu_id] = va_to_pa(chprp); 6420Sstevel@tonic-gate ASSERT(ch_err_tl1_paddrs[cp->cpu_id] != -1); 6430Sstevel@tonic-gate } 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate /* 6460Sstevel@tonic-gate * Clear the error state registers for this CPU. 6470Sstevel@tonic-gate * For Cheetah, just clear the AFSR 6480Sstevel@tonic-gate */ 6490Sstevel@tonic-gate void 6500Sstevel@tonic-gate set_cpu_error_state(ch_cpu_errors_t *cpu_error_regs) 6510Sstevel@tonic-gate { 6520Sstevel@tonic-gate set_asyncflt(cpu_error_regs->afsr & ~C_AFSR_FATAL_ERRS); 6530Sstevel@tonic-gate } 6540Sstevel@tonic-gate 6550Sstevel@tonic-gate /* 6560Sstevel@tonic-gate * For Cheetah, the error recovery code uses an alternate flush area in the 6570Sstevel@tonic-gate * TL>0 fast ECC handler. ecache_tl1_flushaddr is the physical address of 6580Sstevel@tonic-gate * this exclusive displacement flush area. 6590Sstevel@tonic-gate */ 6600Sstevel@tonic-gate uint64_t ecache_tl1_flushaddr = (uint64_t)-1; /* physaddr for E$ flushing */ 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate /* 6630Sstevel@tonic-gate * Allocate and initialize the exclusive displacement flush area. 6640Sstevel@tonic-gate * Must be called before startup_bop_gone(). 6650Sstevel@tonic-gate */ 6660Sstevel@tonic-gate caddr_t 6670Sstevel@tonic-gate ecache_init_scrub_flush_area(caddr_t alloc_base) 6680Sstevel@tonic-gate { 6690Sstevel@tonic-gate unsigned size = 2 * CH_ECACHE_8M_SIZE; 6700Sstevel@tonic-gate caddr_t tmp_alloc_base = alloc_base; 6710Sstevel@tonic-gate caddr_t flush_alloc_base = 6720Sstevel@tonic-gate (caddr_t)roundup((uintptr_t)alloc_base, size); 6730Sstevel@tonic-gate caddr_t ecache_tl1_virtaddr; 6740Sstevel@tonic-gate 6750Sstevel@tonic-gate /* 6760Sstevel@tonic-gate * Allocate the physical memory for the exclusive flush area 6770Sstevel@tonic-gate * 6780Sstevel@tonic-gate * Need to allocate an exclusive flush area that is twice the 6790Sstevel@tonic-gate * largest supported E$ size, physically contiguous, and 6800Sstevel@tonic-gate * aligned on twice the largest E$ size boundary. 6810Sstevel@tonic-gate * 6820Sstevel@tonic-gate * Memory allocated via BOP_ALLOC is included in the "cage" 6830Sstevel@tonic-gate * from the DR perspective and due to this, its physical 6840Sstevel@tonic-gate * address will never change and the memory will not be 6850Sstevel@tonic-gate * removed. 6860Sstevel@tonic-gate * 6870Sstevel@tonic-gate * BOP_ALLOC takes 4 arguments: bootops, virtual address hint, 6880Sstevel@tonic-gate * size of the area to allocate, and alignment of the area to 6890Sstevel@tonic-gate * allocate. It returns zero if the allocation fails, or the 6900Sstevel@tonic-gate * virtual address for a successful allocation. Memory BOP_ALLOC'd 6910Sstevel@tonic-gate * is physically contiguous. 6920Sstevel@tonic-gate */ 6930Sstevel@tonic-gate if ((ecache_tl1_virtaddr = (caddr_t)BOP_ALLOC(bootops, 6940Sstevel@tonic-gate flush_alloc_base, size, size)) != NULL) { 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate tmp_alloc_base = 6970Sstevel@tonic-gate (caddr_t)roundup((uintptr_t)(ecache_tl1_virtaddr + size), 6980Sstevel@tonic-gate ecache_alignsize); 6990Sstevel@tonic-gate 7000Sstevel@tonic-gate /* 7010Sstevel@tonic-gate * get the physical address of the exclusive flush area 7020Sstevel@tonic-gate */ 7030Sstevel@tonic-gate ecache_tl1_flushaddr = va_to_pa(ecache_tl1_virtaddr); 7040Sstevel@tonic-gate 7050Sstevel@tonic-gate } else { 7060Sstevel@tonic-gate ecache_tl1_virtaddr = (caddr_t)-1; 7070Sstevel@tonic-gate cmn_err(CE_NOTE, "!ecache_init_scrub_flush_area failed\n"); 7080Sstevel@tonic-gate } 7090Sstevel@tonic-gate 7100Sstevel@tonic-gate return (tmp_alloc_base); 7110Sstevel@tonic-gate } 7120Sstevel@tonic-gate 7130Sstevel@tonic-gate /* 7140Sstevel@tonic-gate * Update cpu_offline_set so the scrubber knows which cpus are offline 7150Sstevel@tonic-gate */ 7160Sstevel@tonic-gate /*ARGSUSED*/ 7170Sstevel@tonic-gate int 7180Sstevel@tonic-gate cpu_scrub_cpu_setup(cpu_setup_t what, int cpuid, void *arg) 7190Sstevel@tonic-gate { 7200Sstevel@tonic-gate switch (what) { 7210Sstevel@tonic-gate case CPU_ON: 7220Sstevel@tonic-gate case CPU_INIT: 7230Sstevel@tonic-gate CPUSET_DEL(cpu_offline_set, cpuid); 7240Sstevel@tonic-gate break; 7250Sstevel@tonic-gate case CPU_OFF: 7260Sstevel@tonic-gate CPUSET_ADD(cpu_offline_set, cpuid); 7270Sstevel@tonic-gate break; 7280Sstevel@tonic-gate default: 7290Sstevel@tonic-gate break; 7300Sstevel@tonic-gate } 7310Sstevel@tonic-gate return (0); 7320Sstevel@tonic-gate } 733