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