1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/errno.h> 27 #include <sys/types.h> 28 #include <sys/param.h> 29 #include <sys/cpu.h> 30 #include <sys/cpuvar.h> 31 #include <sys/clock.h> 32 33 #include <sys/promif.h> 34 #include <sys/promimpl.h> 35 #include <sys/systm.h> 36 #include <sys/machsystm.h> 37 #include <sys/debug.h> 38 #include <sys/sunddi.h> 39 #include <sys/modctl.h> 40 #include <sys/spitregs.h> 41 #include <sys/cheetahregs.h> 42 #include <sys/cpu_module.h> 43 #include <sys/kobj.h> 44 #include <sys/cmp.h> 45 #include <sys/async.h> 46 #include <vm/page.h> 47 48 /* 49 * The OpenBoot Standalone Interface supplies the kernel with 50 * implementation dependent parameters through the devinfo/property mechanism 51 */ 52 typedef enum { XDRBOOL, XDRINT, XDRSTRING } xdrs; 53 54 /* 55 * structure describing properties that we are interested in querying the 56 * OBP for. 57 */ 58 struct getprop_info { 59 char *name; 60 xdrs type; 61 uint_t *var; 62 }; 63 64 /* 65 * structure used to convert between a string returned by the OBP & a type 66 * used within the kernel. We prefer to paramaterize rather than type. 67 */ 68 struct convert_info { 69 char *name; 70 uint_t var; 71 char *realname; 72 }; 73 74 /* 75 * structure describing nodes that we are interested in querying the OBP for 76 * properties. 77 */ 78 struct node_info { 79 char *name; 80 int size; 81 struct getprop_info *prop; 82 struct getprop_info *prop_end; 83 unsigned int *value; 84 }; 85 86 /* 87 * macro definitions for routines that form the OBP interface 88 */ 89 #define NEXT prom_nextnode 90 #define CHILD prom_childnode 91 #define GETPROP prom_getprop 92 #define GETPROPLEN prom_getproplen 93 94 95 /* 0=quiet; 1=verbose; 2=debug */ 96 int debug_fillsysinfo = 0; 97 #define VPRINTF if (debug_fillsysinfo) prom_printf 98 99 int ncpunode; 100 struct cpu_node cpunodes[NCPU]; 101 102 static void check_cpus_ver(void); 103 static void check_cpus_set(void); 104 static void fill_address(pnode_t, char *); 105 void fill_cpu(pnode_t); 106 void fill_cpu_ddi(dev_info_t *); 107 void empty_cpu(int); 108 void plat_fill_mc(pnode_t); 109 #pragma weak plat_fill_mc 110 111 uint64_t system_clock_freq; 112 113 /* 114 * list of well known devices that must be mapped, and the variables that 115 * contain their addresses. 116 */ 117 caddr_t v_auxio_addr = NULL; 118 caddr_t v_eeprom_addr = NULL; 119 caddr_t v_timecheck_addr = NULL; 120 caddr_t v_rtc_addr_reg = NULL; 121 volatile unsigned char *v_rtc_data_reg = NULL; 122 volatile uint8_t *v_pmc_addr_reg = NULL; 123 volatile uint8_t *v_pmc_data_reg = NULL; 124 125 int niobus = 0; 126 uint_t niommu_tsbs = 0; 127 128 /* 129 * Hardware watchdog support. 130 */ 131 #define CHOSEN_EEPROM "eeprom" 132 #define WATCHDOG_ENABLE "watchdog-enable" 133 static pnode_t chosen_eeprom; 134 135 /* 136 * Appropriate tod module will be dynamically selected while booting 137 * based on finding a device tree node with a "device_type" property value 138 * of "tod". If such a node describing tod is not found, for backward 139 * compatibility, a node with a "name" property value of "eeprom" and 140 * "model" property value of "mk48t59" will be used. Failing to find a 141 * node matching either of the above criteria will result in no tod module 142 * being selected; this will cause the boot process to halt. 143 */ 144 char *tod_module_name; 145 146 /* 147 * If this variable is non-zero, cpr should return "not supported" when 148 * it is queried even though it would normally be supported on this platform. 149 */ 150 int cpr_supported_override; 151 152 /* 153 * Some platforms may need to support CPR even in the absence of the 154 * energystar-v* property (Enchilada server, for example). If this 155 * variable is non-zero, cpr should proceed even in the absence 156 * of the energystar-v* property. 157 */ 158 int cpr_platform_enable = 0; 159 160 /* 161 * Some nodes have functions that need to be called when they're seen. 162 */ 163 static void have_sbus(pnode_t); 164 static void have_pci(pnode_t); 165 static void have_eeprom(pnode_t); 166 static void have_auxio(pnode_t); 167 static void have_rtc(pnode_t); 168 static void have_tod(pnode_t); 169 static void have_pmc(pnode_t); 170 171 static struct wkdevice { 172 char *wk_namep; 173 void (*wk_func)(pnode_t); 174 caddr_t *wk_vaddrp; 175 ushort_t wk_flags; 176 #define V_OPTIONAL 0x0000 177 #define V_MUSTHAVE 0x0001 178 #define V_MAPPED 0x0002 179 #define V_MULTI 0x0003 /* optional, may be more than one */ 180 } wkdevice[] = { 181 { "sbus", have_sbus, NULL, V_MULTI }, 182 { "pci", have_pci, NULL, V_MULTI }, 183 { "eeprom", have_eeprom, NULL, V_MULTI }, 184 { "auxio", have_auxio, NULL, V_OPTIONAL }, 185 { "rtc", have_rtc, NULL, V_OPTIONAL }, 186 { "pmc", have_pmc, NULL, V_OPTIONAL }, 187 { 0, }, 188 }; 189 190 static void map_wellknown(pnode_t); 191 192 void 193 map_wellknown_devices() 194 { 195 struct wkdevice *wkp; 196 phandle_t ieeprom; 197 pnode_t root; 198 uint_t stick_freq; 199 200 /* 201 * if there is a chosen eeprom, note it (for have_eeprom()) 202 */ 203 if (GETPROPLEN(prom_chosennode(), CHOSEN_EEPROM) == 204 sizeof (phandle_t) && 205 GETPROP(prom_chosennode(), CHOSEN_EEPROM, (caddr_t)&ieeprom) != -1) 206 chosen_eeprom = (pnode_t)prom_decode_int(ieeprom); 207 208 root = prom_nextnode((pnode_t)0); 209 /* 210 * Get System clock frequency from root node if it exists. 211 */ 212 if (GETPROP(root, "stick-frequency", (caddr_t)&stick_freq) != -1) 213 system_clock_freq = stick_freq; 214 215 map_wellknown(NEXT((pnode_t)0)); 216 217 /* 218 * See if it worked 219 */ 220 for (wkp = wkdevice; wkp->wk_namep; ++wkp) { 221 if (wkp->wk_flags == V_MUSTHAVE) { 222 cmn_err(CE_PANIC, "map_wellknown_devices: required " 223 "device %s not mapped", wkp->wk_namep); 224 } 225 } 226 227 /* 228 * all sun4u systems must have an IO bus, i.e. sbus or pcibus 229 */ 230 if (niobus == 0) 231 cmn_err(CE_PANIC, "map_wellknown_devices: no i/o bus node"); 232 233 check_cpus_ver(); 234 check_cpus_set(); 235 } 236 237 /* 238 * map_wellknown - map known devices & registers 239 */ 240 static void 241 map_wellknown(pnode_t curnode) 242 { 243 extern int status_okay(int, char *, int); 244 char tmp_name[MAXSYSNAME]; 245 int sok; 246 247 #ifdef VPRINTF 248 VPRINTF("map_wellknown(%x)\n", curnode); 249 #endif /* VPRINTF */ 250 251 for (curnode = CHILD(curnode); curnode; curnode = NEXT(curnode)) { 252 /* 253 * prune subtree if status property indicating not okay 254 */ 255 sok = status_okay((int)curnode, (char *)NULL, 0); 256 if (!sok) { 257 char devtype_buf[OBP_MAXPROPNAME]; 258 int size; 259 260 #ifdef VPRINTF 261 VPRINTF("map_wellknown: !okay status property\n"); 262 #endif /* VPRINTF */ 263 /* 264 * a status property indicating bad memory will be 265 * associated with a node which has a "device_type" 266 * property with a value of "memory-controller" 267 */ 268 if ((size = GETPROPLEN(curnode, 269 OBP_DEVICETYPE)) == -1) 270 continue; 271 if (size > OBP_MAXPROPNAME) { 272 cmn_err(CE_CONT, "node %x '%s' prop too " 273 "big\n", curnode, OBP_DEVICETYPE); 274 continue; 275 } 276 if (GETPROP(curnode, OBP_DEVICETYPE, 277 devtype_buf) == -1) { 278 cmn_err(CE_CONT, "node %x '%s' get failed\n", 279 curnode, OBP_DEVICETYPE); 280 continue; 281 } 282 if (strcmp(devtype_buf, "memory-controller") != 0) 283 continue; 284 /* 285 * ...else fall thru and process the node... 286 */ 287 } 288 bzero(tmp_name, MAXSYSNAME); 289 if (GETPROP(curnode, OBP_NAME, (caddr_t)tmp_name) != -1) 290 fill_address(curnode, tmp_name); 291 if (GETPROP(curnode, OBP_DEVICETYPE, tmp_name) != -1 && 292 strcmp(tmp_name, "cpu") == 0) { 293 fill_cpu(curnode); 294 } 295 if (strcmp(tmp_name, "tod") == 0) 296 have_tod(curnode); 297 if (sok && (strcmp(tmp_name, "memory-controller") == 0) && 298 (&plat_fill_mc != NULL)) 299 plat_fill_mc(curnode); 300 map_wellknown(curnode); 301 } 302 } 303 304 static void 305 fill_address(pnode_t curnode, char *namep) 306 { 307 struct wkdevice *wkp; 308 int size; 309 uint32_t vaddr; 310 311 for (wkp = wkdevice; wkp->wk_namep; ++wkp) { 312 if (strcmp(wkp->wk_namep, namep) != 0) 313 continue; 314 if (wkp->wk_flags == V_MAPPED) 315 return; 316 if (wkp->wk_vaddrp != NULL) { 317 if ((size = GETPROPLEN(curnode, OBP_ADDRESS)) == -1) { 318 cmn_err(CE_CONT, "device %s size %d\n", 319 namep, size); 320 continue; 321 } 322 if (size != sizeof (vaddr)) { 323 cmn_err(CE_CONT, "device %s address prop too " 324 "big\n", namep); 325 continue; 326 } 327 if (GETPROP(curnode, OBP_ADDRESS, 328 (caddr_t)&vaddr) == -1) { 329 cmn_err(CE_CONT, "device %s not mapped\n", 330 namep); 331 continue; 332 } 333 334 /* make into a native pointer */ 335 *wkp->wk_vaddrp = (caddr_t)(uintptr_t)vaddr; 336 #ifdef VPRINTF 337 VPRINTF("fill_address: %s mapped to %p\n", namep, 338 (void *)*wkp->wk_vaddrp); 339 #endif /* VPRINTF */ 340 } 341 if (wkp->wk_func != NULL) 342 (*wkp->wk_func)(curnode); 343 /* 344 * If this one is optional and there may be more than 345 * one, don't set V_MAPPED, which would cause us to skip it 346 * next time around 347 */ 348 if (wkp->wk_flags != V_MULTI) 349 wkp->wk_flags = V_MAPPED; 350 } 351 } 352 353 int 354 get_portid(pnode_t node, pnode_t *cmpp) 355 { 356 int portid; 357 int i; 358 char dev_type[OBP_MAXPROPNAME]; 359 pnode_t cpu_parent; 360 361 if (cmpp != NULL) 362 *cmpp = OBP_NONODE; 363 364 if (GETPROP(node, "portid", (caddr_t)&portid) != -1) 365 return (portid); 366 if (GETPROP(node, "upa-portid", (caddr_t)&portid) != -1) 367 return (portid); 368 if (GETPROP(node, "device_type", (caddr_t)&dev_type) == -1) 369 return (-1); 370 371 /* 372 * For a virtual cpu node that is a CMP core, the "portid" 373 * is in the parent node. 374 * For a virtual cpu node that is a CMT strand, the "portid" is 375 * in its grandparent node. 376 * So we iterate up as far as 2 levels to get the "portid". 377 */ 378 if (strcmp(dev_type, "cpu") == 0) { 379 cpu_parent = node = prom_parentnode(node); 380 for (i = 0; i < 2; i++) { 381 if (node == OBP_NONODE || node == OBP_BADNODE) 382 break; 383 if (GETPROP(node, "portid", (caddr_t)&portid) != -1) { 384 if (cmpp != NULL) 385 *cmpp = cpu_parent; 386 return (portid); 387 } 388 node = prom_parentnode(node); 389 } 390 } 391 392 return (-1); 393 } 394 395 /* 396 * Adjust page coloring variables based on the physical ecache setsize of 397 * the configured cpus: 398 * 399 * Set ecache_setsize to max ecache set size to be used by 400 * page_coloring_init() to determine the page colors to configure. 401 * The adjustment is unlikely to be necessary... For cheetah+ systems, 402 * ecache_setsize should already be set in cpu_fiximp() to the maximum 403 * possible ecache setsize of any supported cheetah+ cpus. The adjustment 404 * is for the off chance that a non-cheetah+ system may have heterogenous 405 * cpus. 406 * 407 * Set cpu_setsize to the actual cpu setsize if the setsize is homogenous 408 * across all cpus otherwise set it to -1 if heterogenous. 409 * 410 * Set cpu_page_colors to -1 to signify heterogeneity of ecache setsizes 411 * to the page_get routines. 412 */ 413 static void 414 adj_ecache_setsize(int ecsetsize) 415 { 416 if (ecsetsize > ecache_setsize) 417 ecache_setsize = ecsetsize; 418 419 switch (cpu_setsize) { 420 case -1: 421 break; 422 case 0: 423 cpu_setsize = ecsetsize; 424 break; 425 default: 426 /* set to -1 if hetergenous cpus */ 427 if (cpu_setsize != ecsetsize) { 428 if (do_pg_coloring) 429 cpu_page_colors = -1; 430 /* 431 * if page coloring disabled, cpu_page_colors should 432 * remain 0 to prevent page coloring processing. 433 */ 434 cpu_setsize = -1; 435 } 436 break; 437 } 438 } 439 440 void 441 fill_cpu(pnode_t node) 442 { 443 extern int cpu_get_cpu_unum(int, char *, int, int *); 444 struct cpu_node *cpunode; 445 processorid_t cpuid; 446 int portid; 447 int tlbsize; 448 int size; 449 uint_t clk_freq; 450 pnode_t cmpnode; 451 char namebuf[OBP_MAXPROPNAME], unum[UNUM_NAMLEN]; 452 char *namebufp; 453 int proplen; 454 455 if ((portid = get_portid(node, &cmpnode)) == -1) { 456 cmn_err(CE_PANIC, "portid not found"); 457 } 458 459 if (GETPROP(node, "cpuid", (caddr_t)&cpuid) == -1) { 460 cpuid = portid; 461 } 462 463 if (cpuid < 0 || cpuid >= NCPU) { 464 cmn_err(CE_PANIC, "cpu node %x: cpuid %d out of range", node, 465 cpuid); 466 return; 467 } 468 469 cpunode = &cpunodes[cpuid]; 470 cpunode->portid = portid; 471 cpunode->nodeid = node; 472 473 if (cpu_get_cpu_unum(cpuid, unum, UNUM_NAMLEN, &size) != 0) { 474 cpunode->fru_fmri[0] = '\0'; 475 } else { 476 (void) snprintf(cpunode->fru_fmri, sizeof (cpunode->fru_fmri), 477 "%s%s", CPU_FRU_FMRI, unum); 478 } 479 480 if (cmpnode) { 481 /* 482 * For the CMT case, the parent "core" node contains 483 * properties needed below, use it instead of the 484 * cpu node. 485 */ 486 if ((GETPROP(cmpnode, "device_type", namebuf) > 0) && 487 (strcmp(namebuf, "core") == 0)) { 488 node = cmpnode; 489 } 490 } 491 492 (void) GETPROP(node, (cmpnode ? "compatible" : "name"), namebuf); 493 494 /* Make sure CPU name is within boundary and NULL terminated */ 495 proplen = GETPROPLEN(node, (cmpnode ? "compatible" : "name")); 496 ASSERT(proplen > 0 && proplen <= OBP_MAXPROPNAME); 497 498 if (proplen >= OBP_MAXPROPNAME) 499 proplen = OBP_MAXPROPNAME - 1; 500 501 namebuf[proplen] = '\0'; 502 503 namebufp = namebuf; 504 if (strncmp(namebufp, "SUNW,", 5) == 0) 505 namebufp += 5; 506 else if (strncmp(namebufp, "FJSV,", 5) == 0) 507 namebufp += 5; 508 (void) strcpy(cpunode->name, namebufp); 509 510 (void) GETPROP(node, "implementation#", 511 (caddr_t)&cpunode->implementation); 512 (void) GETPROP(node, "mask#", (caddr_t)&cpunode->version); 513 514 if (IS_CHEETAH(cpunode->implementation)) { 515 /* remap mask reg */ 516 cpunode->version = REMAP_CHEETAH_MASK(cpunode->version); 517 } 518 if (GETPROP(node, "clock-frequency", (caddr_t)&clk_freq) == -1) { 519 /* 520 * If we didn't find it in the CPU node, look in the root node. 521 */ 522 pnode_t root = prom_nextnode((pnode_t)0); 523 if (GETPROP(root, "clock-frequency", (caddr_t)&clk_freq) == -1) 524 clk_freq = 0; 525 } 526 cpunode->clock_freq = clk_freq; 527 528 ASSERT(cpunode->clock_freq != 0); 529 /* 530 * Compute scaling factor based on rate of %tick. This is used 531 * to convert from ticks derived from %tick to nanoseconds. See 532 * comment in sun4u/sys/clock.h for details. 533 */ 534 cpunode->tick_nsec_scale = (uint_t)(((uint64_t)NANOSEC << 535 (32 - TICK_NSEC_SHIFT)) / cpunode->clock_freq); 536 537 (void) GETPROP(node, "#itlb-entries", (caddr_t)&tlbsize); 538 ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ 539 cpunode->itlb_size = (ushort_t)tlbsize; 540 541 (void) GETPROP(node, "#dtlb-entries", (caddr_t)&tlbsize); 542 ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ 543 cpunode->dtlb_size = (ushort_t)tlbsize; 544 545 if (cmpnode != OBP_NONODE) { 546 /* 547 * If the CPU has a level 3 cache, then it will be the 548 * external cache. Otherwise the level 2 cache is the 549 * external cache. 550 */ 551 size = 0; 552 (void) GETPROP(node, "l3-cache-size", (caddr_t)&size); 553 if (size <= 0) 554 (void) GETPROP(node, "l2-cache-size", (caddr_t)&size); 555 ASSERT(size != 0); 556 cpunode->ecache_size = size; 557 558 size = 0; 559 (void) GETPROP(node, "l3-cache-line-size", (caddr_t)&size); 560 if (size <= 0) 561 (void) GETPROP(node, "l2-cache-line-size", 562 (caddr_t)&size); 563 ASSERT(size != 0); 564 cpunode->ecache_linesize = size; 565 566 size = 0; 567 (void) GETPROP(node, "l2-cache-associativity", (caddr_t)&size); 568 ASSERT(size != 0); 569 cpunode->ecache_associativity = size; 570 571 cmp_add_cpu(portid, cpuid); 572 } else { 573 size = 0; 574 (void) GETPROP(node, "ecache-size", (caddr_t)&size); 575 ASSERT(size != 0); 576 cpunode->ecache_size = size; 577 578 size = 0; 579 (void) GETPROP(node, "ecache-line-size", (caddr_t)&size); 580 ASSERT(size != 0); 581 cpunode->ecache_linesize = size; 582 583 size = 0; 584 (void) GETPROP(node, "ecache-associativity", (caddr_t)&size); 585 ASSERT(size != 0); 586 cpunode->ecache_associativity = size; 587 } 588 589 /* by default set msram to non-mirrored one */ 590 cpunode->msram = ECACHE_CPU_NON_MIRROR; 591 592 if (GETPROPLEN(node, "msram") != -1) { 593 cpunode->msram = ECACHE_CPU_MIRROR; 594 } 595 596 if (GETPROPLEN(node, "msram-observed") != -1) { 597 cpunode->msram = ECACHE_CPU_MIRROR; 598 } 599 600 if (ncpunode == 0) { 601 cpu_fiximp(node); 602 } 603 604 cpunode->ecache_setsize = 605 cpunode->ecache_size / cpunode->ecache_associativity; 606 607 adj_ecache_setsize(cpunode->ecache_setsize); 608 609 ncpunode++; 610 } 611 612 int 613 get_portid_ddi(dev_info_t *dip, dev_info_t **cmpp) 614 { 615 int portid; 616 int i; 617 char dev_type[OBP_MAXPROPNAME]; 618 int len = OBP_MAXPROPNAME; 619 dev_info_t *cpu_parent; 620 621 if (cmpp != NULL) 622 *cmpp = NULL; 623 624 if ((portid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 625 DDI_PROP_DONTPASS, "portid", -1)) != -1) 626 return (portid); 627 if ((portid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 628 DDI_PROP_DONTPASS, "upa-portid", -1)) != -1) 629 return (portid); 630 if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 631 DDI_PROP_DONTPASS, "device_type", (caddr_t)dev_type, 632 &len) != 0) 633 return (-1); 634 635 /* 636 * For a virtual cpu node that is a CMP core, the "portid" 637 * is in the parent node. 638 * For a virtual cpu node that is a CMT strand, the "portid" is 639 * in its grandparent node. 640 * So we iterate up as far as 2 levels to get the "portid". 641 */ 642 if (strcmp(dev_type, "cpu") == 0) { 643 cpu_parent = dip = ddi_get_parent(dip); 644 for (i = 0; dip != NULL && i < 2; i++) { 645 if ((portid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 646 DDI_PROP_DONTPASS, "portid", -1)) != -1) { 647 if (cmpp != NULL) 648 *cmpp = cpu_parent; 649 return (portid); 650 } 651 dip = ddi_get_parent(dip); 652 } 653 } 654 655 return (-1); 656 } 657 658 /* 659 * A hotplug version of fill_cpu(). (Doesn't assume that there's a node 660 * in the PROM device tree for this CPU.) We still need the PROM version 661 * since it is called very early in the boot cycle before (before 662 * setup_ddi()). Sigh...someday this will all be cleaned up. 663 */ 664 void 665 fill_cpu_ddi(dev_info_t *dip) 666 { 667 extern int cpu_get_cpu_unum(int, char *, int, int *); 668 struct cpu_node *cpunode; 669 processorid_t cpuid; 670 int portid; 671 int len = OBP_MAXPROPNAME; 672 int tlbsize; 673 dev_info_t *cmpnode; 674 char namebuf[OBP_MAXPROPNAME], unum[UNUM_NAMLEN]; 675 char *namebufp; 676 char dev_type[OBP_MAXPROPNAME]; 677 678 if ((portid = get_portid_ddi(dip, &cmpnode)) == -1) { 679 cmn_err(CE_PANIC, "portid not found"); 680 } 681 682 if ((cpuid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 683 DDI_PROP_DONTPASS, "cpuid", -1)) == -1) { 684 cpuid = portid; 685 } 686 687 if (cpuid < 0 || cpuid >= NCPU) { 688 cmn_err(CE_PANIC, "cpu dip %p: cpuid %d out of range", 689 (void *)dip, cpuid); 690 return; 691 } 692 693 cpunode = &cpunodes[cpuid]; 694 cpunode->portid = portid; 695 cpunode->nodeid = ddi_get_nodeid(dip); 696 697 if (cmpnode != NULL) { 698 /* 699 * For the CMT case, the parent "core" node contains 700 * properties needed below, use it instead of the 701 * cpu node. 702 */ 703 if ((ddi_prop_op(DDI_DEV_T_ANY, cmpnode, PROP_LEN_AND_VAL_BUF, 704 DDI_PROP_DONTPASS, "device_type", 705 (caddr_t)dev_type, &len) == DDI_PROP_SUCCESS) && 706 (strcmp(dev_type, "core") == 0)) 707 dip = cmpnode; 708 } 709 710 if (cpu_get_cpu_unum(cpuid, unum, UNUM_NAMLEN, &len) != 0) { 711 cpunode->fru_fmri[0] = '\0'; 712 } else { 713 (void) snprintf(cpunode->fru_fmri, sizeof (cpunode->fru_fmri), 714 "%s%s", CPU_FRU_FMRI, unum); 715 } 716 717 len = sizeof (namebuf); 718 (void) ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 719 DDI_PROP_DONTPASS, (cmpnode ? "compatible" : "name"), 720 (caddr_t)namebuf, &len); 721 722 namebufp = namebuf; 723 if (strncmp(namebufp, "SUNW,", 5) == 0) 724 namebufp += 5; 725 else if (strncmp(namebufp, "FJSV,", 5) == 0) 726 namebufp += 5; 727 (void) strcpy(cpunode->name, namebufp); 728 729 cpunode->implementation = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 730 DDI_PROP_DONTPASS, "implementation#", 0); 731 732 cpunode->version = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 733 DDI_PROP_DONTPASS, "mask#", 0); 734 735 if (IS_CHEETAH(cpunode->implementation)) { 736 /* remap mask reg */ 737 cpunode->version = REMAP_CHEETAH_MASK(cpunode->version); 738 } 739 740 cpunode->clock_freq = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip, 741 DDI_PROP_DONTPASS, "clock-frequency", 0); 742 743 ASSERT(cpunode->clock_freq != 0); 744 /* 745 * Compute scaling factor based on rate of %tick. This is used 746 * to convert from ticks derived from %tick to nanoseconds. See 747 * comment in sun4u/sys/clock.h for details. 748 */ 749 cpunode->tick_nsec_scale = (uint_t)(((uint64_t)NANOSEC << 750 (32 - TICK_NSEC_SHIFT)) / cpunode->clock_freq); 751 752 tlbsize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 753 DDI_PROP_DONTPASS, "#itlb-entries", 0); 754 ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ 755 cpunode->itlb_size = (ushort_t)tlbsize; 756 757 tlbsize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 758 DDI_PROP_DONTPASS, "#dtlb-entries", 0); 759 ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ 760 cpunode->dtlb_size = (ushort_t)tlbsize; 761 762 if (cmpnode != NULL) { 763 /* 764 * If the CPU has a level 3 cache, then that is it's 765 * external cache. Otherwise the external cache must 766 * be the level 2 cache. 767 */ 768 cpunode->ecache_size = ddi_prop_get_int(DDI_DEV_T_ANY, 769 dip, DDI_PROP_DONTPASS, "l3-cache-size", 0); 770 if (cpunode->ecache_size == 0) 771 cpunode->ecache_size = ddi_prop_get_int(DDI_DEV_T_ANY, 772 dip, DDI_PROP_DONTPASS, "l2-cache-size", 0); 773 ASSERT(cpunode->ecache_size != 0); 774 775 cpunode->ecache_linesize = ddi_prop_get_int(DDI_DEV_T_ANY, 776 dip, DDI_PROP_DONTPASS, "l3-cache-line-size", 0); 777 if (cpunode->ecache_linesize == 0) 778 cpunode->ecache_linesize = 779 ddi_prop_get_int(DDI_DEV_T_ANY, dip, 780 DDI_PROP_DONTPASS, "l2-cache-line-size", 0); 781 ASSERT(cpunode->ecache_linesize != 0); 782 783 cpunode->ecache_associativity = ddi_prop_get_int(DDI_DEV_T_ANY, 784 dip, DDI_PROP_DONTPASS, "l2-cache-associativity", 0); 785 ASSERT(cpunode->ecache_associativity != 0); 786 787 cmp_add_cpu(portid, cpuid); 788 } else { 789 cpunode->ecache_size = ddi_prop_get_int(DDI_DEV_T_ANY, 790 dip, DDI_PROP_DONTPASS, "ecache-size", 0); 791 ASSERT(cpunode->ecache_size != 0); 792 793 cpunode->ecache_linesize = ddi_prop_get_int(DDI_DEV_T_ANY, 794 dip, DDI_PROP_DONTPASS, "ecache-line-size", 0); 795 ASSERT(cpunode->ecache_linesize != 0); 796 797 cpunode->ecache_associativity = ddi_prop_get_int(DDI_DEV_T_ANY, 798 dip, DDI_PROP_DONTPASS, "ecache-associativity", 0); 799 ASSERT(cpunode->ecache_associativity != 0); 800 } 801 802 /* by default set msram to non-mirrored one */ 803 cpunode->msram = ECACHE_CPU_NON_MIRROR; 804 805 if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "msram")) { 806 cpunode->msram = ECACHE_CPU_MIRROR; 807 } else if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 808 "msram-observed")) { 809 cpunode->msram = ECACHE_CPU_MIRROR; 810 } 811 812 ASSERT(ncpunode > 0); /* fiximp not req'd */ 813 814 cpunode->ecache_setsize = 815 cpunode->ecache_size / cpunode->ecache_associativity; 816 817 adj_ecache_setsize(cpunode->ecache_setsize); 818 819 ncpunode++; 820 } 821 822 void 823 empty_cpu(int cpuid) 824 { 825 bzero(&cpunodes[cpuid], sizeof (struct cpu_node)); 826 ncpunode--; 827 } 828 829 #ifdef SF_ERRATA_30 /* call causes fp-disabled */ 830 int spitfire_call_bug = 0; 831 #endif 832 #ifdef SF_V9_TABLE_28 /* fp over/underflow traps may cause wrong fsr.cexc */ 833 int spitfire_bb_fsr_bug = 0; 834 #endif 835 836 #ifdef JALAPENO_ERRATA_85 837 /* 838 * Set the values here assuming we're running 2.4 or later Jalapenos. If 839 * not, they'll be reset below. Either way, the default can be overridden 840 * when we read /etc/system later in boot. 841 */ 842 int jp_errata_85_allow_slow_scrub = 1; 843 int jp_errata_85_enable = 0; 844 #endif /* JALAPENO_ERRATA_85 */ 845 846 static void 847 check_cpus_ver(void) 848 { 849 int i; 850 int impl, cpuid = getprocessorid(); 851 int min_supported_rev; 852 853 ASSERT(cpunodes[cpuid].nodeid != 0); 854 855 impl = cpunodes[cpuid].implementation; 856 switch (impl) { 857 default: 858 min_supported_rev = 0; 859 break; 860 case SPITFIRE_IMPL: 861 min_supported_rev = SPITFIRE_MINREV_SUPPORTED; 862 break; 863 case CHEETAH_IMPL: 864 min_supported_rev = CHEETAH_MINREV_SUPPORTED; 865 break; 866 } 867 868 for (i = 0; i < NCPU; i++) { 869 if (cpunodes[i].nodeid == 0) 870 continue; 871 872 if (IS_SPITFIRE(impl)) { 873 if (cpunodes[i].version < min_supported_rev) { 874 cmn_err(CE_PANIC, "UltraSPARC versions older " 875 "than %d.%d are no longer supported " 876 "(cpu #%d)", 877 SPITFIRE_MAJOR_VERSION(min_supported_rev), 878 SPITFIRE_MINOR_VERSION(min_supported_rev), 879 i); 880 } 881 882 /* 883 * Min supported rev is 2.1 but we've seen problems 884 * with that so we still want to warn if we see one. 885 */ 886 if (cpunodes[i].version < 0x22) { 887 cmn_err(CE_WARN, 888 "UltraSPARC versions older than " 889 "2.2 are not supported (cpu #%d)", i); 890 #ifdef SF_ERRATA_30 /* call causes fp-disabled */ 891 spitfire_call_bug = 1; 892 #endif /* SF_ERRATA_30 */ 893 } 894 } 895 896 897 #ifdef SF_V9_TABLE_28 /* fp over/underflow traps may cause wrong fsr.cexc */ 898 if (IS_SPITFIRE(impl) || IS_BLACKBIRD(impl)) 899 spitfire_bb_fsr_bug = 1; 900 #endif /* SF_V9_TABLE_28 */ 901 902 if (IS_CHEETAH(impl)) { 903 if (cpunodes[i].version < min_supported_rev) { 904 cmn_err(CE_PANIC, "UltraSPARC-III versions " 905 "older than %d.%d are no longer supported " 906 "(cpu #%d)", 907 CHEETAH_MAJOR_VERSION(min_supported_rev), 908 CHEETAH_MINOR_VERSION(min_supported_rev), 909 i); 910 } 911 912 } 913 914 #ifdef JALAPENO_ERRATA_85 915 if (IS_JALAPENO(impl) && (cpunodes[i].version < 0x24)) { 916 jp_errata_85_allow_slow_scrub = 0; 917 jp_errata_85_enable = 1; 918 } 919 #endif /* JALAPENO_ERRATA_85 */ 920 } 921 } 922 923 /* 924 * Check for a legal set of CPUs. 925 */ 926 static void 927 check_cpus_set(void) 928 { 929 int i; 930 int impl; 931 int npanther = 0; 932 int njupiter = 0; 933 934 impl = cpunodes[getprocessorid()].implementation; 935 936 switch (impl) { 937 case CHEETAH_PLUS_IMPL: 938 case JAGUAR_IMPL: 939 case PANTHER_IMPL: 940 /* 941 * Check for a legal heterogeneous set of CPUs. 942 */ 943 for (i = 0; i < NCPU; i++) { 944 if (cpunodes[i].nodeid == 0) 945 continue; 946 947 if (IS_PANTHER(cpunodes[i].implementation)) { 948 npanther += 1; 949 } 950 951 if (!(IS_CHEETAH_PLUS(cpunodes[i].implementation) || 952 IS_JAGUAR(cpunodes[i].implementation) || 953 IS_PANTHER(cpunodes[i].implementation))) { 954 use_mp = 0; 955 break; 956 } 957 } 958 break; 959 case OLYMPUS_C_IMPL: 960 case JUPITER_IMPL: 961 /* 962 * Check for a legal heterogeneous set of CPUs on the 963 * OPL platform. 964 */ 965 for (i = 0; i < NCPU; i++) { 966 if (cpunodes[i].nodeid == 0) 967 continue; 968 969 if (IS_JUPITER(cpunodes[i].implementation)) { 970 njupiter += 1; 971 } 972 if (!(IS_OLYMPUS_C(cpunodes[i].implementation) || 973 IS_JUPITER(cpunodes[i].implementation))) { 974 use_mp = 0; 975 break; 976 } 977 } 978 break; 979 default: 980 /* 981 * Check for a homogeneous set of CPUs. 982 */ 983 for (i = 0; i < NCPU; i++) { 984 if (cpunodes[i].nodeid == 0) 985 continue; 986 987 if (cpunodes[i].implementation != impl) { 988 use_mp = 0; 989 break; 990 } 991 } 992 break; 993 } 994 995 /* 996 * Change from mmu_page_sizes from 4 to 6 for totally-Panther domains, 997 * where npanther == ncpunode. Also, set ecache_alignsize (and a few 998 * other globals) to the correct value for totally-Panther domains. 999 */ 1000 if (&mmu_init_mmu_page_sizes) { 1001 (void) mmu_init_mmu_page_sizes(npanther); 1002 } 1003 if ((npanther == ncpunode) && (&cpu_fix_allpanther)) { 1004 cpu_fix_allpanther(); 1005 } 1006 1007 /* 1008 * For all-Jupiter domains the cpu module will update the hwcap features 1009 * for integer multiply-add instruction support. 1010 */ 1011 if ((njupiter == ncpunode) && (&cpu_fix_alljupiter)) { 1012 cpu_fix_alljupiter(); 1013 } 1014 1015 /* 1016 * Set max cpus we can have based on ncpunode and use_mp 1017 */ 1018 if (use_mp) { 1019 int (*set_max_ncpus)(void); 1020 1021 set_max_ncpus = (int (*)(void)) 1022 kobj_getsymvalue("set_platform_max_ncpus", 0); 1023 1024 if (set_max_ncpus) { 1025 max_ncpus = set_max_ncpus(); 1026 if (max_ncpus < ncpunode) 1027 max_ncpus = ncpunode; 1028 boot_ncpus = boot_max_ncpus = ncpunode; 1029 } else { 1030 max_ncpus = ncpunode; 1031 } 1032 } else { 1033 cmn_err(CE_NOTE, "MP not supported on mismatched modules," 1034 " booting UP only"); 1035 1036 for (i = 0; i < NCPU; i++) { 1037 if (cpunodes[i].nodeid == 0) 1038 continue; 1039 1040 cmn_err(CE_NOTE, "cpu%d: %s version 0x%x", i, 1041 cpunodes[i].name, cpunodes[i].version); 1042 } 1043 1044 max_ncpus = 1; 1045 } 1046 } 1047 1048 /* 1049 * The first sysio must always programmed up for the system clock and error 1050 * handling purposes, referenced by v_sysio_addr in machdep.c. 1051 */ 1052 static void 1053 have_sbus(pnode_t node) 1054 { 1055 int size; 1056 uint_t portid; 1057 1058 size = GETPROPLEN(node, "upa-portid"); 1059 if (size == -1 || size > sizeof (portid)) 1060 cmn_err(CE_PANIC, "upa-portid size"); 1061 if (GETPROP(node, "upa-portid", (caddr_t)&portid) == -1) 1062 cmn_err(CE_PANIC, "upa-portid"); 1063 1064 niobus++; 1065 1066 /* 1067 * need one physical TSB 1068 */ 1069 niommu_tsbs++; 1070 } 1071 1072 1073 #define IOMMU_PER_SCHIZO 2 1074 1075 /* 1076 * The first psycho must always programmed up for the system clock and error 1077 * handling purposes. 1078 */ 1079 static void 1080 have_pci(pnode_t node) 1081 { 1082 int size; 1083 uint_t portid; 1084 char compatible[OBP_MAXDRVNAME]; 1085 1086 size = GETPROPLEN(node, "portid"); 1087 if (size == -1) size = GETPROPLEN(node, "upa-portid"); 1088 if (size == -1) 1089 return; 1090 if (size > sizeof (portid)) 1091 cmn_err(CE_PANIC, "portid size wrong"); 1092 1093 if (GETPROP(node, "portid", (caddr_t)&portid) == -1) 1094 if (GETPROP(node, "upa-portid", (caddr_t)&portid) == -1) 1095 cmn_err(CE_PANIC, "portid not found"); 1096 1097 niobus++; 1098 1099 1100 /* 1101 * Need two physical TSBs for Schizo compatible nodes, 1102 * one otherwise. 1103 */ 1104 compatible[0] = '\0'; 1105 (void) prom_getprop(node, OBP_COMPATIBLE, compatible); 1106 if (strcmp(compatible, "pci108e,8001") == 0) 1107 niommu_tsbs += IOMMU_PER_SCHIZO; 1108 else 1109 niommu_tsbs++; 1110 } 1111 1112 /* 1113 * The first eeprom is used as the TOD clock, referenced 1114 * by v_eeprom_addr in locore.s. 1115 */ 1116 static void 1117 have_eeprom(pnode_t node) 1118 { 1119 int size; 1120 uint32_t eaddr; 1121 1122 /* 1123 * "todmostek" module will be selected based on finding a "model" 1124 * property value of "mk48t59" in the "eeprom" node. 1125 */ 1126 if (tod_module_name == NULL) { 1127 char buf[MAXSYSNAME]; 1128 1129 if ((GETPROP(node, "model", buf) != -1) && 1130 (strcmp(buf, "mk48t59") == 0)) 1131 tod_module_name = "todmostek"; 1132 } 1133 1134 /* 1135 * If we have found two distinct eeprom's, then we're done. 1136 */ 1137 if (v_eeprom_addr && v_timecheck_addr != v_eeprom_addr) 1138 return; 1139 1140 /* 1141 * multiple eeproms may exist but at least 1142 * one must have an "address" property 1143 */ 1144 if ((size = GETPROPLEN(node, OBP_ADDRESS)) == -1) 1145 return; 1146 if (size != sizeof (eaddr)) 1147 cmn_err(CE_PANIC, "eeprom addr size"); 1148 if (GETPROP(node, OBP_ADDRESS, (caddr_t)&eaddr) == -1) 1149 cmn_err(CE_PANIC, "eeprom addr"); 1150 1151 /* 1152 * If we have a chosen eeprom and it is not this node, keep looking. 1153 */ 1154 if (chosen_eeprom != NULL && chosen_eeprom != node) { 1155 v_timecheck_addr = (caddr_t)(uintptr_t)eaddr; 1156 return; 1157 } 1158 1159 v_eeprom_addr = (caddr_t)(uintptr_t)eaddr; 1160 1161 /* 1162 * If we don't find an I/O board to use to check the clock, 1163 * we'll fall back on whichever TOD is available. 1164 */ 1165 if (v_timecheck_addr == NULL) 1166 v_timecheck_addr = v_eeprom_addr; 1167 1168 /* 1169 * Does this eeprom have watchdog support? 1170 */ 1171 if (GETPROPLEN(node, WATCHDOG_ENABLE) != -1) 1172 watchdog_available = 1; 1173 } 1174 1175 static void 1176 have_rtc(pnode_t node) 1177 { 1178 int size; 1179 uint32_t eaddr; 1180 1181 /* 1182 * "ds1287" module will be selected based on finding a "model" 1183 * property value of "ds1287" in the "rtc" node. 1184 */ 1185 if (tod_module_name == NULL) { 1186 char buf[MAXSYSNAME]; 1187 1188 if (GETPROP(node, "model", buf) != -1) { 1189 if ((strcmp(buf, "m5819p") == 0) || 1190 (strcmp(buf, "m5823") == 0)) 1191 tod_module_name = "todm5823"; 1192 else if (strcmp(buf, "ds1287") == 0) 1193 tod_module_name = "todds1287"; 1194 } 1195 } 1196 1197 /* 1198 * XXX - drives on if address prop doesn't exist, later falls 1199 * over in tod module 1200 */ 1201 if ((size = GETPROPLEN(node, OBP_ADDRESS)) == -1) 1202 return; 1203 if (size != sizeof (eaddr)) 1204 cmn_err(CE_PANIC, "rtc addr size"); 1205 if (GETPROP(node, OBP_ADDRESS, (caddr_t)&eaddr) == -1) 1206 cmn_err(CE_PANIC, "rtc addr"); 1207 1208 v_rtc_addr_reg = (caddr_t)(uintptr_t)eaddr; 1209 v_rtc_data_reg = (volatile unsigned char *)(uintptr_t)eaddr + 1; 1210 1211 /* 1212 * Does this rtc have watchdog support? 1213 */ 1214 if (GETPROPLEN(node, WATCHDOG_ENABLE) != -1) 1215 watchdog_available = 1; 1216 } 1217 1218 static void 1219 have_pmc(pnode_t node) 1220 { 1221 uint32_t vaddr; 1222 pnode_t root; 1223 1224 /* 1225 * Watchdog property is in the root node. 1226 */ 1227 root = prom_nextnode((pnode_t)0); 1228 if (GETPROPLEN(root, WATCHDOG_ENABLE) != -1) { 1229 /* 1230 * The hardware watchdog timer resides within logical 1231 * unit 8 of SuperI/O. The address property of the node 1232 * contains the virtual address that we use to program 1233 * the timer. 1234 */ 1235 if (GETPROP(node, OBP_ADDRESS, (caddr_t)&vaddr) == -1) { 1236 watchdog_available = 0; 1237 return; 1238 } 1239 v_pmc_addr_reg = (volatile uint8_t *)(uintptr_t)vaddr; 1240 v_pmc_data_reg = (volatile uint8_t *)(uintptr_t)vaddr + 1; 1241 watchdog_available = 1; 1242 } 1243 } 1244 1245 static void 1246 have_auxio(pnode_t node) 1247 { 1248 size_t size, n; 1249 uint32_t addr[5]; 1250 1251 /* 1252 * Get the size of the auzio's address property. 1253 * On some platforms, the address property contains one 1254 * entry and on others it contains five entries. 1255 * In all cases, the first entries are compatible. 1256 * 1257 * This routine gets the address property for the auxio 1258 * node and stores the first entry in v_auxio_addr which 1259 * is used by the routine set_auxioreg in sun4u/ml/locore.s. 1260 */ 1261 if ((size = GETPROPLEN(node, OBP_ADDRESS)) == -1) 1262 cmn_err(CE_PANIC, "no auxio address property"); 1263 1264 switch (n = (size / sizeof (addr[0]))) { 1265 case 1: 1266 break; 1267 case 5: 1268 break; 1269 default: 1270 cmn_err(CE_PANIC, "auxio addr has %lu entries?", n); 1271 } 1272 1273 if (GETPROP(node, OBP_ADDRESS, (caddr_t)addr) == -1) 1274 cmn_err(CE_PANIC, "auxio addr"); 1275 1276 v_auxio_addr = (caddr_t)(uintptr_t)(addr[0]); /* make into pointer */ 1277 } 1278 1279 static void 1280 have_tod(pnode_t node) 1281 { 1282 static char tod_name[MAXSYSNAME]; 1283 1284 if (GETPROP(node, OBP_NAME, (caddr_t)tod_name) == -1) 1285 cmn_err(CE_PANIC, "tod name"); 1286 /* 1287 * This is a node with "device_type" property value of "tod". 1288 * Name of the tod module is the name from the node. 1289 */ 1290 tod_module_name = tod_name; 1291 } 1292