17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 507b65a64Saguzovsk * Common Development and Distribution License (the "License"). 607b65a64Saguzovsk * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22b9e93c10SJonathan Haslam * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/types.h> 277c478bd9Sstevel@tonic-gate #include <sys/systm.h> 287c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 297c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 307c478bd9Sstevel@tonic-gate #include <sys/archsystm.h> 317c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h> 327c478bd9Sstevel@tonic-gate #include <sys/machparam.h> 337c478bd9Sstevel@tonic-gate #include <sys/machsystm.h> 347c478bd9Sstevel@tonic-gate #include <sys/machthread.h> 357c478bd9Sstevel@tonic-gate #include <sys/cpu.h> 367c478bd9Sstevel@tonic-gate #include <sys/cmp.h> 377c478bd9Sstevel@tonic-gate #include <sys/elf_SPARC.h> 387c478bd9Sstevel@tonic-gate #include <vm/hat_sfmmu.h> 397c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 407c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 417c478bd9Sstevel@tonic-gate #include <sys/cheetahregs.h> 427c478bd9Sstevel@tonic-gate #include <sys/us3_module.h> 437c478bd9Sstevel@tonic-gate #include <sys/async.h> 447c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 457c478bd9Sstevel@tonic-gate #include <sys/debug.h> 467c478bd9Sstevel@tonic-gate #include <sys/dditypes.h> 477c478bd9Sstevel@tonic-gate #include <sys/prom_debug.h> 487c478bd9Sstevel@tonic-gate #include <sys/prom_plat.h> 497c478bd9Sstevel@tonic-gate #include <sys/cpu_module.h> 507c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 517c478bd9Sstevel@tonic-gate #include <sys/intreg.h> 527c478bd9Sstevel@tonic-gate #include <sys/clock.h> 537c478bd9Sstevel@tonic-gate #include <sys/platform_module.h> 547c478bd9Sstevel@tonic-gate #include <sys/machtrap.h> 557c478bd9Sstevel@tonic-gate #include <sys/ontrap.h> 567c478bd9Sstevel@tonic-gate #include <sys/panic.h> 577c478bd9Sstevel@tonic-gate #include <sys/memlist.h> 587c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 597c478bd9Sstevel@tonic-gate #include <sys/ivintr.h> 607c478bd9Sstevel@tonic-gate #include <sys/atomic.h> 617c478bd9Sstevel@tonic-gate #include <sys/fm/protocol.h> 627c478bd9Sstevel@tonic-gate #include <sys/fm/cpu/UltraSPARC-III.h> 637c478bd9Sstevel@tonic-gate #include <vm/vm_dep.h> 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 667c478bd9Sstevel@tonic-gate #include <sys/cyclic.h> 677c478bd9Sstevel@tonic-gate #endif /* CHEETAHPLUS_ERRATUM_25 */ 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate /* 70ec25b48fSsusans * Note that 'Cheetah PRM' refers to: 71ec25b48fSsusans * SPARC V9 JPS1 Implementation Supplement: Sun UltraSPARC-III 72ec25b48fSsusans */ 73ec25b48fSsusans 74ec25b48fSsusans /* 757c478bd9Sstevel@tonic-gate * Setup trap handlers. 767c478bd9Sstevel@tonic-gate */ 777c478bd9Sstevel@tonic-gate void 787c478bd9Sstevel@tonic-gate cpu_init_trap(void) 797c478bd9Sstevel@tonic-gate { 80b9e93c10SJonathan Haslam CH_SET_TRAP(pil15_epilogue, ch_pil15_interrupt_instr); 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate CH_SET_TRAP(tt0_fecc, fecc_err_instr); 837c478bd9Sstevel@tonic-gate CH_SET_TRAP(tt1_fecc, fecc_err_tl1_instr); 847c478bd9Sstevel@tonic-gate CH_SET_TRAP(tt1_swtrap0, fecc_err_tl1_cont_instr); 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate static int 88fa9e4066Sahrens getintprop(pnode_t node, char *name, int deflt) 897c478bd9Sstevel@tonic-gate { 907c478bd9Sstevel@tonic-gate int value; 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate switch (prom_getproplen(node, name)) { 937c478bd9Sstevel@tonic-gate case sizeof (int): 947c478bd9Sstevel@tonic-gate (void) prom_getprop(node, name, (caddr_t)&value); 957c478bd9Sstevel@tonic-gate break; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate default: 987c478bd9Sstevel@tonic-gate value = deflt; 997c478bd9Sstevel@tonic-gate break; 1007c478bd9Sstevel@tonic-gate } 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate return (value); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * Set the magic constants of the implementation. 1077c478bd9Sstevel@tonic-gate */ 1087c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1097c478bd9Sstevel@tonic-gate void 110fa9e4066Sahrens cpu_fiximp(pnode_t dnode) 1117c478bd9Sstevel@tonic-gate { 1127c478bd9Sstevel@tonic-gate int i, a; 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate static struct { 1157c478bd9Sstevel@tonic-gate char *name; 1167c478bd9Sstevel@tonic-gate int *var; 1177c478bd9Sstevel@tonic-gate int defval; 1187c478bd9Sstevel@tonic-gate } prop[] = { 1197c478bd9Sstevel@tonic-gate "dcache-size", &dcache_size, CH_DCACHE_SIZE, 1207c478bd9Sstevel@tonic-gate "dcache-line-size", &dcache_linesize, CH_DCACHE_LSIZE, 1217c478bd9Sstevel@tonic-gate "icache-size", &icache_size, CH_ICACHE_SIZE, 1227c478bd9Sstevel@tonic-gate "icache-line-size", &icache_linesize, CH_ICACHE_LSIZE, 1237c478bd9Sstevel@tonic-gate "ecache-size", &ecache_size, CH_ECACHE_MAX_SIZE, 1247c478bd9Sstevel@tonic-gate "ecache-line-size", &ecache_alignsize, CH_ECACHE_MAX_LSIZE, 1257c478bd9Sstevel@tonic-gate "ecache-associativity", &ecache_associativity, CH_ECACHE_NWAY 1267c478bd9Sstevel@tonic-gate }; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (prop) / sizeof (prop[0]); i++) 1297c478bd9Sstevel@tonic-gate *prop[i].var = getintprop(dnode, prop[i].name, prop[i].defval); 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate ecache_setsize = ecache_size / ecache_associativity; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate vac_size = CH_VAC_SIZE; 1347c478bd9Sstevel@tonic-gate vac_mask = MMU_PAGEMASK & (vac_size - 1); 1357c478bd9Sstevel@tonic-gate i = 0; a = vac_size; 1367c478bd9Sstevel@tonic-gate while (a >>= 1) 1377c478bd9Sstevel@tonic-gate ++i; 1387c478bd9Sstevel@tonic-gate vac_shift = i; 1397c478bd9Sstevel@tonic-gate shm_alignment = vac_size; 1407c478bd9Sstevel@tonic-gate vac = 1; 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * Cheetah's large page support has problems with large numbers of 1447c478bd9Sstevel@tonic-gate * large pages, so just disable large pages out-of-the-box. 145ec25b48fSsusans * Note that the other defaults are set in sun4u/vm/mach_vm_dep.c. 1467c478bd9Sstevel@tonic-gate */ 147ec25b48fSsusans max_uheap_lpsize = MMU_PAGESIZE; 148ec25b48fSsusans max_ustack_lpsize = MMU_PAGESIZE; 149ec25b48fSsusans max_privmap_lpsize = MMU_PAGESIZE; 150ec25b48fSsusans max_utext_lpsize = MMU_PAGESIZE; 15107b65a64Saguzovsk max_shm_lpsize = MMU_PAGESIZE; 152bb121940Sdp78419 max_bootlp_tteszc = TTE8K; 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate void 1567c478bd9Sstevel@tonic-gate send_mondo_set(cpuset_t set) 1577c478bd9Sstevel@tonic-gate { 1587c478bd9Sstevel@tonic-gate int lo, busy, nack, shipped = 0; 1597c478bd9Sstevel@tonic-gate uint16_t i, cpuids[IDSR_BN_SETS]; 1607c478bd9Sstevel@tonic-gate uint64_t idsr, nackmask = 0, busymask, curnack, curbusy; 1617c478bd9Sstevel@tonic-gate uint64_t starttick, endtick, tick, lasttick; 1627c478bd9Sstevel@tonic-gate #if (NCPU > IDSR_BN_SETS) 1637c478bd9Sstevel@tonic-gate int index = 0; 1647c478bd9Sstevel@tonic-gate int ncpuids = 0; 1657c478bd9Sstevel@tonic-gate #endif 1667c478bd9Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 1677c478bd9Sstevel@tonic-gate int recovered = 0; 1687c478bd9Sstevel@tonic-gate int cpuid; 1697c478bd9Sstevel@tonic-gate #endif 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate ASSERT(!CPUSET_ISNULL(set)); 1727c478bd9Sstevel@tonic-gate starttick = lasttick = gettick(); 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate #if (NCPU <= IDSR_BN_SETS) 1757c478bd9Sstevel@tonic-gate for (i = 0; i < NCPU; i++) 1767c478bd9Sstevel@tonic-gate if (CPU_IN_SET(set, i)) { 1777c478bd9Sstevel@tonic-gate shipit(i, shipped); 1787c478bd9Sstevel@tonic-gate nackmask |= IDSR_NACK_BIT(shipped); 1797c478bd9Sstevel@tonic-gate cpuids[shipped++] = i; 1807c478bd9Sstevel@tonic-gate CPUSET_DEL(set, i); 1817c478bd9Sstevel@tonic-gate if (CPUSET_ISNULL(set)) 1827c478bd9Sstevel@tonic-gate break; 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, xcalls, shipped); 1857c478bd9Sstevel@tonic-gate #else 1867c478bd9Sstevel@tonic-gate for (i = 0; i < NCPU; i++) 1877c478bd9Sstevel@tonic-gate if (CPU_IN_SET(set, i)) { 1887c478bd9Sstevel@tonic-gate ncpuids++; 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate /* 1917c478bd9Sstevel@tonic-gate * Ship only to the first (IDSR_BN_SETS) CPUs. If we 1927c478bd9Sstevel@tonic-gate * find we have shipped to more than (IDSR_BN_SETS) 1937c478bd9Sstevel@tonic-gate * CPUs, set "index" to the highest numbered CPU in 1947c478bd9Sstevel@tonic-gate * the set so we can ship to other CPUs a bit later on. 1957c478bd9Sstevel@tonic-gate */ 1967c478bd9Sstevel@tonic-gate if (shipped < IDSR_BN_SETS) { 1977c478bd9Sstevel@tonic-gate shipit(i, shipped); 1987c478bd9Sstevel@tonic-gate nackmask |= IDSR_NACK_BIT(shipped); 1997c478bd9Sstevel@tonic-gate cpuids[shipped++] = i; 2007c478bd9Sstevel@tonic-gate CPUSET_DEL(set, i); 2017c478bd9Sstevel@tonic-gate if (CPUSET_ISNULL(set)) 2027c478bd9Sstevel@tonic-gate break; 2037c478bd9Sstevel@tonic-gate } else 2047c478bd9Sstevel@tonic-gate index = (int)i; 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate CPU_STATS_ADDQ(CPU, sys, xcalls, ncpuids); 2087c478bd9Sstevel@tonic-gate #endif 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate busymask = IDSR_NACK_TO_BUSY(nackmask); 2117c478bd9Sstevel@tonic-gate busy = nack = 0; 2127c478bd9Sstevel@tonic-gate endtick = starttick + xc_tick_limit; 2137c478bd9Sstevel@tonic-gate for (;;) { 2147c478bd9Sstevel@tonic-gate idsr = getidsr(); 2157c478bd9Sstevel@tonic-gate #if (NCPU <= IDSR_BN_SETS) 2167c478bd9Sstevel@tonic-gate if (idsr == 0) 2177c478bd9Sstevel@tonic-gate break; 2187c478bd9Sstevel@tonic-gate #else 2197c478bd9Sstevel@tonic-gate if (idsr == 0 && shipped == ncpuids) 2207c478bd9Sstevel@tonic-gate break; 2217c478bd9Sstevel@tonic-gate #endif 2227c478bd9Sstevel@tonic-gate tick = gettick(); 2237c478bd9Sstevel@tonic-gate /* 2247c478bd9Sstevel@tonic-gate * If there is a big jump between the current tick 2257c478bd9Sstevel@tonic-gate * count and lasttick, we have probably hit a break 2267c478bd9Sstevel@tonic-gate * point. Adjust endtick accordingly to avoid panic. 2277c478bd9Sstevel@tonic-gate */ 2287c478bd9Sstevel@tonic-gate if (tick > (lasttick + xc_tick_jump_limit)) 2297c478bd9Sstevel@tonic-gate endtick += (tick - lasttick); 2307c478bd9Sstevel@tonic-gate lasttick = tick; 2317c478bd9Sstevel@tonic-gate if (tick > endtick) { 2327c478bd9Sstevel@tonic-gate if (panic_quiesce) 2337c478bd9Sstevel@tonic-gate return; 2347c478bd9Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 2357c478bd9Sstevel@tonic-gate cpuid = -1; 2367c478bd9Sstevel@tonic-gate for (i = 0; i < IDSR_BN_SETS; i++) { 2377c478bd9Sstevel@tonic-gate if (idsr & (IDSR_NACK_BIT(i) | 2387c478bd9Sstevel@tonic-gate IDSR_BUSY_BIT(i))) { 2397c478bd9Sstevel@tonic-gate cpuid = cpuids[i]; 2407c478bd9Sstevel@tonic-gate break; 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate if (cheetah_sendmondo_recover && cpuid != -1 && 2447c478bd9Sstevel@tonic-gate recovered == 0) { 2457c478bd9Sstevel@tonic-gate if (mondo_recover(cpuid, i)) { 2467c478bd9Sstevel@tonic-gate /* 2477c478bd9Sstevel@tonic-gate * We claimed the whole memory or 2487c478bd9Sstevel@tonic-gate * full scan is disabled. 2497c478bd9Sstevel@tonic-gate */ 2507c478bd9Sstevel@tonic-gate recovered++; 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate tick = gettick(); 2537c478bd9Sstevel@tonic-gate endtick = tick + xc_tick_limit; 2547c478bd9Sstevel@tonic-gate lasttick = tick; 2557c478bd9Sstevel@tonic-gate /* 2567c478bd9Sstevel@tonic-gate * Recheck idsr 2577c478bd9Sstevel@tonic-gate */ 2587c478bd9Sstevel@tonic-gate continue; 2597c478bd9Sstevel@tonic-gate } else 2607c478bd9Sstevel@tonic-gate #endif /* CHEETAHPLUS_ERRATUM_25 */ 2617c478bd9Sstevel@tonic-gate { 2627c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "send mondo timeout " 2637c478bd9Sstevel@tonic-gate "[%d NACK %d BUSY]\nIDSR 0x%" 2647c478bd9Sstevel@tonic-gate "" PRIx64 " cpuids:", nack, busy, idsr); 2657c478bd9Sstevel@tonic-gate for (i = 0; i < IDSR_BN_SETS; i++) { 2667c478bd9Sstevel@tonic-gate if (idsr & (IDSR_NACK_BIT(i) | 2677c478bd9Sstevel@tonic-gate IDSR_BUSY_BIT(i))) { 2687c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, " 0x%x", 2697c478bd9Sstevel@tonic-gate cpuids[i]); 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "\n"); 2737c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "send_mondo_set: timeout"); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate curnack = idsr & nackmask; 2777c478bd9Sstevel@tonic-gate curbusy = idsr & busymask; 2787c478bd9Sstevel@tonic-gate #if (NCPU > IDSR_BN_SETS) 2797c478bd9Sstevel@tonic-gate if (shipped < ncpuids) { 2807c478bd9Sstevel@tonic-gate uint64_t cpus_left; 2817c478bd9Sstevel@tonic-gate uint16_t next = (uint16_t)index; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate cpus_left = ~(IDSR_NACK_TO_BUSY(curnack) | curbusy) & 2847c478bd9Sstevel@tonic-gate busymask; 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate if (cpus_left) { 2877c478bd9Sstevel@tonic-gate do { 2887c478bd9Sstevel@tonic-gate /* 2897c478bd9Sstevel@tonic-gate * Sequence through and ship to the 2907c478bd9Sstevel@tonic-gate * remainder of the CPUs in the system 2917c478bd9Sstevel@tonic-gate * (e.g. other than the first 2927c478bd9Sstevel@tonic-gate * (IDSR_BN_SETS)) in reverse order. 2937c478bd9Sstevel@tonic-gate */ 2947c478bd9Sstevel@tonic-gate lo = lowbit(cpus_left) - 1; 2957c478bd9Sstevel@tonic-gate i = IDSR_BUSY_IDX(lo); 2967c478bd9Sstevel@tonic-gate shipit(next, i); 2977c478bd9Sstevel@tonic-gate shipped++; 2987c478bd9Sstevel@tonic-gate cpuids[i] = next; 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate /* 3017c478bd9Sstevel@tonic-gate * If we've processed all the CPUs, 3027c478bd9Sstevel@tonic-gate * exit the loop now and save 3037c478bd9Sstevel@tonic-gate * instructions. 3047c478bd9Sstevel@tonic-gate */ 3057c478bd9Sstevel@tonic-gate if (shipped == ncpuids) 3067c478bd9Sstevel@tonic-gate break; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate for ((index = ((int)next - 1)); 3097c478bd9Sstevel@tonic-gate index >= 0; index--) 3107c478bd9Sstevel@tonic-gate if (CPU_IN_SET(set, index)) { 3117c478bd9Sstevel@tonic-gate next = (uint16_t)index; 3127c478bd9Sstevel@tonic-gate break; 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate cpus_left &= ~(1ull << lo); 3167c478bd9Sstevel@tonic-gate } while (cpus_left); 3177c478bd9Sstevel@tonic-gate #ifdef CHEETAHPLUS_ERRATUM_25 3187c478bd9Sstevel@tonic-gate /* 3197c478bd9Sstevel@tonic-gate * Clear recovered because we are sending to 3207c478bd9Sstevel@tonic-gate * a new set of targets. 3217c478bd9Sstevel@tonic-gate */ 3227c478bd9Sstevel@tonic-gate recovered = 0; 3237c478bd9Sstevel@tonic-gate #endif 3247c478bd9Sstevel@tonic-gate continue; 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate #endif 3287c478bd9Sstevel@tonic-gate if (curbusy) { 3297c478bd9Sstevel@tonic-gate busy++; 3307c478bd9Sstevel@tonic-gate continue; 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate 3337c478bd9Sstevel@tonic-gate #ifdef SEND_MONDO_STATS 3347c478bd9Sstevel@tonic-gate { 3357c478bd9Sstevel@tonic-gate int n = gettick() - starttick; 3367c478bd9Sstevel@tonic-gate if (n < 8192) 3377c478bd9Sstevel@tonic-gate x_nack_stimes[n >> 7]++; 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate #endif 3407c478bd9Sstevel@tonic-gate while (gettick() < (tick + sys_clock_mhz)) 3417c478bd9Sstevel@tonic-gate ; 3427c478bd9Sstevel@tonic-gate do { 3437c478bd9Sstevel@tonic-gate lo = lowbit(curnack) - 1; 3447c478bd9Sstevel@tonic-gate i = IDSR_NACK_IDX(lo); 3457c478bd9Sstevel@tonic-gate shipit(cpuids[i], i); 3467c478bd9Sstevel@tonic-gate curnack &= ~(1ull << lo); 3477c478bd9Sstevel@tonic-gate } while (curnack); 3487c478bd9Sstevel@tonic-gate nack++; 3497c478bd9Sstevel@tonic-gate busy = 0; 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate #ifdef SEND_MONDO_STATS 3527c478bd9Sstevel@tonic-gate { 3537c478bd9Sstevel@tonic-gate int n = gettick() - starttick; 3547c478bd9Sstevel@tonic-gate if (n < 8192) 3557c478bd9Sstevel@tonic-gate x_set_stimes[n >> 7]++; 3567c478bd9Sstevel@tonic-gate else 3577c478bd9Sstevel@tonic-gate x_set_ltimes[(n >> 13) & 0xf]++; 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate x_set_cpus[shipped]++; 3607c478bd9Sstevel@tonic-gate #endif 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* 3647c478bd9Sstevel@tonic-gate * Handles error logging for implementation specific error types. 3657c478bd9Sstevel@tonic-gate */ 3667c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3677c478bd9Sstevel@tonic-gate int 3687c478bd9Sstevel@tonic-gate cpu_impl_async_log_err(void *flt, errorq_elem_t *eqep) 3697c478bd9Sstevel@tonic-gate { 3707c478bd9Sstevel@tonic-gate /* There aren't any error types which are specific to cheetah only */ 3717c478bd9Sstevel@tonic-gate return (CH_ASYNC_LOG_UNKNOWN); 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate /* 3757c478bd9Sstevel@tonic-gate * Figure out if Ecache is direct-mapped (Cheetah or Cheetah+ with Ecache 3767c478bd9Sstevel@tonic-gate * control ECCR_ASSOC bit off or 2-way (Cheetah+ with ECCR_ASSOC on). 3777c478bd9Sstevel@tonic-gate * We need to do this on the fly because we may have mixed Cheetah+'s with 3787c478bd9Sstevel@tonic-gate * both direct and 2-way Ecaches. 3797c478bd9Sstevel@tonic-gate */ 3807c478bd9Sstevel@tonic-gate int 3817c478bd9Sstevel@tonic-gate cpu_ecache_nway(void) 3827c478bd9Sstevel@tonic-gate { 3837c478bd9Sstevel@tonic-gate return (CH_ECACHE_NWAY); 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate /* 3877c478bd9Sstevel@tonic-gate * Note that these are entered into the table: Fatal Errors (PERR, IERR, 3887c478bd9Sstevel@tonic-gate * ISAP, EMU) first, orphaned UCU/UCC, AFAR Overwrite policy, finally IVU, IVC. 3897c478bd9Sstevel@tonic-gate * Afar overwrite policy is: 3907c478bd9Sstevel@tonic-gate * UCU,UCC > UE,EDU,WDU,CPU > CE,EDC,EMC,WDC,CPC > TO,BERR 3917c478bd9Sstevel@tonic-gate */ 3927c478bd9Sstevel@tonic-gate ecc_type_to_info_t ecc_type_to_info[] = { 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate /* Fatal Errors */ 3957c478bd9Sstevel@tonic-gate C_AFSR_PERR, "PERR ", ECC_ALL_TRAPS, CPU_FATAL, 3967c478bd9Sstevel@tonic-gate "PERR Fatal", 3977c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM2, 3987c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_PERR, 3997c478bd9Sstevel@tonic-gate C_AFSR_IERR, "IERR ", ECC_ALL_TRAPS, CPU_FATAL, 4007c478bd9Sstevel@tonic-gate "IERR Fatal", 4017c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM2, 4027c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IERR, 4037c478bd9Sstevel@tonic-gate C_AFSR_ISAP, "ISAP ", ECC_ALL_TRAPS, CPU_FATAL, 4047c478bd9Sstevel@tonic-gate "ISAP Fatal", 4057c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 4067c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_ISAP, 4077c478bd9Sstevel@tonic-gate C_AFSR_EMU, "EMU ", ECC_ASYNC_TRAPS, CPU_FATAL, 4087c478bd9Sstevel@tonic-gate "EMU Fatal", 4097c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 4107c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EMU, 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate /* Orphaned UCC/UCU Errors */ 4137c478bd9Sstevel@tonic-gate C_AFSR_UCU, "OUCU ", ECC_ORPH_TRAPS, CPU_ORPH, 4147c478bd9Sstevel@tonic-gate "Orphaned UCU", 4157c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4167c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCU, 4177c478bd9Sstevel@tonic-gate C_AFSR_UCC, "OUCC ", ECC_ORPH_TRAPS, CPU_ORPH, 4187c478bd9Sstevel@tonic-gate "Orphaned UCC", 4197c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4207c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCC, 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate /* UCU, UCC */ 4237c478bd9Sstevel@tonic-gate C_AFSR_UCU, "UCU ", ECC_F_TRAP, CPU_UE_ECACHE, 4247c478bd9Sstevel@tonic-gate "UCU", 4257c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4267c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCU, 4277c478bd9Sstevel@tonic-gate C_AFSR_UCC, "UCC ", ECC_F_TRAP, CPU_CE_ECACHE, 4287c478bd9Sstevel@tonic-gate "UCC", 4297c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4307c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UCC, 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate /* UE, EDU:ST, EDU:BLD, WDU, CPU */ 4337c478bd9Sstevel@tonic-gate C_AFSR_UE, "UE ", ECC_ASYNC_TRAPS, CPU_UE, 4347c478bd9Sstevel@tonic-gate "Uncorrectable system bus (UE)", 4357c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 4367c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UE, 4377c478bd9Sstevel@tonic-gate C_AFSR_EDU, "EDU ", ECC_C_TRAP, CPU_UE_ECACHE_RETIRE, 4387c478bd9Sstevel@tonic-gate "EDU:ST", 4397c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4407c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EDUST, 4417c478bd9Sstevel@tonic-gate C_AFSR_EDU, "EDU ", ECC_D_TRAP, CPU_UE_ECACHE_RETIRE, 4427c478bd9Sstevel@tonic-gate "EDU:BLD", 4437c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4447c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EDUBL, 4457c478bd9Sstevel@tonic-gate C_AFSR_WDU, "WDU ", ECC_C_TRAP, CPU_UE_ECACHE_RETIRE, 4467c478bd9Sstevel@tonic-gate "WDU", 4477c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4487c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_WDU, 4497c478bd9Sstevel@tonic-gate C_AFSR_CPU, "CPU ", ECC_C_TRAP, CPU_UE_ECACHE, 4507c478bd9Sstevel@tonic-gate "CPU", 4517c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4527c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_CPU, 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate /* CE, EDC, EMC, WDC, CPC */ 4557c478bd9Sstevel@tonic-gate C_AFSR_CE, "CE ", ECC_C_TRAP, CPU_CE, 4567c478bd9Sstevel@tonic-gate "Corrected system bus (CE)", 4577c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 4587c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_CE, 4597c478bd9Sstevel@tonic-gate C_AFSR_EDC, "EDC ", ECC_C_TRAP, CPU_CE_ECACHE, 4607c478bd9Sstevel@tonic-gate "EDC", 4617c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4627c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EDC, 4637c478bd9Sstevel@tonic-gate C_AFSR_EMC, "EMC ", ECC_C_TRAP, CPU_EMC, 4647c478bd9Sstevel@tonic-gate "EMC", 4657c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_MEMORY, 4667c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_EMC, 4677c478bd9Sstevel@tonic-gate C_AFSR_WDC, "WDC ", ECC_C_TRAP, CPU_CE_ECACHE, 4687c478bd9Sstevel@tonic-gate "WDC", 4697c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4707c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_WDC, 4717c478bd9Sstevel@tonic-gate C_AFSR_CPC, "CPC ", ECC_C_TRAP, CPU_CE_ECACHE, 4727c478bd9Sstevel@tonic-gate "CPC", 4737c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_L2_DATA, 4747c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_CPC, 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate /* TO, BERR */ 4777c478bd9Sstevel@tonic-gate C_AFSR_TO, "TO ", ECC_ASYNC_TRAPS, CPU_TO, 4787c478bd9Sstevel@tonic-gate "Timeout (TO)", 4797c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_IO, 4807c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_TO, 4817c478bd9Sstevel@tonic-gate C_AFSR_BERR, "BERR ", ECC_ASYNC_TRAPS, CPU_BERR, 4827c478bd9Sstevel@tonic-gate "Bus Error (BERR)", 4837c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_IO, 4847c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_BERR, 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate /* IVU, IVC */ 4877c478bd9Sstevel@tonic-gate C_AFSR_IVU, "IVU ", ECC_C_TRAP, CPU_IV, 4887c478bd9Sstevel@tonic-gate "IVU", 4897c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 4907c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IVU, 4917c478bd9Sstevel@tonic-gate C_AFSR_IVC, "IVC ", ECC_C_TRAP, CPU_IV, 4927c478bd9Sstevel@tonic-gate "IVC", 4937c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_SYSTEM1, 4947c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_IVC, 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate 0, NULL, 0, 0, 4977c478bd9Sstevel@tonic-gate NULL, 4987c478bd9Sstevel@tonic-gate FM_EREPORT_PAYLOAD_UNKNOWN, 4997c478bd9Sstevel@tonic-gate FM_EREPORT_CPU_USIII_UNKNOWN, 5007c478bd9Sstevel@tonic-gate }; 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate /* 5037c478bd9Sstevel@tonic-gate * Prioritized list of Error bits for AFAR overwrite. 5047c478bd9Sstevel@tonic-gate * See Cheetah PRM P.6.1 5057c478bd9Sstevel@tonic-gate * Class 4: UCC, UCU 5067c478bd9Sstevel@tonic-gate * Class 3: UE, EDU, EMU, WDU, CPU 5077c478bd9Sstevel@tonic-gate * Class 2: CE, EDC, EMC, WDC, CPC 5087c478bd9Sstevel@tonic-gate * Class 1: TO, BERR 5097c478bd9Sstevel@tonic-gate */ 5107c478bd9Sstevel@tonic-gate uint64_t afar_overwrite[] = { 5117c478bd9Sstevel@tonic-gate C_AFSR_UCC | C_AFSR_UCU, 5127c478bd9Sstevel@tonic-gate C_AFSR_UE | C_AFSR_EDU | C_AFSR_EMU | C_AFSR_WDU | C_AFSR_CPU, 5137c478bd9Sstevel@tonic-gate C_AFSR_CE | C_AFSR_EDC | C_AFSR_EMC | C_AFSR_WDC | C_AFSR_CPC, 5147c478bd9Sstevel@tonic-gate C_AFSR_TO | C_AFSR_BERR, 5157c478bd9Sstevel@tonic-gate 0 5167c478bd9Sstevel@tonic-gate }; 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate /* 5197c478bd9Sstevel@tonic-gate * Prioritized list of Error bits for ESYND overwrite. 5207c478bd9Sstevel@tonic-gate * See Cheetah PRM P.6.2 5217c478bd9Sstevel@tonic-gate * Class 2: UE, IVU, EDU, WDU, UCU, CPU 5227c478bd9Sstevel@tonic-gate * Class 1: CE, IVC, EDC, WDC, UCC, CPC 5237c478bd9Sstevel@tonic-gate */ 5247c478bd9Sstevel@tonic-gate uint64_t esynd_overwrite[] = { 5257c478bd9Sstevel@tonic-gate C_AFSR_UE | C_AFSR_IVU | C_AFSR_EDU | C_AFSR_WDU | C_AFSR_UCU | 5267c478bd9Sstevel@tonic-gate C_AFSR_CPU, 5277c478bd9Sstevel@tonic-gate C_AFSR_CE | C_AFSR_IVC | C_AFSR_EDC | C_AFSR_WDC | C_AFSR_UCC | 5287c478bd9Sstevel@tonic-gate C_AFSR_CPC, 5297c478bd9Sstevel@tonic-gate 0 5307c478bd9Sstevel@tonic-gate }; 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate /* 5337c478bd9Sstevel@tonic-gate * Prioritized list of Error bits for MSYND overwrite. 5347c478bd9Sstevel@tonic-gate * See Cheetah PRM P.6.3 5357c478bd9Sstevel@tonic-gate * Class 2: EMU 5367c478bd9Sstevel@tonic-gate * Class 1: EMC 5377c478bd9Sstevel@tonic-gate */ 5387c478bd9Sstevel@tonic-gate uint64_t msynd_overwrite[] = { 5397c478bd9Sstevel@tonic-gate C_AFSR_EMU, 5407c478bd9Sstevel@tonic-gate C_AFSR_EMC, 5417c478bd9Sstevel@tonic-gate 0 5427c478bd9Sstevel@tonic-gate }; 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate /* 5457c478bd9Sstevel@tonic-gate * change cpu speed bits -- new speed will be normal-speed/divisor. 5467c478bd9Sstevel@tonic-gate * 5477c478bd9Sstevel@tonic-gate * The Jalapeno memory controllers are required to drain outstanding 5487c478bd9Sstevel@tonic-gate * memory transactions within 32 JBus clocks in order to be ready 5497c478bd9Sstevel@tonic-gate * to enter Estar mode. In some corner cases however, that time 5507c478bd9Sstevel@tonic-gate * fell short. 5517c478bd9Sstevel@tonic-gate * 5527c478bd9Sstevel@tonic-gate * A safe software solution is to force MCU to act like in Estar mode, 5537c478bd9Sstevel@tonic-gate * then delay 1us (in ppm code) prior to assert J_CHNG_L signal. 5547c478bd9Sstevel@tonic-gate * To reverse the effect, upon exiting Estar, software restores the 5557c478bd9Sstevel@tonic-gate * MCU to its original state. 5567c478bd9Sstevel@tonic-gate */ 5577c478bd9Sstevel@tonic-gate /* ARGSUSED1 */ 5587c478bd9Sstevel@tonic-gate void 5597c478bd9Sstevel@tonic-gate cpu_change_speed(uint64_t divisor, uint64_t arg2) 5607c478bd9Sstevel@tonic-gate { 5617c478bd9Sstevel@tonic-gate bus_config_eclk_t *bceclk; 5627c478bd9Sstevel@tonic-gate uint64_t reg; 5635cff7825Smh27603 processor_info_t *pi = &(CPU->cpu_type_info); 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate for (bceclk = bus_config_eclk; bceclk->divisor; bceclk++) { 5667c478bd9Sstevel@tonic-gate if (bceclk->divisor != divisor) 5677c478bd9Sstevel@tonic-gate continue; 5687c478bd9Sstevel@tonic-gate reg = get_safari_config(); 5697c478bd9Sstevel@tonic-gate reg &= ~SAFARI_CONFIG_ECLK_MASK; 5707c478bd9Sstevel@tonic-gate reg |= bceclk->mask; 5717c478bd9Sstevel@tonic-gate set_safari_config(reg); 5727c478bd9Sstevel@tonic-gate CPU->cpu_m.divisor = (uchar_t)divisor; 573*0e751525SEric Saxe cpu_set_curr_clock(((uint64_t)pi->pi_clock * 1000000) / 574*0e751525SEric Saxe divisor); 5757c478bd9Sstevel@tonic-gate return; 5767c478bd9Sstevel@tonic-gate } 5777c478bd9Sstevel@tonic-gate /* 5787c478bd9Sstevel@tonic-gate * We will reach here only if OBP and kernel don't agree on 5797c478bd9Sstevel@tonic-gate * the speeds supported by the CPU. 5807c478bd9Sstevel@tonic-gate */ 5817c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "cpu_change_speed: bad divisor %" PRIu64, divisor); 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate /* 5857c478bd9Sstevel@tonic-gate * Cpu private initialization. This includes allocating the cpu_private 5867c478bd9Sstevel@tonic-gate * data structure, initializing it, and initializing the scrubber for this 5877c478bd9Sstevel@tonic-gate * cpu. This function calls cpu_init_ecache_scrub_dr to init the scrubber. 5887c478bd9Sstevel@tonic-gate * We use kmem_cache_create for the cheetah private data structure because 5897c478bd9Sstevel@tonic-gate * it needs to be allocated on a PAGESIZE (8192) byte boundary. 5907c478bd9Sstevel@tonic-gate */ 5917c478bd9Sstevel@tonic-gate void 5927c478bd9Sstevel@tonic-gate cpu_init_private(struct cpu *cp) 5937c478bd9Sstevel@tonic-gate { 5947c478bd9Sstevel@tonic-gate cheetah_private_t *chprp; 5957c478bd9Sstevel@tonic-gate int i; 5967c478bd9Sstevel@tonic-gate 5977c478bd9Sstevel@tonic-gate ASSERT(CPU_PRIVATE(cp) == NULL); 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate /* LINTED: E_TRUE_LOGICAL_EXPR */ 6007c478bd9Sstevel@tonic-gate ASSERT((offsetof(cheetah_private_t, chpr_tl1_err_data) + 6017c478bd9Sstevel@tonic-gate sizeof (ch_err_tl1_data_t) * CH_ERR_TL1_TLMAX) <= PAGESIZE); 6027c478bd9Sstevel@tonic-gate 6037c478bd9Sstevel@tonic-gate /* 6047c478bd9Sstevel@tonic-gate * Running with a Cheetah+, Jaguar, or Panther on a Cheetah CPU 6057c478bd9Sstevel@tonic-gate * machine is not a supported configuration. Attempting to do so 6067c478bd9Sstevel@tonic-gate * may result in unpredictable failures (e.g. running Cheetah+ 6077c478bd9Sstevel@tonic-gate * CPUs with Cheetah E$ disp flush) so don't allow it. 6087c478bd9Sstevel@tonic-gate * 6097c478bd9Sstevel@tonic-gate * This is just defensive code since this configuration mismatch 6107c478bd9Sstevel@tonic-gate * should have been caught prior to OS execution. 6117c478bd9Sstevel@tonic-gate */ 6127c478bd9Sstevel@tonic-gate if (!IS_CHEETAH(cpunodes[cp->cpu_id].implementation)) { 6137c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "CPU%d: UltraSPARC-III+/IV/IV+ not" 6147c478bd9Sstevel@tonic-gate " supported on UltraSPARC-III code\n", cp->cpu_id); 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate /* 6187c478bd9Sstevel@tonic-gate * If the ch_private_cache has not been created, create it. 6197c478bd9Sstevel@tonic-gate */ 6207c478bd9Sstevel@tonic-gate if (ch_private_cache == NULL) { 6217c478bd9Sstevel@tonic-gate ch_private_cache = kmem_cache_create("ch_private_cache", 6227c478bd9Sstevel@tonic-gate sizeof (cheetah_private_t), PAGESIZE, NULL, NULL, 6237c478bd9Sstevel@tonic-gate NULL, NULL, static_arena, 0); 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate chprp = CPU_PRIVATE(cp) = kmem_cache_alloc(ch_private_cache, KM_SLEEP); 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate bzero(chprp, sizeof (cheetah_private_t)); 6297c478bd9Sstevel@tonic-gate chprp->chpr_fecctl0_logout.clo_data.chd_afar = LOGOUT_INVALID; 6307c478bd9Sstevel@tonic-gate chprp->chpr_cecc_logout.clo_data.chd_afar = LOGOUT_INVALID; 6317c478bd9Sstevel@tonic-gate chprp->chpr_async_logout.clo_data.chd_afar = LOGOUT_INVALID; 6327c478bd9Sstevel@tonic-gate for (i = 0; i < CH_ERR_TL1_TLMAX; i++) 6337c478bd9Sstevel@tonic-gate chprp->chpr_tl1_err_data[i].ch_err_tl1_logout.clo_data.chd_afar 6347c478bd9Sstevel@tonic-gate = LOGOUT_INVALID; 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate chprp->chpr_icache_size = CH_ICACHE_SIZE; 6377c478bd9Sstevel@tonic-gate chprp->chpr_icache_linesize = CH_ICACHE_LSIZE; 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate cpu_init_ecache_scrub_dr(cp); 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate chprp->chpr_ec_set_size = cpunodes[cp->cpu_id].ecache_size / 6427c478bd9Sstevel@tonic-gate cpu_ecache_nway(); 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate adjust_hw_copy_limits(cpunodes[cp->cpu_id].ecache_size); 6457c478bd9Sstevel@tonic-gate ch_err_tl1_paddrs[cp->cpu_id] = va_to_pa(chprp); 6467c478bd9Sstevel@tonic-gate ASSERT(ch_err_tl1_paddrs[cp->cpu_id] != -1); 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate /* 6507c478bd9Sstevel@tonic-gate * Clear the error state registers for this CPU. 6517c478bd9Sstevel@tonic-gate * For Cheetah, just clear the AFSR 6527c478bd9Sstevel@tonic-gate */ 6537c478bd9Sstevel@tonic-gate void 6547c478bd9Sstevel@tonic-gate set_cpu_error_state(ch_cpu_errors_t *cpu_error_regs) 6557c478bd9Sstevel@tonic-gate { 6567c478bd9Sstevel@tonic-gate set_asyncflt(cpu_error_regs->afsr & ~C_AFSR_FATAL_ERRS); 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate /* 6607c478bd9Sstevel@tonic-gate * For Cheetah, the error recovery code uses an alternate flush area in the 6617c478bd9Sstevel@tonic-gate * TL>0 fast ECC handler. ecache_tl1_flushaddr is the physical address of 6627c478bd9Sstevel@tonic-gate * this exclusive displacement flush area. 6637c478bd9Sstevel@tonic-gate */ 6647c478bd9Sstevel@tonic-gate uint64_t ecache_tl1_flushaddr = (uint64_t)-1; /* physaddr for E$ flushing */ 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate /* 6677c478bd9Sstevel@tonic-gate * Allocate and initialize the exclusive displacement flush area. 6687c478bd9Sstevel@tonic-gate */ 6697c478bd9Sstevel@tonic-gate caddr_t 6707c478bd9Sstevel@tonic-gate ecache_init_scrub_flush_area(caddr_t alloc_base) 6717c478bd9Sstevel@tonic-gate { 672986fd29aSsetje unsigned size = 2 * CH_ECACHE_8M_SIZE; 673986fd29aSsetje caddr_t tmp_alloc_base = alloc_base; 674986fd29aSsetje caddr_t flush_alloc_base = 675986fd29aSsetje (caddr_t)roundup((uintptr_t)alloc_base, size); 676986fd29aSsetje caddr_t ecache_tl1_virtaddr; 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate /* 679986fd29aSsetje * Allocate the physical memory for the exclusive flush area 680986fd29aSsetje * 6817c478bd9Sstevel@tonic-gate * Need to allocate an exclusive flush area that is twice the 6827c478bd9Sstevel@tonic-gate * largest supported E$ size, physically contiguous, and 6837c478bd9Sstevel@tonic-gate * aligned on twice the largest E$ size boundary. 684986fd29aSsetje * 685986fd29aSsetje * Memory allocated via prom_alloc is included in the "cage" 686986fd29aSsetje * from the DR perspective and due to this, its physical 687986fd29aSsetje * address will never change and the memory will not be 688986fd29aSsetje * removed. 689986fd29aSsetje * 690986fd29aSsetje * prom_alloc takes 3 arguments: bootops, virtual address hint, 691986fd29aSsetje * size of the area to allocate, and alignment of the area to 692986fd29aSsetje * allocate. It returns zero if the allocation fails, or the 693986fd29aSsetje * virtual address for a successful allocation. Memory prom_alloc'd 694986fd29aSsetje * is physically contiguous. 6957c478bd9Sstevel@tonic-gate */ 696986fd29aSsetje if ((ecache_tl1_virtaddr = 697986fd29aSsetje prom_alloc(flush_alloc_base, size, size)) != NULL) { 6987c478bd9Sstevel@tonic-gate 699986fd29aSsetje tmp_alloc_base = 700986fd29aSsetje (caddr_t)roundup((uintptr_t)(ecache_tl1_virtaddr + size), 701986fd29aSsetje ecache_alignsize); 702986fd29aSsetje 703986fd29aSsetje /* 704986fd29aSsetje * get the physical address of the exclusive flush area 705986fd29aSsetje */ 706986fd29aSsetje ecache_tl1_flushaddr = va_to_pa(ecache_tl1_virtaddr); 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate } else { 709986fd29aSsetje ecache_tl1_virtaddr = (caddr_t)-1; 710986fd29aSsetje cmn_err(CE_NOTE, "!ecache_init_scrub_flush_area failed\n"); 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate 713986fd29aSsetje return (tmp_alloc_base); 7147c478bd9Sstevel@tonic-gate } 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate /* 7177c478bd9Sstevel@tonic-gate * Update cpu_offline_set so the scrubber knows which cpus are offline 7187c478bd9Sstevel@tonic-gate */ 7197c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 7207c478bd9Sstevel@tonic-gate int 7217c478bd9Sstevel@tonic-gate cpu_scrub_cpu_setup(cpu_setup_t what, int cpuid, void *arg) 7227c478bd9Sstevel@tonic-gate { 7237c478bd9Sstevel@tonic-gate switch (what) { 7247c478bd9Sstevel@tonic-gate case CPU_ON: 7257c478bd9Sstevel@tonic-gate case CPU_INIT: 7267c478bd9Sstevel@tonic-gate CPUSET_DEL(cpu_offline_set, cpuid); 7277c478bd9Sstevel@tonic-gate break; 7287c478bd9Sstevel@tonic-gate case CPU_OFF: 7297c478bd9Sstevel@tonic-gate CPUSET_ADD(cpu_offline_set, cpuid); 7307c478bd9Sstevel@tonic-gate break; 7317c478bd9Sstevel@tonic-gate default: 7327c478bd9Sstevel@tonic-gate break; 7337c478bd9Sstevel@tonic-gate } 7347c478bd9Sstevel@tonic-gate return (0); 7357c478bd9Sstevel@tonic-gate } 736