1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/cpu.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/clock.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/promif.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/promimpl.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/machsystm.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/cpu_module.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/cmp.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/async.h> 46*7c478bd9Sstevel@tonic-gate #include <vm/page.h> 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate /* 49*7c478bd9Sstevel@tonic-gate * The OpenBoot Standalone Interface supplies the kernel with 50*7c478bd9Sstevel@tonic-gate * implementation dependent parameters through the devinfo/property mechanism 51*7c478bd9Sstevel@tonic-gate */ 52*7c478bd9Sstevel@tonic-gate typedef enum { XDRBOOL, XDRINT, XDRSTRING } xdrs; 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate /* 55*7c478bd9Sstevel@tonic-gate * structure describing properties that we are interested in querying the 56*7c478bd9Sstevel@tonic-gate * OBP for. 57*7c478bd9Sstevel@tonic-gate */ 58*7c478bd9Sstevel@tonic-gate struct getprop_info { 59*7c478bd9Sstevel@tonic-gate char *name; 60*7c478bd9Sstevel@tonic-gate xdrs type; 61*7c478bd9Sstevel@tonic-gate uint_t *var; 62*7c478bd9Sstevel@tonic-gate }; 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate /* 65*7c478bd9Sstevel@tonic-gate * structure used to convert between a string returned by the OBP & a type 66*7c478bd9Sstevel@tonic-gate * used within the kernel. We prefer to paramaterize rather than type. 67*7c478bd9Sstevel@tonic-gate */ 68*7c478bd9Sstevel@tonic-gate struct convert_info { 69*7c478bd9Sstevel@tonic-gate char *name; 70*7c478bd9Sstevel@tonic-gate uint_t var; 71*7c478bd9Sstevel@tonic-gate char *realname; 72*7c478bd9Sstevel@tonic-gate }; 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate /* 75*7c478bd9Sstevel@tonic-gate * structure describing nodes that we are interested in querying the OBP for 76*7c478bd9Sstevel@tonic-gate * properties. 77*7c478bd9Sstevel@tonic-gate */ 78*7c478bd9Sstevel@tonic-gate struct node_info { 79*7c478bd9Sstevel@tonic-gate char *name; 80*7c478bd9Sstevel@tonic-gate int size; 81*7c478bd9Sstevel@tonic-gate struct getprop_info *prop; 82*7c478bd9Sstevel@tonic-gate struct getprop_info *prop_end; 83*7c478bd9Sstevel@tonic-gate unsigned int *value; 84*7c478bd9Sstevel@tonic-gate }; 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate /* 87*7c478bd9Sstevel@tonic-gate * macro definitions for routines that form the OBP interface 88*7c478bd9Sstevel@tonic-gate */ 89*7c478bd9Sstevel@tonic-gate #define NEXT prom_nextnode 90*7c478bd9Sstevel@tonic-gate #define CHILD prom_childnode 91*7c478bd9Sstevel@tonic-gate #define GETPROP prom_getprop 92*7c478bd9Sstevel@tonic-gate #define GETPROPLEN prom_getproplen 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate /* 0=quiet; 1=verbose; 2=debug */ 95*7c478bd9Sstevel@tonic-gate int debug_fillsysinfo = 0; 96*7c478bd9Sstevel@tonic-gate #define VPRINTF if (debug_fillsysinfo) prom_printf 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate int ncpunode; 99*7c478bd9Sstevel@tonic-gate struct cpu_node cpunodes[NCPU]; 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate void fill_cpu(dnode_t); 102*7c478bd9Sstevel@tonic-gate void plat_fill_mc(dnode_t); 103*7c478bd9Sstevel@tonic-gate #pragma weak plat_fill_mc 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate uint64_t system_clock_freq; 106*7c478bd9Sstevel@tonic-gate int niobus = 0; 107*7c478bd9Sstevel@tonic-gate uint_t niommu_tsbs = 0; 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate /* 110*7c478bd9Sstevel@tonic-gate * Hardware watchdog support. 111*7c478bd9Sstevel@tonic-gate */ 112*7c478bd9Sstevel@tonic-gate #define CHOSEN_EEPROM "eeprom" 113*7c478bd9Sstevel@tonic-gate static dnode_t chosen_eeprom; 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate /* 116*7c478bd9Sstevel@tonic-gate * If this variable is non-zero, cpr should return "not supported" when 117*7c478bd9Sstevel@tonic-gate * it is queried even though it would normally be supported on this platform. 118*7c478bd9Sstevel@tonic-gate */ 119*7c478bd9Sstevel@tonic-gate int cpr_supported_override; 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate /* 122*7c478bd9Sstevel@tonic-gate * Some platforms may need to support CPR even in the absence of the 123*7c478bd9Sstevel@tonic-gate * energystar-v* property (Enchilada server, for example). If this 124*7c478bd9Sstevel@tonic-gate * variable is non-zero, cpr should proceed even in the absence 125*7c478bd9Sstevel@tonic-gate * of the energystar-v* property. 126*7c478bd9Sstevel@tonic-gate */ 127*7c478bd9Sstevel@tonic-gate int cpr_platform_enable = 0; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate /* 130*7c478bd9Sstevel@tonic-gate * Some nodes have functions that need to be called when they're seen. 131*7c478bd9Sstevel@tonic-gate */ 132*7c478bd9Sstevel@tonic-gate static void have_pci(dnode_t); 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate static struct wkdevice { 135*7c478bd9Sstevel@tonic-gate char *wk_namep; 136*7c478bd9Sstevel@tonic-gate void (*wk_func)(dnode_t); 137*7c478bd9Sstevel@tonic-gate caddr_t *wk_vaddrp; 138*7c478bd9Sstevel@tonic-gate ushort_t wk_flags; 139*7c478bd9Sstevel@tonic-gate #define V_OPTIONAL 0x0000 140*7c478bd9Sstevel@tonic-gate #define V_MUSTHAVE 0x0001 141*7c478bd9Sstevel@tonic-gate #define V_MAPPED 0x0002 142*7c478bd9Sstevel@tonic-gate #define V_MULTI 0x0003 /* optional, may be more than one */ 143*7c478bd9Sstevel@tonic-gate } wkdevice[] = { 144*7c478bd9Sstevel@tonic-gate { "pci", have_pci, NULL, V_MULTI }, 145*7c478bd9Sstevel@tonic-gate { 0, }, 146*7c478bd9Sstevel@tonic-gate }; 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate static void map_wellknown(dnode_t); 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate void 151*7c478bd9Sstevel@tonic-gate map_wellknown_devices() 152*7c478bd9Sstevel@tonic-gate { 153*7c478bd9Sstevel@tonic-gate struct wkdevice *wkp; 154*7c478bd9Sstevel@tonic-gate phandle_t ieeprom; 155*7c478bd9Sstevel@tonic-gate dnode_t root; 156*7c478bd9Sstevel@tonic-gate uint_t stick_freq; 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate /* 159*7c478bd9Sstevel@tonic-gate * if there is a chosen eeprom, note it (for have_eeprom()) 160*7c478bd9Sstevel@tonic-gate */ 161*7c478bd9Sstevel@tonic-gate if (GETPROPLEN(prom_chosennode(), CHOSEN_EEPROM) == 162*7c478bd9Sstevel@tonic-gate sizeof (phandle_t) && 163*7c478bd9Sstevel@tonic-gate GETPROP(prom_chosennode(), CHOSEN_EEPROM, (caddr_t)&ieeprom) != -1) 164*7c478bd9Sstevel@tonic-gate chosen_eeprom = (dnode_t)prom_decode_int(ieeprom); 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate root = prom_nextnode((dnode_t)0); 167*7c478bd9Sstevel@tonic-gate /* 168*7c478bd9Sstevel@tonic-gate * Get System clock frequency from root node if it exists. 169*7c478bd9Sstevel@tonic-gate */ 170*7c478bd9Sstevel@tonic-gate if (GETPROP(root, "stick-frequency", (caddr_t)&stick_freq) != -1) 171*7c478bd9Sstevel@tonic-gate system_clock_freq = stick_freq; 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate map_wellknown(NEXT((dnode_t)0)); 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate /* 176*7c478bd9Sstevel@tonic-gate * See if it worked 177*7c478bd9Sstevel@tonic-gate */ 178*7c478bd9Sstevel@tonic-gate for (wkp = wkdevice; wkp->wk_namep; ++wkp) { 179*7c478bd9Sstevel@tonic-gate if (wkp->wk_flags == V_MUSTHAVE) { 180*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "map_wellknown_devices: required " 181*7c478bd9Sstevel@tonic-gate "device %s not mapped", wkp->wk_namep); 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate /* 187*7c478bd9Sstevel@tonic-gate * map_wellknown - map known devices & registers 188*7c478bd9Sstevel@tonic-gate */ 189*7c478bd9Sstevel@tonic-gate static void 190*7c478bd9Sstevel@tonic-gate map_wellknown(dnode_t curnode) 191*7c478bd9Sstevel@tonic-gate { 192*7c478bd9Sstevel@tonic-gate extern int status_okay(int, char *, int); 193*7c478bd9Sstevel@tonic-gate char tmp_name[MAXSYSNAME]; 194*7c478bd9Sstevel@tonic-gate static void fill_address(dnode_t, char *); 195*7c478bd9Sstevel@tonic-gate int sok; 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate #ifdef VPRINTF 198*7c478bd9Sstevel@tonic-gate VPRINTF("map_wellknown(%x)\n", curnode); 199*7c478bd9Sstevel@tonic-gate #endif /* VPRINTF */ 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate for (curnode = CHILD(curnode); curnode; curnode = NEXT(curnode)) { 202*7c478bd9Sstevel@tonic-gate /* 203*7c478bd9Sstevel@tonic-gate * prune subtree if status property indicating not okay 204*7c478bd9Sstevel@tonic-gate */ 205*7c478bd9Sstevel@tonic-gate sok = status_okay((int)curnode, (char *)NULL, 0); 206*7c478bd9Sstevel@tonic-gate if (!sok) { 207*7c478bd9Sstevel@tonic-gate char devtype_buf[OBP_MAXPROPNAME]; 208*7c478bd9Sstevel@tonic-gate int size; 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate #ifdef VPRINTF 211*7c478bd9Sstevel@tonic-gate VPRINTF("map_wellknown: !okay status property\n"); 212*7c478bd9Sstevel@tonic-gate #endif /* VPRINTF */ 213*7c478bd9Sstevel@tonic-gate /* 214*7c478bd9Sstevel@tonic-gate * a status property indicating bad memory will be 215*7c478bd9Sstevel@tonic-gate * associated with a node which has a "device_type" 216*7c478bd9Sstevel@tonic-gate * property with a value of "memory-controller" 217*7c478bd9Sstevel@tonic-gate */ 218*7c478bd9Sstevel@tonic-gate if ((size = GETPROPLEN(curnode, 219*7c478bd9Sstevel@tonic-gate OBP_DEVICETYPE)) == -1) 220*7c478bd9Sstevel@tonic-gate continue; 221*7c478bd9Sstevel@tonic-gate if (size > OBP_MAXPROPNAME) { 222*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "node %x '%s' prop too " 223*7c478bd9Sstevel@tonic-gate "big\n", curnode, OBP_DEVICETYPE); 224*7c478bd9Sstevel@tonic-gate continue; 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate if (GETPROP(curnode, OBP_DEVICETYPE, 227*7c478bd9Sstevel@tonic-gate devtype_buf) == -1) { 228*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "node %x '%s' get failed\n", 229*7c478bd9Sstevel@tonic-gate curnode, OBP_DEVICETYPE); 230*7c478bd9Sstevel@tonic-gate continue; 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate if (strcmp(devtype_buf, "memory-controller") != 0) 233*7c478bd9Sstevel@tonic-gate continue; 234*7c478bd9Sstevel@tonic-gate /* 235*7c478bd9Sstevel@tonic-gate * ...else fall thru and process the node... 236*7c478bd9Sstevel@tonic-gate */ 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate bzero(tmp_name, MAXSYSNAME); 239*7c478bd9Sstevel@tonic-gate if (GETPROP(curnode, OBP_NAME, (caddr_t)tmp_name) != -1) 240*7c478bd9Sstevel@tonic-gate fill_address(curnode, tmp_name); 241*7c478bd9Sstevel@tonic-gate if (GETPROP(curnode, OBP_DEVICETYPE, tmp_name) != -1 && 242*7c478bd9Sstevel@tonic-gate strcmp(tmp_name, "cpu") == 0) { 243*7c478bd9Sstevel@tonic-gate fill_cpu(curnode); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate if (sok && (strcmp(tmp_name, "memory-controller") == 0) && 247*7c478bd9Sstevel@tonic-gate (&plat_fill_mc != NULL)) 248*7c478bd9Sstevel@tonic-gate plat_fill_mc(curnode); 249*7c478bd9Sstevel@tonic-gate map_wellknown(curnode); 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate static void 254*7c478bd9Sstevel@tonic-gate fill_address(dnode_t curnode, char *namep) 255*7c478bd9Sstevel@tonic-gate { 256*7c478bd9Sstevel@tonic-gate struct wkdevice *wkp; 257*7c478bd9Sstevel@tonic-gate int size; 258*7c478bd9Sstevel@tonic-gate uint32_t vaddr; 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate for (wkp = wkdevice; wkp->wk_namep; ++wkp) { 261*7c478bd9Sstevel@tonic-gate if (strcmp(wkp->wk_namep, namep) != 0) 262*7c478bd9Sstevel@tonic-gate continue; 263*7c478bd9Sstevel@tonic-gate if (wkp->wk_flags == V_MAPPED) 264*7c478bd9Sstevel@tonic-gate return; 265*7c478bd9Sstevel@tonic-gate if (wkp->wk_vaddrp != NULL) { 266*7c478bd9Sstevel@tonic-gate if ((size = GETPROPLEN(curnode, OBP_ADDRESS)) == -1) { 267*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "device %s size %d\n", 268*7c478bd9Sstevel@tonic-gate namep, size); 269*7c478bd9Sstevel@tonic-gate continue; 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate if (size != sizeof (vaddr)) { 272*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "device %s address prop too " 273*7c478bd9Sstevel@tonic-gate "big\n", namep); 274*7c478bd9Sstevel@tonic-gate continue; 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate if (GETPROP(curnode, OBP_ADDRESS, 277*7c478bd9Sstevel@tonic-gate (caddr_t)&vaddr) == -1) { 278*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "device %s not mapped\n", 279*7c478bd9Sstevel@tonic-gate namep); 280*7c478bd9Sstevel@tonic-gate continue; 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate /* make into a native pointer */ 284*7c478bd9Sstevel@tonic-gate *wkp->wk_vaddrp = (caddr_t)vaddr; 285*7c478bd9Sstevel@tonic-gate #ifdef VPRINTF 286*7c478bd9Sstevel@tonic-gate VPRINTF("fill_address: %s mapped to %x\n", namep, 287*7c478bd9Sstevel@tonic-gate *wkp->wk_vaddrp); 288*7c478bd9Sstevel@tonic-gate #endif /* VPRINTF */ 289*7c478bd9Sstevel@tonic-gate } 290*7c478bd9Sstevel@tonic-gate if (wkp->wk_func != NULL) 291*7c478bd9Sstevel@tonic-gate (*wkp->wk_func)(curnode); 292*7c478bd9Sstevel@tonic-gate /* 293*7c478bd9Sstevel@tonic-gate * If this one is optional and there may be more than 294*7c478bd9Sstevel@tonic-gate * one, don't set V_MAPPED, which would cause us to skip it 295*7c478bd9Sstevel@tonic-gate * next time around 296*7c478bd9Sstevel@tonic-gate */ 297*7c478bd9Sstevel@tonic-gate if (wkp->wk_flags != V_MULTI) 298*7c478bd9Sstevel@tonic-gate wkp->wk_flags = V_MAPPED; 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate void 303*7c478bd9Sstevel@tonic-gate fill_cpu(dnode_t node) 304*7c478bd9Sstevel@tonic-gate { 305*7c478bd9Sstevel@tonic-gate struct cpu_node *cpunode; 306*7c478bd9Sstevel@tonic-gate processorid_t cpuid; 307*7c478bd9Sstevel@tonic-gate uint_t clk_freq; 308*7c478bd9Sstevel@tonic-gate char namebuf[OBP_MAXPROPNAME], unum[UNUM_NAMLEN]; 309*7c478bd9Sstevel@tonic-gate char *namebufp; 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate if (GETPROP(node, "cpuid", (caddr_t)&cpuid) == -1) { 312*7c478bd9Sstevel@tonic-gate if (GETPROP(node, "reg", (caddr_t)&cpuid) == -1) 313*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "reg prop not found in cpu node"); 314*7c478bd9Sstevel@tonic-gate cpuid = PROM_CFGHDL_TO_CPUID(cpuid); 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate if (cpuid < 0 || cpuid >= NCPU) { 318*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "cpu (dnode %x): out of range cpuid %d - " 319*7c478bd9Sstevel@tonic-gate "cpu excluded from configuration\n", node, cpuid); 320*7c478bd9Sstevel@tonic-gate return; 321*7c478bd9Sstevel@tonic-gate } 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate cpunode = &cpunodes[cpuid]; 324*7c478bd9Sstevel@tonic-gate cpunode->cpuid = cpuid; 325*7c478bd9Sstevel@tonic-gate cpunode->device_id = cpuid; 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate unum[0] = '\0'; 328*7c478bd9Sstevel@tonic-gate (void) snprintf(cpunode->fru_fmri, sizeof (cpunode->fru_fmri), 329*7c478bd9Sstevel@tonic-gate "%s%s", CPU_FRU_FMRI, unum); 330*7c478bd9Sstevel@tonic-gate (void) GETPROP(node, "compatible", namebuf); 331*7c478bd9Sstevel@tonic-gate namebufp = namebuf; 332*7c478bd9Sstevel@tonic-gate if (strncmp(namebufp, "SUNW,", 5) == 0) 333*7c478bd9Sstevel@tonic-gate namebufp += 5; 334*7c478bd9Sstevel@tonic-gate (void) strcpy(cpunode->name, namebufp); 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate if (GETPROP(node, "clock-frequency", (caddr_t)&clk_freq) == -1) { 337*7c478bd9Sstevel@tonic-gate /* 338*7c478bd9Sstevel@tonic-gate * If we didn't find it in the CPU node, look in the root node. 339*7c478bd9Sstevel@tonic-gate */ 340*7c478bd9Sstevel@tonic-gate dnode_t root = prom_nextnode((dnode_t)0); 341*7c478bd9Sstevel@tonic-gate if (GETPROP(root, "clock-frequency", (caddr_t)&clk_freq) == -1) 342*7c478bd9Sstevel@tonic-gate clk_freq = 0; 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate cpunode->clock_freq = clk_freq; 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate ASSERT(cpunode->clock_freq != 0); 347*7c478bd9Sstevel@tonic-gate /* 348*7c478bd9Sstevel@tonic-gate * Compute scaling factor based on rate of %tick. This is used 349*7c478bd9Sstevel@tonic-gate * to convert from ticks derived from %tick to nanoseconds. See 350*7c478bd9Sstevel@tonic-gate * comment in sun4u/sys/clock.h for details. 351*7c478bd9Sstevel@tonic-gate */ 352*7c478bd9Sstevel@tonic-gate cpunode->tick_nsec_scale = (uint_t)(((uint64_t)NANOSEC << 353*7c478bd9Sstevel@tonic-gate (32 - TICK_NSEC_SHIFT)) / cpunode->clock_freq); 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate cpunode->nodeid = node; 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate /* 359*7c478bd9Sstevel@tonic-gate * Call cpu module specific code to fill in the cpu properities 360*7c478bd9Sstevel@tonic-gate */ 361*7c478bd9Sstevel@tonic-gate cpu_fiximp(cpunode); 362*7c478bd9Sstevel@tonic-gate } 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate #define IOMMU_PER_SCHIZO 2 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate /* 367*7c478bd9Sstevel@tonic-gate * The first psycho must always programmed up for the system clock and error 368*7c478bd9Sstevel@tonic-gate * handling purposes. 369*7c478bd9Sstevel@tonic-gate */ 370*7c478bd9Sstevel@tonic-gate static void 371*7c478bd9Sstevel@tonic-gate have_pci(dnode_t node) 372*7c478bd9Sstevel@tonic-gate { 373*7c478bd9Sstevel@tonic-gate int size; 374*7c478bd9Sstevel@tonic-gate uint_t portid; 375*7c478bd9Sstevel@tonic-gate char compatible[OBP_MAXDRVNAME]; 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate size = GETPROPLEN(node, "portid"); 378*7c478bd9Sstevel@tonic-gate if (size == -1) size = GETPROPLEN(node, "upa-portid"); 379*7c478bd9Sstevel@tonic-gate if (size == -1) 380*7c478bd9Sstevel@tonic-gate return; 381*7c478bd9Sstevel@tonic-gate if (size > sizeof (portid)) 382*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "portid size wrong"); 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate if (GETPROP(node, "portid", (caddr_t)&portid) == -1) 385*7c478bd9Sstevel@tonic-gate if (GETPROP(node, "upa-portid", (caddr_t)&portid) == -1) 386*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, "portid not found"); 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate niobus++; 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate /* 392*7c478bd9Sstevel@tonic-gate * Need two physical TSBs for Schizo-compatible nodes, 393*7c478bd9Sstevel@tonic-gate * one otherwise. 394*7c478bd9Sstevel@tonic-gate */ 395*7c478bd9Sstevel@tonic-gate compatible[0] = '\0'; 396*7c478bd9Sstevel@tonic-gate (void) prom_getprop(node, OBP_COMPATIBLE, compatible); 397*7c478bd9Sstevel@tonic-gate if (strcmp(compatible, "pci108e,8001") == 0) 398*7c478bd9Sstevel@tonic-gate niommu_tsbs += IOMMU_PER_SCHIZO; 399*7c478bd9Sstevel@tonic-gate else 400*7c478bd9Sstevel@tonic-gate niommu_tsbs++; 401*7c478bd9Sstevel@tonic-gate } 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate int 405*7c478bd9Sstevel@tonic-gate get_cpu_pagesizes(void) 406*7c478bd9Sstevel@tonic-gate { 407*7c478bd9Sstevel@tonic-gate /* 408*7c478bd9Sstevel@tonic-gate * XXXQ Get supported page sizes information from the PD 409*7c478bd9Sstevel@tonic-gate * and return a bit mask indicating which page sizes are 410*7c478bd9Sstevel@tonic-gate * supported. 411*7c478bd9Sstevel@tonic-gate * 412*7c478bd9Sstevel@tonic-gate * Return 0 when no information is available. 413*7c478bd9Sstevel@tonic-gate */ 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate return (0); /* XXXQ for now return 0 as no PD */ 416*7c478bd9Sstevel@tonic-gate } 417