1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/systm.h> 31*0Sstevel@tonic-gate #include <sys/ddi.h> 32*0Sstevel@tonic-gate #include <sys/sysmacros.h> 33*0Sstevel@tonic-gate #include <sys/archsystm.h> 34*0Sstevel@tonic-gate #include <sys/vmsystm.h> 35*0Sstevel@tonic-gate #include <sys/machparam.h> 36*0Sstevel@tonic-gate #include <sys/machsystm.h> 37*0Sstevel@tonic-gate #include <sys/machthread.h> 38*0Sstevel@tonic-gate #include <sys/cpu.h> 39*0Sstevel@tonic-gate #include <sys/cmp.h> 40*0Sstevel@tonic-gate #include <sys/elf_SPARC.h> 41*0Sstevel@tonic-gate #include <vm/hat_sfmmu.h> 42*0Sstevel@tonic-gate #include <vm/seg_kmem.h> 43*0Sstevel@tonic-gate #include <sys/cpuvar.h> 44*0Sstevel@tonic-gate #include <sys/cheetahregs.h> 45*0Sstevel@tonic-gate #include <sys/us3_module.h> 46*0Sstevel@tonic-gate #include <sys/async.h> 47*0Sstevel@tonic-gate #include <sys/cmn_err.h> 48*0Sstevel@tonic-gate #include <sys/debug.h> 49*0Sstevel@tonic-gate #include <sys/dditypes.h> 50*0Sstevel@tonic-gate #include <sys/prom_debug.h> 51*0Sstevel@tonic-gate #include <sys/prom_plat.h> 52*0Sstevel@tonic-gate #include <sys/cpu_module.h> 53*0Sstevel@tonic-gate #include <sys/sysmacros.h> 54*0Sstevel@tonic-gate #include <sys/intreg.h> 55*0Sstevel@tonic-gate #include <sys/clock.h> 56*0Sstevel@tonic-gate #include <sys/platform_module.h> 57*0Sstevel@tonic-gate #include <sys/machtrap.h> 58*0Sstevel@tonic-gate #include <sys/ontrap.h> 59*0Sstevel@tonic-gate #include <sys/panic.h> 60*0Sstevel@tonic-gate #include <sys/memlist.h> 61*0Sstevel@tonic-gate #include <sys/bootconf.h> 62*0Sstevel@tonic-gate #include <sys/ivintr.h> 63*0Sstevel@tonic-gate #include <sys/atomic.h> 64*0Sstevel@tonic-gate #include <sys/fm/protocol.h> 65*0Sstevel@tonic-gate #include <sys/fm/cpu/UltraSPARC-III.h> 66*0Sstevel@tonic-gate #include <vm/vm_dep.h> 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 69*0Sstevel@tonic-gate #include <sys/cyclic.h> 70*0Sstevel@tonic-gate #endif /* CHEETAHPLUS_ERRATUM_25 */ 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate /* 73*0Sstevel@tonic-gate * Setup trap handlers. 74*0Sstevel@tonic-gate */ 75*0Sstevel@tonic-gate void 76*0Sstevel@tonic-gate cpu_init_trap(void) 77*0Sstevel@tonic-gate { 78*0Sstevel@tonic-gate CH_SET_TRAP(tt_pil15, ch_pil15_interrupt_instr); 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate CH_SET_TRAP(tt0_fecc, fecc_err_instr); 81*0Sstevel@tonic-gate CH_SET_TRAP(tt1_fecc, fecc_err_tl1_instr); 82*0Sstevel@tonic-gate CH_SET_TRAP(tt1_swtrap0, fecc_err_tl1_cont_instr); 83*0Sstevel@tonic-gate } 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate static int 86*0Sstevel@tonic-gate getintprop(dnode_t node, char *name, int deflt) 87*0Sstevel@tonic-gate { 88*0Sstevel@tonic-gate int value; 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate switch (prom_getproplen(node, name)) { 91*0Sstevel@tonic-gate case sizeof (int): 92*0Sstevel@tonic-gate (void) prom_getprop(node, name, (caddr_t)&value); 93*0Sstevel@tonic-gate break; 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate default: 96*0Sstevel@tonic-gate value = deflt; 97*0Sstevel@tonic-gate break; 98*0Sstevel@tonic-gate } 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate return (value); 101*0Sstevel@tonic-gate } 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate /* 104*0Sstevel@tonic-gate * Set the magic constants of the implementation. 105*0Sstevel@tonic-gate */ 106*0Sstevel@tonic-gate /*ARGSUSED*/ 107*0Sstevel@tonic-gate void 108*0Sstevel@tonic-gate cpu_fiximp(dnode_t dnode) 109*0Sstevel@tonic-gate { 110*0Sstevel@tonic-gate int i, a; 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate static struct { 113*0Sstevel@tonic-gate char *name; 114*0Sstevel@tonic-gate int *var; 115*0Sstevel@tonic-gate int defval; 116*0Sstevel@tonic-gate } prop[] = { 117*0Sstevel@tonic-gate "dcache-size", &dcache_size, CH_DCACHE_SIZE, 118*0Sstevel@tonic-gate "dcache-line-size", &dcache_linesize, CH_DCACHE_LSIZE, 119*0Sstevel@tonic-gate "icache-size", &icache_size, CH_ICACHE_SIZE, 120*0Sstevel@tonic-gate "icache-line-size", &icache_linesize, CH_ICACHE_LSIZE, 121*0Sstevel@tonic-gate "ecache-size", &ecache_size, CH_ECACHE_MAX_SIZE, 122*0Sstevel@tonic-gate "ecache-line-size", &ecache_alignsize, CH_ECACHE_MAX_LSIZE, 123*0Sstevel@tonic-gate "ecache-associativity", &ecache_associativity, CH_ECACHE_NWAY 124*0Sstevel@tonic-gate }; 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate extern int exec_lpg_disable, use_brk_lpg, use_stk_lpg, use_zmap_lpg; 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate for (i = 0; i < sizeof (prop) / sizeof (prop[0]); i++) 130*0Sstevel@tonic-gate *prop[i].var = getintprop(dnode, prop[i].name, prop[i].defval); 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate ecache_setsize = ecache_size / ecache_associativity; 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate vac_size = CH_VAC_SIZE; 135*0Sstevel@tonic-gate vac_mask = MMU_PAGEMASK & (vac_size - 1); 136*0Sstevel@tonic-gate i = 0; a = vac_size; 137*0Sstevel@tonic-gate while (a >>= 1) 138*0Sstevel@tonic-gate ++i; 139*0Sstevel@tonic-gate vac_shift = i; 140*0Sstevel@tonic-gate shm_alignment = vac_size; 141*0Sstevel@tonic-gate vac = 1; 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate /* 144*0Sstevel@tonic-gate * Cheetah's large page support has problems with large numbers of 145*0Sstevel@tonic-gate * large pages, so just disable large pages out-of-the-box. 146*0Sstevel@tonic-gate */ 147*0Sstevel@tonic-gate exec_lpg_disable = 1; 148*0Sstevel@tonic-gate use_brk_lpg = 0; 149*0Sstevel@tonic-gate use_stk_lpg = 0; 150*0Sstevel@tonic-gate use_zmap_lpg = 0; 151*0Sstevel@tonic-gate } 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate void 154*0Sstevel@tonic-gate send_mondo_set(cpuset_t set) 155*0Sstevel@tonic-gate { 156*0Sstevel@tonic-gate int lo, busy, nack, shipped = 0; 157*0Sstevel@tonic-gate uint16_t i, cpuids[IDSR_BN_SETS]; 158*0Sstevel@tonic-gate uint64_t idsr, nackmask = 0, busymask, curnack, curbusy; 159*0Sstevel@tonic-gate uint64_t starttick, endtick, tick, lasttick; 160*0Sstevel@tonic-gate #if (NCPU > IDSR_BN_SETS) 161*0Sstevel@tonic-gate int index = 0; 162*0Sstevel@tonic-gate int ncpuids = 0; 163*0Sstevel@tonic-gate #endif 164*0Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 165*0Sstevel@tonic-gate int recovered = 0; 166*0Sstevel@tonic-gate int cpuid; 167*0Sstevel@tonic-gate #endif 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate ASSERT(!CPUSET_ISNULL(set)); 170*0Sstevel@tonic-gate starttick = lasttick = gettick(); 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate #if (NCPU <= IDSR_BN_SETS) 173*0Sstevel@tonic-gate for (i = 0; i < NCPU; i++) 174*0Sstevel@tonic-gate if (CPU_IN_SET(set, i)) { 175*0Sstevel@tonic-gate shipit(i, shipped); 176*0Sstevel@tonic-gate nackmask |= IDSR_NACK_BIT(shipped); 177*0Sstevel@tonic-gate cpuids[shipped++] = i; 178*0Sstevel@tonic-gate CPUSET_DEL(set, i); 179*0Sstevel@tonic-gate if (CPUSET_ISNULL(set)) 180*0Sstevel@tonic-gate break; 181*0Sstevel@tonic-gate } 182*0Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, xcalls, shipped); 183*0Sstevel@tonic-gate #else 184*0Sstevel@tonic-gate for (i = 0; i < NCPU; i++) 185*0Sstevel@tonic-gate if (CPU_IN_SET(set, i)) { 186*0Sstevel@tonic-gate ncpuids++; 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate /* 189*0Sstevel@tonic-gate * Ship only to the first (IDSR_BN_SETS) CPUs. If we 190*0Sstevel@tonic-gate * find we have shipped to more than (IDSR_BN_SETS) 191*0Sstevel@tonic-gate * CPUs, set "index" to the highest numbered CPU in 192*0Sstevel@tonic-gate * the set so we can ship to other CPUs a bit later on. 193*0Sstevel@tonic-gate */ 194*0Sstevel@tonic-gate if (shipped < IDSR_BN_SETS) { 195*0Sstevel@tonic-gate shipit(i, shipped); 196*0Sstevel@tonic-gate nackmask |= IDSR_NACK_BIT(shipped); 197*0Sstevel@tonic-gate cpuids[shipped++] = i; 198*0Sstevel@tonic-gate CPUSET_DEL(set, i); 199*0Sstevel@tonic-gate if (CPUSET_ISNULL(set)) 200*0Sstevel@tonic-gate break; 201*0Sstevel@tonic-gate } else 202*0Sstevel@tonic-gate index = (int)i; 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate 205*0Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, xcalls, ncpuids); 206*0Sstevel@tonic-gate #endif 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate busymask = IDSR_NACK_TO_BUSY(nackmask); 209*0Sstevel@tonic-gate busy = nack = 0; 210*0Sstevel@tonic-gate endtick = starttick + xc_tick_limit; 211*0Sstevel@tonic-gate for (;;) { 212*0Sstevel@tonic-gate idsr = getidsr(); 213*0Sstevel@tonic-gate #if (NCPU <= IDSR_BN_SETS) 214*0Sstevel@tonic-gate if (idsr == 0) 215*0Sstevel@tonic-gate break; 216*0Sstevel@tonic-gate #else 217*0Sstevel@tonic-gate if (idsr == 0 && shipped == ncpuids) 218*0Sstevel@tonic-gate break; 219*0Sstevel@tonic-gate #endif 220*0Sstevel@tonic-gate tick = gettick(); 221*0Sstevel@tonic-gate /* 222*0Sstevel@tonic-gate * If there is a big jump between the current tick 223*0Sstevel@tonic-gate * count and lasttick, we have probably hit a break 224*0Sstevel@tonic-gate * point. Adjust endtick accordingly to avoid panic. 225*0Sstevel@tonic-gate */ 226*0Sstevel@tonic-gate if (tick > (lasttick + xc_tick_jump_limit)) 227*0Sstevel@tonic-gate endtick += (tick - lasttick); 228*0Sstevel@tonic-gate lasttick = tick; 229*0Sstevel@tonic-gate if (tick > endtick) { 230*0Sstevel@tonic-gate if (panic_quiesce) 231*0Sstevel@tonic-gate return; 232*0Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 233*0Sstevel@tonic-gate cpuid = -1; 234*0Sstevel@tonic-gate for (i = 0; i < IDSR_BN_SETS; i++) { 235*0Sstevel@tonic-gate if (idsr & (IDSR_NACK_BIT(i) | 236*0Sstevel@tonic-gate IDSR_BUSY_BIT(i))) { 237*0Sstevel@tonic-gate cpuid = cpuids[i]; 238*0Sstevel@tonic-gate break; 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate } 241*0Sstevel@tonic-gate if (cheetah_sendmondo_recover && cpuid != -1 && 242*0Sstevel@tonic-gate recovered == 0) { 243*0Sstevel@tonic-gate if (mondo_recover(cpuid, i)) { 244*0Sstevel@tonic-gate /* 245*0Sstevel@tonic-gate * We claimed the whole memory or 246*0Sstevel@tonic-gate * full scan is disabled. 247*0Sstevel@tonic-gate */ 248*0Sstevel@tonic-gate recovered++; 249*0Sstevel@tonic-gate } 250*0Sstevel@tonic-gate tick = gettick(); 251*0Sstevel@tonic-gate endtick = tick + xc_tick_limit; 252*0Sstevel@tonic-gate lasttick = tick; 253*0Sstevel@tonic-gate /* 254*0Sstevel@tonic-gate * Recheck idsr 255*0Sstevel@tonic-gate */ 256*0Sstevel@tonic-gate continue; 257*0Sstevel@tonic-gate } else 258*0Sstevel@tonic-gate #endif /* CHEETAHPLUS_ERRATUM_25 */ 259*0Sstevel@tonic-gate { 260*0Sstevel@tonic-gate cmn_err(CE_CONT, "send mondo timeout " 261*0Sstevel@tonic-gate "[%d NACK %d BUSY]\nIDSR 0x%" 262*0Sstevel@tonic-gate "" PRIx64 " cpuids:", nack, busy, idsr); 263*0Sstevel@tonic-gate for (i = 0; i < IDSR_BN_SETS; i++) { 264*0Sstevel@tonic-gate if (idsr & (IDSR_NACK_BIT(i) | 265*0Sstevel@tonic-gate IDSR_BUSY_BIT(i))) { 266*0Sstevel@tonic-gate cmn_err(CE_CONT, " 0x%x", 267*0Sstevel@tonic-gate cpuids[i]); 268*0Sstevel@tonic-gate } 269*0Sstevel@tonic-gate } 270*0Sstevel@tonic-gate cmn_err(CE_CONT, "\n"); 271*0Sstevel@tonic-gate cmn_err(CE_PANIC, "send_mondo_set: timeout"); 272*0Sstevel@tonic-gate } 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate curnack = idsr & nackmask; 275*0Sstevel@tonic-gate curbusy = idsr & busymask; 276*0Sstevel@tonic-gate #if (NCPU > IDSR_BN_SETS) 277*0Sstevel@tonic-gate if (shipped < ncpuids) { 278*0Sstevel@tonic-gate uint64_t cpus_left; 279*0Sstevel@tonic-gate uint16_t next = (uint16_t)index; 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate cpus_left = ~(IDSR_NACK_TO_BUSY(curnack) | curbusy) & 282*0Sstevel@tonic-gate busymask; 283*0Sstevel@tonic-gate 284*0Sstevel@tonic-gate if (cpus_left) { 285*0Sstevel@tonic-gate do { 286*0Sstevel@tonic-gate /* 287*0Sstevel@tonic-gate * Sequence through and ship to the 288*0Sstevel@tonic-gate * remainder of the CPUs in the system 289*0Sstevel@tonic-gate * (e.g. other than the first 290*0Sstevel@tonic-gate * (IDSR_BN_SETS)) in reverse order. 291*0Sstevel@tonic-gate */ 292*0Sstevel@tonic-gate lo = lowbit(cpus_left) - 1; 293*0Sstevel@tonic-gate i = IDSR_BUSY_IDX(lo); 294*0Sstevel@tonic-gate shipit(next, i); 295*0Sstevel@tonic-gate shipped++; 296*0Sstevel@tonic-gate cpuids[i] = next; 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate /* 299*0Sstevel@tonic-gate * If we've processed all the CPUs, 300*0Sstevel@tonic-gate * exit the loop now and save 301*0Sstevel@tonic-gate * instructions. 302*0Sstevel@tonic-gate */ 303*0Sstevel@tonic-gate if (shipped == ncpuids) 304*0Sstevel@tonic-gate break; 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate for ((index = ((int)next - 1)); 307*0Sstevel@tonic-gate index >= 0; index--) 308*0Sstevel@tonic-gate if (CPU_IN_SET(set, index)) { 309*0Sstevel@tonic-gate next = (uint16_t)index; 310*0Sstevel@tonic-gate break; 311*0Sstevel@tonic-gate } 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate cpus_left &= ~(1ull << lo); 314*0Sstevel@tonic-gate } while (cpus_left); 315*0Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 316*0Sstevel@tonic-gate /* 317*0Sstevel@tonic-gate * Clear recovered because we are sending to 318*0Sstevel@tonic-gate * a new set of targets. 319*0Sstevel@tonic-gate */ 320*0Sstevel@tonic-gate recovered = 0; 321*0Sstevel@tonic-gate #endif 322*0Sstevel@tonic-gate continue; 323*0Sstevel@tonic-gate } 324*0Sstevel@tonic-gate } 325*0Sstevel@tonic-gate #endif 326*0Sstevel@tonic-gate if (curbusy) { 327*0Sstevel@tonic-gate busy++; 328*0Sstevel@tonic-gate continue; 329*0Sstevel@tonic-gate } 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate #ifdef SEND_MONDO_STATS 332*0Sstevel@tonic-gate { 333*0Sstevel@tonic-gate int n = gettick() - starttick; 334*0Sstevel@tonic-gate if (n < 8192) 335*0Sstevel@tonic-gate x_nack_stimes[n >> 7]++; 336*0Sstevel@tonic-gate } 337*0Sstevel@tonic-gate #endif 338*0Sstevel@tonic-gate while (gettick() < (tick + sys_clock_mhz)) 339*0Sstevel@tonic-gate ; 340*0Sstevel@tonic-gate do { 341*0Sstevel@tonic-gate lo = lowbit(curnack) - 1; 342*0Sstevel@tonic-gate i = IDSR_NACK_IDX(lo); 343*0Sstevel@tonic-gate shipit(cpuids[i], i); 344*0Sstevel@tonic-gate curnack &= ~(1ull << lo); 345*0Sstevel@tonic-gate } while (curnack); 346*0Sstevel@tonic-gate nack++; 347*0Sstevel@tonic-gate busy = 0; 348*0Sstevel@tonic-gate } 349*0Sstevel@tonic-gate #ifdef SEND_MONDO_STATS 350*0Sstevel@tonic-gate { 351*0Sstevel@tonic-gate int n = gettick() - starttick; 352*0Sstevel@tonic-gate if (n < 8192) 353*0Sstevel@tonic-gate x_set_stimes[n >> 7]++; 354*0Sstevel@tonic-gate else 355*0Sstevel@tonic-gate x_set_ltimes[(n >> 13) & 0xf]++; 356*0Sstevel@tonic-gate } 357*0Sstevel@tonic-gate x_set_cpus[shipped]++; 358*0Sstevel@tonic-gate #endif 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate /* 362*0Sstevel@tonic-gate * Handles error logging for implementation specific error types. 363*0Sstevel@tonic-gate */ 364*0Sstevel@tonic-gate /*ARGSUSED*/ 365*0Sstevel@tonic-gate int 366*0Sstevel@tonic-gate cpu_impl_async_log_err(void *flt, errorq_elem_t *eqep) 367*0Sstevel@tonic-gate { 368*0Sstevel@tonic-gate /* There aren't any error types which are specific to cheetah only */ 369*0Sstevel@tonic-gate return (CH_ASYNC_LOG_UNKNOWN); 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate /* 373*0Sstevel@tonic-gate * Figure out if Ecache is direct-mapped (Cheetah or Cheetah+ with Ecache 374*0Sstevel@tonic-gate * control ECCR_ASSOC bit off or 2-way (Cheetah+ with ECCR_ASSOC on). 375*0Sstevel@tonic-gate * We need to do this on the fly because we may have mixed Cheetah+'s with 376*0Sstevel@tonic-gate * both direct and 2-way Ecaches. 377*0Sstevel@tonic-gate */ 378*0Sstevel@tonic-gate int 379*0Sstevel@tonic-gate cpu_ecache_nway(void) 380*0Sstevel@tonic-gate { 381*0Sstevel@tonic-gate return (CH_ECACHE_NWAY); 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate /* 385*0Sstevel@tonic-gate * Note that these are entered into the table: Fatal Errors (PERR, IERR, 386*0Sstevel@tonic-gate * ISAP, EMU) first, orphaned UCU/UCC, AFAR Overwrite policy, finally IVU, IVC. 387*0Sstevel@tonic-gate * Afar overwrite policy is: 388*0Sstevel@tonic-gate * UCU,UCC > UE,EDU,WDU,CPU > CE,EDC,EMC,WDC,CPC > TO,BERR 389*0Sstevel@tonic-gate */ 390*0Sstevel@tonic-gate ecc_type_to_info_t ecc_type_to_info[] = { 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate /* Fatal Errors */ 393*0Sstevel@tonic-gate C_AFSR_PERR, "PERR ", ECC_ALL_TRAPS, CPU_FATAL, 394*0Sstevel@tonic-gate "PERR Fatal", 395*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM2, 396*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_PERR, 397*0Sstevel@tonic-gate C_AFSR_IERR, "IERR ", ECC_ALL_TRAPS, CPU_FATAL, 398*0Sstevel@tonic-gate "IERR Fatal", 399*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM2, 400*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IERR, 401*0Sstevel@tonic-gate C_AFSR_ISAP, "ISAP ", ECC_ALL_TRAPS, CPU_FATAL, 402*0Sstevel@tonic-gate "ISAP Fatal", 403*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 404*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_ISAP, 405*0Sstevel@tonic-gate C_AFSR_EMU, "EMU ", ECC_ASYNC_TRAPS, CPU_FATAL, 406*0Sstevel@tonic-gate "EMU Fatal", 407*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 408*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EMU, 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate /* Orphaned UCC/UCU Errors */ 411*0Sstevel@tonic-gate C_AFSR_UCU, "OUCU ", ECC_ORPH_TRAPS, CPU_ORPH, 412*0Sstevel@tonic-gate "Orphaned UCU", 413*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 414*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCU, 415*0Sstevel@tonic-gate C_AFSR_UCC, "OUCC ", ECC_ORPH_TRAPS, CPU_ORPH, 416*0Sstevel@tonic-gate "Orphaned UCC", 417*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 418*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCC, 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate /* UCU, UCC */ 421*0Sstevel@tonic-gate C_AFSR_UCU, "UCU ", ECC_F_TRAP, CPU_UE_ECACHE, 422*0Sstevel@tonic-gate "UCU", 423*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 424*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCU, 425*0Sstevel@tonic-gate C_AFSR_UCC, "UCC ", ECC_F_TRAP, CPU_CE_ECACHE, 426*0Sstevel@tonic-gate "UCC", 427*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 428*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCC, 429*0Sstevel@tonic-gate 430*0Sstevel@tonic-gate /* UE, EDU:ST, EDU:BLD, WDU, CPU */ 431*0Sstevel@tonic-gate C_AFSR_UE, "UE ", ECC_ASYNC_TRAPS, CPU_UE, 432*0Sstevel@tonic-gate "Uncorrectable system bus (UE)", 433*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 434*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UE, 435*0Sstevel@tonic-gate C_AFSR_EDU, "EDU ", ECC_C_TRAP, CPU_UE_ECACHE_RETIRE, 436*0Sstevel@tonic-gate "EDU:ST", 437*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 438*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EDUST, 439*0Sstevel@tonic-gate C_AFSR_EDU, "EDU ", ECC_D_TRAP, CPU_UE_ECACHE_RETIRE, 440*0Sstevel@tonic-gate "EDU:BLD", 441*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 442*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EDUBL, 443*0Sstevel@tonic-gate C_AFSR_WDU, "WDU ", ECC_C_TRAP, CPU_UE_ECACHE_RETIRE, 444*0Sstevel@tonic-gate "WDU", 445*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 446*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_WDU, 447*0Sstevel@tonic-gate C_AFSR_CPU, "CPU ", ECC_C_TRAP, CPU_UE_ECACHE, 448*0Sstevel@tonic-gate "CPU", 449*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 450*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_CPU, 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gate /* CE, EDC, EMC, WDC, CPC */ 453*0Sstevel@tonic-gate C_AFSR_CE, "CE ", ECC_C_TRAP, CPU_CE, 454*0Sstevel@tonic-gate "Corrected system bus (CE)", 455*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 456*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_CE, 457*0Sstevel@tonic-gate C_AFSR_EDC, "EDC ", ECC_C_TRAP, CPU_CE_ECACHE, 458*0Sstevel@tonic-gate "EDC", 459*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 460*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EDC, 461*0Sstevel@tonic-gate C_AFSR_EMC, "EMC ", ECC_C_TRAP, CPU_EMC, 462*0Sstevel@tonic-gate "EMC", 463*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 464*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EMC, 465*0Sstevel@tonic-gate C_AFSR_WDC, "WDC ", ECC_C_TRAP, CPU_CE_ECACHE, 466*0Sstevel@tonic-gate "WDC", 467*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 468*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_WDC, 469*0Sstevel@tonic-gate C_AFSR_CPC, "CPC ", ECC_C_TRAP, CPU_CE_ECACHE, 470*0Sstevel@tonic-gate "CPC", 471*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 472*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_CPC, 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate /* TO, BERR */ 475*0Sstevel@tonic-gate C_AFSR_TO, "TO ", ECC_ASYNC_TRAPS, CPU_TO, 476*0Sstevel@tonic-gate "Timeout (TO)", 477*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_IO, 478*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_TO, 479*0Sstevel@tonic-gate C_AFSR_BERR, "BERR ", ECC_ASYNC_TRAPS, CPU_BERR, 480*0Sstevel@tonic-gate "Bus Error (BERR)", 481*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_IO, 482*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_BERR, 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gate /* IVU, IVC */ 485*0Sstevel@tonic-gate C_AFSR_IVU, "IVU ", ECC_C_TRAP, CPU_IV, 486*0Sstevel@tonic-gate "IVU", 487*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 488*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IVU, 489*0Sstevel@tonic-gate C_AFSR_IVC, "IVC ", ECC_C_TRAP, CPU_IV, 490*0Sstevel@tonic-gate "IVC", 491*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 492*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IVC, 493*0Sstevel@tonic-gate 494*0Sstevel@tonic-gate 0, NULL, 0, 0, 495*0Sstevel@tonic-gate NULL, 496*0Sstevel@tonic-gate FM_EREPORT_PAYLOAD_UNKNOWN, 497*0Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UNKNOWN, 498*0Sstevel@tonic-gate }; 499*0Sstevel@tonic-gate 500*0Sstevel@tonic-gate /* 501*0Sstevel@tonic-gate * Prioritized list of Error bits for AFAR overwrite. 502*0Sstevel@tonic-gate * See Cheetah PRM P.6.1 503*0Sstevel@tonic-gate * Class 4: UCC, UCU 504*0Sstevel@tonic-gate * Class 3: UE, EDU, EMU, WDU, CPU 505*0Sstevel@tonic-gate * Class 2: CE, EDC, EMC, WDC, CPC 506*0Sstevel@tonic-gate * Class 1: TO, BERR 507*0Sstevel@tonic-gate */ 508*0Sstevel@tonic-gate uint64_t afar_overwrite[] = { 509*0Sstevel@tonic-gate C_AFSR_UCC | C_AFSR_UCU, 510*0Sstevel@tonic-gate C_AFSR_UE | C_AFSR_EDU | C_AFSR_EMU | C_AFSR_WDU | C_AFSR_CPU, 511*0Sstevel@tonic-gate C_AFSR_CE | C_AFSR_EDC | C_AFSR_EMC | C_AFSR_WDC | C_AFSR_CPC, 512*0Sstevel@tonic-gate C_AFSR_TO | C_AFSR_BERR, 513*0Sstevel@tonic-gate 0 514*0Sstevel@tonic-gate }; 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gate /* 517*0Sstevel@tonic-gate * Prioritized list of Error bits for ESYND overwrite. 518*0Sstevel@tonic-gate * See Cheetah PRM P.6.2 519*0Sstevel@tonic-gate * Class 2: UE, IVU, EDU, WDU, UCU, CPU 520*0Sstevel@tonic-gate * Class 1: CE, IVC, EDC, WDC, UCC, CPC 521*0Sstevel@tonic-gate */ 522*0Sstevel@tonic-gate uint64_t esynd_overwrite[] = { 523*0Sstevel@tonic-gate C_AFSR_UE | C_AFSR_IVU | C_AFSR_EDU | C_AFSR_WDU | C_AFSR_UCU | 524*0Sstevel@tonic-gate C_AFSR_CPU, 525*0Sstevel@tonic-gate C_AFSR_CE | C_AFSR_IVC | C_AFSR_EDC | C_AFSR_WDC | C_AFSR_UCC | 526*0Sstevel@tonic-gate C_AFSR_CPC, 527*0Sstevel@tonic-gate 0 528*0Sstevel@tonic-gate }; 529*0Sstevel@tonic-gate 530*0Sstevel@tonic-gate /* 531*0Sstevel@tonic-gate * Prioritized list of Error bits for MSYND overwrite. 532*0Sstevel@tonic-gate * See Cheetah PRM P.6.3 533*0Sstevel@tonic-gate * Class 2: EMU 534*0Sstevel@tonic-gate * Class 1: EMC 535*0Sstevel@tonic-gate */ 536*0Sstevel@tonic-gate uint64_t msynd_overwrite[] = { 537*0Sstevel@tonic-gate C_AFSR_EMU, 538*0Sstevel@tonic-gate C_AFSR_EMC, 539*0Sstevel@tonic-gate 0 540*0Sstevel@tonic-gate }; 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate /* 543*0Sstevel@tonic-gate * change cpu speed bits -- new speed will be normal-speed/divisor. 544*0Sstevel@tonic-gate * 545*0Sstevel@tonic-gate * The Jalapeno memory controllers are required to drain outstanding 546*0Sstevel@tonic-gate * memory transactions within 32 JBus clocks in order to be ready 547*0Sstevel@tonic-gate * to enter Estar mode. In some corner cases however, that time 548*0Sstevel@tonic-gate * fell short. 549*0Sstevel@tonic-gate * 550*0Sstevel@tonic-gate * A safe software solution is to force MCU to act like in Estar mode, 551*0Sstevel@tonic-gate * then delay 1us (in ppm code) prior to assert J_CHNG_L signal. 552*0Sstevel@tonic-gate * To reverse the effect, upon exiting Estar, software restores the 553*0Sstevel@tonic-gate * MCU to its original state. 554*0Sstevel@tonic-gate */ 555*0Sstevel@tonic-gate /* ARGSUSED1 */ 556*0Sstevel@tonic-gate void 557*0Sstevel@tonic-gate cpu_change_speed(uint64_t divisor, uint64_t arg2) 558*0Sstevel@tonic-gate { 559*0Sstevel@tonic-gate bus_config_eclk_t *bceclk; 560*0Sstevel@tonic-gate uint64_t reg; 561*0Sstevel@tonic-gate 562*0Sstevel@tonic-gate for (bceclk = bus_config_eclk; bceclk->divisor; bceclk++) { 563*0Sstevel@tonic-gate if (bceclk->divisor != divisor) 564*0Sstevel@tonic-gate continue; 565*0Sstevel@tonic-gate reg = get_safari_config(); 566*0Sstevel@tonic-gate reg &= ~SAFARI_CONFIG_ECLK_MASK; 567*0Sstevel@tonic-gate reg |= bceclk->mask; 568*0Sstevel@tonic-gate set_safari_config(reg); 569*0Sstevel@tonic-gate CPU->cpu_m.divisor = (uchar_t)divisor; 570*0Sstevel@tonic-gate return; 571*0Sstevel@tonic-gate } 572*0Sstevel@tonic-gate /* 573*0Sstevel@tonic-gate * We will reach here only if OBP and kernel don't agree on 574*0Sstevel@tonic-gate * the speeds supported by the CPU. 575*0Sstevel@tonic-gate */ 576*0Sstevel@tonic-gate cmn_err(CE_WARN, "cpu_change_speed: bad divisor %" PRIu64, divisor); 577*0Sstevel@tonic-gate } 578*0Sstevel@tonic-gate 579*0Sstevel@tonic-gate /* 580*0Sstevel@tonic-gate * Cpu private initialization. This includes allocating the cpu_private 581*0Sstevel@tonic-gate * data structure, initializing it, and initializing the scrubber for this 582*0Sstevel@tonic-gate * cpu. This function calls cpu_init_ecache_scrub_dr to init the scrubber. 583*0Sstevel@tonic-gate * We use kmem_cache_create for the cheetah private data structure because 584*0Sstevel@tonic-gate * it needs to be allocated on a PAGESIZE (8192) byte boundary. 585*0Sstevel@tonic-gate */ 586*0Sstevel@tonic-gate void 587*0Sstevel@tonic-gate cpu_init_private(struct cpu *cp) 588*0Sstevel@tonic-gate { 589*0Sstevel@tonic-gate cheetah_private_t *chprp; 590*0Sstevel@tonic-gate int i; 591*0Sstevel@tonic-gate 592*0Sstevel@tonic-gate ASSERT(CPU_PRIVATE(cp) == NULL); 593*0Sstevel@tonic-gate 594*0Sstevel@tonic-gate /* LINTED: E_TRUE_LOGICAL_EXPR */ 595*0Sstevel@tonic-gate ASSERT((offsetof(cheetah_private_t, chpr_tl1_err_data) + 596*0Sstevel@tonic-gate sizeof (ch_err_tl1_data_t) * CH_ERR_TL1_TLMAX) <= PAGESIZE); 597*0Sstevel@tonic-gate 598*0Sstevel@tonic-gate /* 599*0Sstevel@tonic-gate * Running with a Cheetah+, Jaguar, or Panther on a Cheetah CPU 600*0Sstevel@tonic-gate * machine is not a supported configuration. Attempting to do so 601*0Sstevel@tonic-gate * may result in unpredictable failures (e.g. running Cheetah+ 602*0Sstevel@tonic-gate * CPUs with Cheetah E$ disp flush) so don't allow it. 603*0Sstevel@tonic-gate * 604*0Sstevel@tonic-gate * This is just defensive code since this configuration mismatch 605*0Sstevel@tonic-gate * should have been caught prior to OS execution. 606*0Sstevel@tonic-gate */ 607*0Sstevel@tonic-gate if (!IS_CHEETAH(cpunodes[cp->cpu_id].implementation)) { 608*0Sstevel@tonic-gate cmn_err(CE_PANIC, "CPU%d: UltraSPARC-III+/IV/IV+ not" 609*0Sstevel@tonic-gate " supported on UltraSPARC-III code\n", cp->cpu_id); 610*0Sstevel@tonic-gate } 611*0Sstevel@tonic-gate 612*0Sstevel@tonic-gate /* 613*0Sstevel@tonic-gate * If the ch_private_cache has not been created, create it. 614*0Sstevel@tonic-gate */ 615*0Sstevel@tonic-gate if (ch_private_cache == NULL) { 616*0Sstevel@tonic-gate ch_private_cache = kmem_cache_create("ch_private_cache", 617*0Sstevel@tonic-gate sizeof (cheetah_private_t), PAGESIZE, NULL, NULL, 618*0Sstevel@tonic-gate NULL, NULL, static_arena, 0); 619*0Sstevel@tonic-gate } 620*0Sstevel@tonic-gate 621*0Sstevel@tonic-gate chprp = CPU_PRIVATE(cp) = kmem_cache_alloc(ch_private_cache, KM_SLEEP); 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gate bzero(chprp, sizeof (cheetah_private_t)); 624*0Sstevel@tonic-gate chprp->chpr_fecctl0_logout.clo_data.chd_afar = LOGOUT_INVALID; 625*0Sstevel@tonic-gate chprp->chpr_cecc_logout.clo_data.chd_afar = LOGOUT_INVALID; 626*0Sstevel@tonic-gate chprp->chpr_async_logout.clo_data.chd_afar = LOGOUT_INVALID; 627*0Sstevel@tonic-gate for (i = 0; i < CH_ERR_TL1_TLMAX; i++) 628*0Sstevel@tonic-gate chprp->chpr_tl1_err_data[i].ch_err_tl1_logout.clo_data.chd_afar 629*0Sstevel@tonic-gate = LOGOUT_INVALID; 630*0Sstevel@tonic-gate 631*0Sstevel@tonic-gate chprp->chpr_icache_size = CH_ICACHE_SIZE; 632*0Sstevel@tonic-gate chprp->chpr_icache_linesize = CH_ICACHE_LSIZE; 633*0Sstevel@tonic-gate 634*0Sstevel@tonic-gate cpu_init_ecache_scrub_dr(cp); 635*0Sstevel@tonic-gate 636*0Sstevel@tonic-gate chprp->chpr_ec_set_size = cpunodes[cp->cpu_id].ecache_size / 637*0Sstevel@tonic-gate cpu_ecache_nway(); 638*0Sstevel@tonic-gate 639*0Sstevel@tonic-gate adjust_hw_copy_limits(cpunodes[cp->cpu_id].ecache_size); 640*0Sstevel@tonic-gate ch_err_tl1_paddrs[cp->cpu_id] = va_to_pa(chprp); 641*0Sstevel@tonic-gate ASSERT(ch_err_tl1_paddrs[cp->cpu_id] != -1); 642*0Sstevel@tonic-gate } 643*0Sstevel@tonic-gate 644*0Sstevel@tonic-gate /* 645*0Sstevel@tonic-gate * Clear the error state registers for this CPU. 646*0Sstevel@tonic-gate * For Cheetah, just clear the AFSR 647*0Sstevel@tonic-gate */ 648*0Sstevel@tonic-gate void 649*0Sstevel@tonic-gate set_cpu_error_state(ch_cpu_errors_t *cpu_error_regs) 650*0Sstevel@tonic-gate { 651*0Sstevel@tonic-gate set_asyncflt(cpu_error_regs->afsr & ~C_AFSR_FATAL_ERRS); 652*0Sstevel@tonic-gate } 653*0Sstevel@tonic-gate 654*0Sstevel@tonic-gate /* 655*0Sstevel@tonic-gate * For Cheetah, the error recovery code uses an alternate flush area in the 656*0Sstevel@tonic-gate * TL>0 fast ECC handler. ecache_tl1_flushaddr is the physical address of 657*0Sstevel@tonic-gate * this exclusive displacement flush area. 658*0Sstevel@tonic-gate */ 659*0Sstevel@tonic-gate uint64_t ecache_tl1_flushaddr = (uint64_t)-1; /* physaddr for E$ flushing */ 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gate /* 662*0Sstevel@tonic-gate * Allocate and initialize the exclusive displacement flush area. 663*0Sstevel@tonic-gate * Must be called before startup_bop_gone(). 664*0Sstevel@tonic-gate */ 665*0Sstevel@tonic-gate caddr_t 666*0Sstevel@tonic-gate ecache_init_scrub_flush_area(caddr_t alloc_base) 667*0Sstevel@tonic-gate { 668*0Sstevel@tonic-gate unsigned size = 2 * CH_ECACHE_8M_SIZE; 669*0Sstevel@tonic-gate caddr_t tmp_alloc_base = alloc_base; 670*0Sstevel@tonic-gate caddr_t flush_alloc_base = 671*0Sstevel@tonic-gate (caddr_t)roundup((uintptr_t)alloc_base, size); 672*0Sstevel@tonic-gate caddr_t ecache_tl1_virtaddr; 673*0Sstevel@tonic-gate 674*0Sstevel@tonic-gate /* 675*0Sstevel@tonic-gate * Allocate the physical memory for the exclusive flush area 676*0Sstevel@tonic-gate * 677*0Sstevel@tonic-gate * Need to allocate an exclusive flush area that is twice the 678*0Sstevel@tonic-gate * largest supported E$ size, physically contiguous, and 679*0Sstevel@tonic-gate * aligned on twice the largest E$ size boundary. 680*0Sstevel@tonic-gate * 681*0Sstevel@tonic-gate * Memory allocated via BOP_ALLOC is included in the "cage" 682*0Sstevel@tonic-gate * from the DR perspective and due to this, its physical 683*0Sstevel@tonic-gate * address will never change and the memory will not be 684*0Sstevel@tonic-gate * removed. 685*0Sstevel@tonic-gate * 686*0Sstevel@tonic-gate * BOP_ALLOC takes 4 arguments: bootops, virtual address hint, 687*0Sstevel@tonic-gate * size of the area to allocate, and alignment of the area to 688*0Sstevel@tonic-gate * allocate. It returns zero if the allocation fails, or the 689*0Sstevel@tonic-gate * virtual address for a successful allocation. Memory BOP_ALLOC'd 690*0Sstevel@tonic-gate * is physically contiguous. 691*0Sstevel@tonic-gate */ 692*0Sstevel@tonic-gate if ((ecache_tl1_virtaddr = (caddr_t)BOP_ALLOC(bootops, 693*0Sstevel@tonic-gate flush_alloc_base, size, size)) != NULL) { 694*0Sstevel@tonic-gate 695*0Sstevel@tonic-gate tmp_alloc_base = 696*0Sstevel@tonic-gate (caddr_t)roundup((uintptr_t)(ecache_tl1_virtaddr + size), 697*0Sstevel@tonic-gate ecache_alignsize); 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate /* 700*0Sstevel@tonic-gate * get the physical address of the exclusive flush area 701*0Sstevel@tonic-gate */ 702*0Sstevel@tonic-gate ecache_tl1_flushaddr = va_to_pa(ecache_tl1_virtaddr); 703*0Sstevel@tonic-gate 704*0Sstevel@tonic-gate } else { 705*0Sstevel@tonic-gate ecache_tl1_virtaddr = (caddr_t)-1; 706*0Sstevel@tonic-gate cmn_err(CE_NOTE, "!ecache_init_scrub_flush_area failed\n"); 707*0Sstevel@tonic-gate } 708*0Sstevel@tonic-gate 709*0Sstevel@tonic-gate return (tmp_alloc_base); 710*0Sstevel@tonic-gate } 711*0Sstevel@tonic-gate 712*0Sstevel@tonic-gate /* 713*0Sstevel@tonic-gate * Update cpu_offline_set so the scrubber knows which cpus are offline 714*0Sstevel@tonic-gate */ 715*0Sstevel@tonic-gate /*ARGSUSED*/ 716*0Sstevel@tonic-gate int 717*0Sstevel@tonic-gate cpu_scrub_cpu_setup(cpu_setup_t what, int cpuid, void *arg) 718*0Sstevel@tonic-gate { 719*0Sstevel@tonic-gate switch (what) { 720*0Sstevel@tonic-gate case CPU_ON: 721*0Sstevel@tonic-gate case CPU_INIT: 722*0Sstevel@tonic-gate CPUSET_DEL(cpu_offline_set, cpuid); 723*0Sstevel@tonic-gate break; 724*0Sstevel@tonic-gate case CPU_OFF: 725*0Sstevel@tonic-gate CPUSET_ADD(cpu_offline_set, cpuid); 726*0Sstevel@tonic-gate break; 727*0Sstevel@tonic-gate default: 728*0Sstevel@tonic-gate break; 729*0Sstevel@tonic-gate } 730*0Sstevel@tonic-gate return (0); 731*0Sstevel@tonic-gate } 732