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 2006 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 456 if ((portid = get_portid(node, &cmpnode)) == -1) { 457 cmn_err(CE_PANIC, "portid not found"); 458 } 459 460 if (GETPROP(node, "cpuid", (caddr_t)&cpuid) == -1) { 461 cpuid = portid; 462 } 463 464 if (cpuid < 0 || cpuid >= NCPU) { 465 cmn_err(CE_PANIC, "cpu node %x: cpuid %d out of range", 466 node, cpuid); 467 return; 468 } 469 470 cpunode = &cpunodes[cpuid]; 471 cpunode->portid = portid; 472 cpunode->nodeid = node; 473 474 if (cpu_get_cpu_unum(cpuid, unum, UNUM_NAMLEN, &size) != 0) { 475 cpunode->fru_fmri[0] = '\0'; 476 } else { 477 (void) snprintf(cpunode->fru_fmri, sizeof (cpunode->fru_fmri), 478 "%s%s", CPU_FRU_FMRI, unum); 479 } 480 481 if (cmpnode) { 482 /* 483 * For the CMT case, the parent "core" node contains 484 * properties needed below, use it instead of the 485 * cpu node. 486 */ 487 if ((GETPROP(cmpnode, "device_type", namebuf) > 0) && 488 (strcmp(namebuf, "core") == 0)) { 489 node = cmpnode; 490 } 491 } 492 493 (void) GETPROP(node, (cmpnode ? "compatible" : "name"), namebuf); 494 namebufp = namebuf; 495 if (strncmp(namebufp, "SUNW,", 5) == 0) 496 namebufp += 5; 497 else if (strncmp(namebufp, "FJSV,", 5) == 0) 498 namebufp += 5; 499 (void) strcpy(cpunode->name, namebufp); 500 501 (void) GETPROP(node, "implementation#", 502 (caddr_t)&cpunode->implementation); 503 (void) GETPROP(node, "mask#", (caddr_t)&cpunode->version); 504 505 if (IS_CHEETAH(cpunode->implementation)) { 506 /* remap mask reg */ 507 cpunode->version = REMAP_CHEETAH_MASK(cpunode->version); 508 } 509 if (GETPROP(node, "clock-frequency", (caddr_t)&clk_freq) == -1) { 510 /* 511 * If we didn't find it in the CPU node, look in the root node. 512 */ 513 pnode_t root = prom_nextnode((pnode_t)0); 514 if (GETPROP(root, "clock-frequency", (caddr_t)&clk_freq) == -1) 515 clk_freq = 0; 516 } 517 cpunode->clock_freq = clk_freq; 518 519 ASSERT(cpunode->clock_freq != 0); 520 /* 521 * Compute scaling factor based on rate of %tick. This is used 522 * to convert from ticks derived from %tick to nanoseconds. See 523 * comment in sun4u/sys/clock.h for details. 524 */ 525 cpunode->tick_nsec_scale = (uint_t)(((uint64_t)NANOSEC << 526 (32 - TICK_NSEC_SHIFT)) / cpunode->clock_freq); 527 528 (void) GETPROP(node, "#itlb-entries", (caddr_t)&tlbsize); 529 ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ 530 cpunode->itlb_size = (ushort_t)tlbsize; 531 532 (void) GETPROP(node, "#dtlb-entries", (caddr_t)&tlbsize); 533 ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ 534 cpunode->dtlb_size = (ushort_t)tlbsize; 535 536 if (cmpnode != OBP_NONODE) { 537 /* 538 * If the CPU has a level 3 cache, then it will be the 539 * external cache. Otherwise the level 2 cache is the 540 * external cache. 541 */ 542 size = 0; 543 (void) GETPROP(node, "l3-cache-size", (caddr_t)&size); 544 if (size <= 0) 545 (void) GETPROP(node, "l2-cache-size", (caddr_t)&size); 546 ASSERT(size != 0); 547 cpunode->ecache_size = size; 548 549 size = 0; 550 (void) GETPROP(node, "l3-cache-line-size", (caddr_t)&size); 551 if (size <= 0) 552 (void) GETPROP(node, "l2-cache-line-size", 553 (caddr_t)&size); 554 ASSERT(size != 0); 555 cpunode->ecache_linesize = size; 556 557 size = 0; 558 (void) GETPROP(node, "l2-cache-associativity", (caddr_t)&size); 559 ASSERT(size != 0); 560 cpunode->ecache_associativity = size; 561 562 cmp_add_cpu(portid, cpuid); 563 } else { 564 size = 0; 565 (void) GETPROP(node, "ecache-size", (caddr_t)&size); 566 ASSERT(size != 0); 567 cpunode->ecache_size = size; 568 569 size = 0; 570 (void) GETPROP(node, "ecache-line-size", (caddr_t)&size); 571 ASSERT(size != 0); 572 cpunode->ecache_linesize = size; 573 574 size = 0; 575 (void) GETPROP(node, "ecache-associativity", (caddr_t)&size); 576 ASSERT(size != 0); 577 cpunode->ecache_associativity = size; 578 } 579 580 /* by default set msram to non-mirrored one */ 581 cpunode->msram = ECACHE_CPU_NON_MIRROR; 582 583 if (GETPROPLEN(node, "msram") != -1) { 584 cpunode->msram = ECACHE_CPU_MIRROR; 585 } 586 587 if (GETPROPLEN(node, "msram-observed") != -1) { 588 cpunode->msram = ECACHE_CPU_MIRROR; 589 } 590 591 if (ncpunode == 0) { 592 cpu_fiximp(node); 593 } 594 595 cpunode->ecache_setsize = 596 cpunode->ecache_size / cpunode->ecache_associativity; 597 598 adj_ecache_setsize(cpunode->ecache_setsize); 599 600 ncpunode++; 601 } 602 603 int 604 get_portid_ddi(dev_info_t *dip, dev_info_t **cmpp) 605 { 606 int portid; 607 int i; 608 char dev_type[OBP_MAXPROPNAME]; 609 int len = OBP_MAXPROPNAME; 610 dev_info_t *cpu_parent; 611 612 if (cmpp != NULL) 613 *cmpp = NULL; 614 615 if ((portid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 616 DDI_PROP_DONTPASS, "portid", -1)) != -1) 617 return (portid); 618 if ((portid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 619 DDI_PROP_DONTPASS, "upa-portid", -1)) != -1) 620 return (portid); 621 if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 622 DDI_PROP_DONTPASS, "device_type", (caddr_t)dev_type, 623 &len) != 0) 624 return (-1); 625 626 /* 627 * For a virtual cpu node that is a CMP core, the "portid" 628 * is in the parent node. 629 * For a virtual cpu node that is a CMT strand, the "portid" is 630 * in its grandparent node. 631 * So we iterate up as far as 2 levels to get the "portid". 632 */ 633 if (strcmp(dev_type, "cpu") == 0) { 634 cpu_parent = dip = ddi_get_parent(dip); 635 for (i = 0; dip != NULL && i < 2; i++) { 636 if ((portid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 637 DDI_PROP_DONTPASS, "portid", -1)) != -1) { 638 if (cmpp != NULL) 639 *cmpp = cpu_parent; 640 return (portid); 641 } 642 dip = ddi_get_parent(dip); 643 } 644 } 645 646 return (-1); 647 } 648 649 /* 650 * A hotplug version of fill_cpu(). (Doesn't assume that there's a node 651 * in the PROM device tree for this CPU.) We still need the PROM version 652 * since it is called very early in the boot cycle before (before 653 * setup_ddi()). Sigh...someday this will all be cleaned up. 654 */ 655 void 656 fill_cpu_ddi(dev_info_t *dip) 657 { 658 extern int cpu_get_cpu_unum(int, char *, int, int *); 659 struct cpu_node *cpunode; 660 processorid_t cpuid; 661 int portid; 662 int len = OBP_MAXPROPNAME; 663 int tlbsize; 664 dev_info_t *cmpnode; 665 char namebuf[OBP_MAXPROPNAME], unum[UNUM_NAMLEN]; 666 char *namebufp; 667 char dev_type[OBP_MAXPROPNAME]; 668 669 if ((portid = get_portid_ddi(dip, &cmpnode)) == -1) { 670 cmn_err(CE_PANIC, "portid not found"); 671 } 672 673 if ((cpuid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 674 DDI_PROP_DONTPASS, "cpuid", -1)) == -1) { 675 cpuid = portid; 676 } 677 678 if (cpuid < 0 || cpuid >= NCPU) { 679 cmn_err(CE_PANIC, "cpu dip %p: cpuid %d out of range", 680 (void *) dip, cpuid); 681 return; 682 } 683 684 cpunode = &cpunodes[cpuid]; 685 cpunode->portid = portid; 686 cpunode->nodeid = ddi_get_nodeid(dip); 687 688 if (cmpnode != NULL) { 689 /* 690 * For the CMT case, the parent "core" node contains 691 * properties needed below, use it instead of the 692 * cpu node. 693 */ 694 if ((ddi_prop_op(DDI_DEV_T_ANY, cmpnode, PROP_LEN_AND_VAL_BUF, 695 DDI_PROP_DONTPASS, "device_type", 696 (caddr_t)dev_type, &len) == DDI_PROP_SUCCESS) && 697 (strcmp(dev_type, "core") == 0)) 698 dip = cmpnode; 699 } 700 701 if (cpu_get_cpu_unum(cpuid, unum, UNUM_NAMLEN, &len) != 0) { 702 cpunode->fru_fmri[0] = '\0'; 703 } else { 704 (void) snprintf(cpunode->fru_fmri, sizeof (cpunode->fru_fmri), 705 "%s%s", CPU_FRU_FMRI, unum); 706 } 707 708 len = sizeof (namebuf); 709 (void) ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, 710 DDI_PROP_DONTPASS, (cmpnode ? "compatible" : "name"), 711 (caddr_t)namebuf, &len); 712 713 namebufp = namebuf; 714 if (strncmp(namebufp, "SUNW,", 5) == 0) 715 namebufp += 5; 716 else if (strncmp(namebufp, "FJSV,", 5) == 0) 717 namebufp += 5; 718 (void) strcpy(cpunode->name, namebufp); 719 720 cpunode->implementation = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 721 DDI_PROP_DONTPASS, "implementation#", 0); 722 723 cpunode->version = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 724 DDI_PROP_DONTPASS, "mask#", 0); 725 726 if (IS_CHEETAH(cpunode->implementation)) { 727 /* remap mask reg */ 728 cpunode->version = REMAP_CHEETAH_MASK(cpunode->version); 729 } 730 731 cpunode->clock_freq = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip, 732 DDI_PROP_DONTPASS, "clock-frequency", 0); 733 734 ASSERT(cpunode->clock_freq != 0); 735 /* 736 * Compute scaling factor based on rate of %tick. This is used 737 * to convert from ticks derived from %tick to nanoseconds. See 738 * comment in sun4u/sys/clock.h for details. 739 */ 740 cpunode->tick_nsec_scale = (uint_t)(((uint64_t)NANOSEC << 741 (32 - TICK_NSEC_SHIFT)) / cpunode->clock_freq); 742 743 tlbsize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 744 DDI_PROP_DONTPASS, "#itlb-entries", 0); 745 ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ 746 cpunode->itlb_size = (ushort_t)tlbsize; 747 748 tlbsize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 749 DDI_PROP_DONTPASS, "#dtlb-entries", 0); 750 ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ 751 cpunode->dtlb_size = (ushort_t)tlbsize; 752 753 if (cmpnode != NULL) { 754 /* 755 * If the CPU has a level 3 cache, then that is it's 756 * external cache. Otherwise the external cache must 757 * be the level 2 cache. 758 */ 759 cpunode->ecache_size = ddi_prop_get_int(DDI_DEV_T_ANY, 760 dip, DDI_PROP_DONTPASS, "l3-cache-size", 0); 761 if (cpunode->ecache_size == 0) 762 cpunode->ecache_size = ddi_prop_get_int(DDI_DEV_T_ANY, 763 dip, DDI_PROP_DONTPASS, "l2-cache-size", 0); 764 ASSERT(cpunode->ecache_size != 0); 765 766 cpunode->ecache_linesize = ddi_prop_get_int(DDI_DEV_T_ANY, 767 dip, DDI_PROP_DONTPASS, "l3-cache-line-size", 0); 768 if (cpunode->ecache_linesize == 0) 769 cpunode->ecache_linesize = 770 ddi_prop_get_int(DDI_DEV_T_ANY, dip, 771 DDI_PROP_DONTPASS, "l2-cache-line-size", 0); 772 ASSERT(cpunode->ecache_linesize != 0); 773 774 cpunode->ecache_associativity = ddi_prop_get_int(DDI_DEV_T_ANY, 775 dip, DDI_PROP_DONTPASS, "l2-cache-associativity", 0); 776 ASSERT(cpunode->ecache_associativity != 0); 777 778 cmp_add_cpu(portid, cpuid); 779 } else { 780 cpunode->ecache_size = ddi_prop_get_int(DDI_DEV_T_ANY, 781 dip, DDI_PROP_DONTPASS, "ecache-size", 0); 782 ASSERT(cpunode->ecache_size != 0); 783 784 cpunode->ecache_linesize = ddi_prop_get_int(DDI_DEV_T_ANY, 785 dip, DDI_PROP_DONTPASS, "ecache-line-size", 0); 786 ASSERT(cpunode->ecache_linesize != 0); 787 788 cpunode->ecache_associativity = ddi_prop_get_int(DDI_DEV_T_ANY, 789 dip, DDI_PROP_DONTPASS, "ecache-associativity", 0); 790 ASSERT(cpunode->ecache_associativity != 0); 791 } 792 793 /* by default set msram to non-mirrored one */ 794 cpunode->msram = ECACHE_CPU_NON_MIRROR; 795 796 if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "msram")) { 797 cpunode->msram = ECACHE_CPU_MIRROR; 798 } else if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 799 "msram-observed")) { 800 cpunode->msram = ECACHE_CPU_MIRROR; 801 } 802 803 ASSERT(ncpunode > 0); /* fiximp not req'd */ 804 805 cpunode->ecache_setsize = 806 cpunode->ecache_size / cpunode->ecache_associativity; 807 808 adj_ecache_setsize(cpunode->ecache_setsize); 809 810 ncpunode++; 811 } 812 813 void 814 empty_cpu(int cpuid) 815 { 816 bzero(&cpunodes[cpuid], sizeof (struct cpu_node)); 817 ncpunode--; 818 } 819 820 #ifdef SF_ERRATA_30 /* call causes fp-disabled */ 821 int spitfire_call_bug = 0; 822 #endif 823 #ifdef SF_V9_TABLE_28 /* fp over/underflow traps may cause wrong fsr.cexc */ 824 int spitfire_bb_fsr_bug = 0; 825 #endif 826 827 #ifdef JALAPENO_ERRATA_85 828 /* 829 * Set the values here assuming we're running 2.4 or later Jalapenos. If 830 * not, they'll be reset below. Either way, the default can be overridden 831 * when we read /etc/system later in boot. 832 */ 833 int jp_errata_85_allow_slow_scrub = 1; 834 int jp_errata_85_enable = 0; 835 #endif /* JALAPENO_ERRATA_85 */ 836 837 static void 838 check_cpus_ver(void) 839 { 840 int i; 841 int impl, cpuid = getprocessorid(); 842 int min_supported_rev; 843 844 ASSERT(cpunodes[cpuid].nodeid != 0); 845 846 impl = cpunodes[cpuid].implementation; 847 switch (impl) { 848 default: 849 min_supported_rev = 0; 850 break; 851 case SPITFIRE_IMPL: 852 min_supported_rev = SPITFIRE_MINREV_SUPPORTED; 853 break; 854 case CHEETAH_IMPL: 855 min_supported_rev = CHEETAH_MINREV_SUPPORTED; 856 break; 857 } 858 859 for (i = 0; i < NCPU; i++) { 860 if (cpunodes[i].nodeid == 0) 861 continue; 862 863 if (IS_SPITFIRE(impl)) { 864 if (cpunodes[i].version < min_supported_rev) { 865 cmn_err(CE_PANIC, 866 "UltraSPARC versions older than %d.%d" 867 " are no longer supported (cpu #%d)", 868 SPITFIRE_MAJOR_VERSION(min_supported_rev), 869 SPITFIRE_MINOR_VERSION(min_supported_rev), i); 870 } 871 872 /* 873 * Min supported rev is 2.1 but we've seen problems 874 * with that so we still want to warn if we see one. 875 */ 876 if (cpunodes[i].version < 0x22) { 877 cmn_err(CE_WARN, 878 "UltraSPARC versions older than " 879 "2.2 are not supported (cpu #%d)", i); 880 #ifdef SF_ERRATA_30 /* call causes fp-disabled */ 881 spitfire_call_bug = 1; 882 #endif /* SF_ERRATA_30 */ 883 } 884 } 885 886 887 #ifdef SF_V9_TABLE_28 /* fp over/underflow traps may cause wrong fsr.cexc */ 888 if (IS_SPITFIRE(impl) || IS_BLACKBIRD(impl)) 889 spitfire_bb_fsr_bug = 1; 890 #endif /* SF_V9_TABLE_28 */ 891 892 if (IS_CHEETAH(impl)) { 893 if (cpunodes[i].version < min_supported_rev) { 894 cmn_err(CE_PANIC, 895 "UltraSPARC-III versions older than %d.%d" 896 " are no longer supported (cpu #%d)", 897 CHEETAH_MAJOR_VERSION(min_supported_rev), 898 CHEETAH_MINOR_VERSION(min_supported_rev), i); 899 } 900 901 } 902 903 #ifdef JALAPENO_ERRATA_85 904 if (IS_JALAPENO(impl) && (cpunodes[i].version < 0x24)) { 905 jp_errata_85_allow_slow_scrub = 0; 906 jp_errata_85_enable = 1; 907 } 908 #endif /* JALAPENO_ERRATA_85 */ 909 } 910 } 911 912 /* 913 * Check for a legal set of CPUs. 914 */ 915 static void 916 check_cpus_set(void) 917 { 918 int i; 919 int impl; 920 int npanther = 0; 921 922 impl = cpunodes[getprocessorid()].implementation; 923 924 switch (impl) { 925 case CHEETAH_PLUS_IMPL: 926 case JAGUAR_IMPL: 927 case PANTHER_IMPL: 928 /* 929 * Check for a legal heterogeneous set of CPUs. 930 */ 931 for (i = 0; i < NCPU; i++) { 932 if (cpunodes[i].nodeid == 0) 933 continue; 934 935 if (IS_PANTHER(cpunodes[i].implementation)) { 936 npanther += 1; 937 } 938 939 if (!(IS_CHEETAH_PLUS(cpunodes[i].implementation) || 940 IS_JAGUAR(cpunodes[i].implementation) || 941 IS_PANTHER(cpunodes[i].implementation))) { 942 use_mp = 0; 943 break; 944 } 945 } 946 break; 947 default: 948 /* 949 * Check for a homogeneous set of CPUs. 950 */ 951 for (i = 0; i < NCPU; i++) { 952 if (cpunodes[i].nodeid == 0) 953 continue; 954 955 if (cpunodes[i].implementation != impl) { 956 use_mp = 0; 957 break; 958 } 959 } 960 break; 961 } 962 963 /* 964 * Change from mmu_page_sizes from 4 to 6 for totally-Panther domains, 965 * where npanther == ncpunode. Also, set ecache_alignsize (and a few 966 * other globals) to the correct value for totally-Panther domains. 967 */ 968 if (&mmu_init_mmu_page_sizes) { 969 (void) mmu_init_mmu_page_sizes(npanther); 970 } 971 if ((npanther == ncpunode) && (&cpu_fix_allpanther)) { 972 cpu_fix_allpanther(); 973 } 974 975 /* 976 * Set max cpus we can have based on ncpunode and use_mp 977 */ 978 if (use_mp) { 979 int (*set_max_ncpus)(void); 980 981 set_max_ncpus = (int (*)(void)) 982 kobj_getsymvalue("set_platform_max_ncpus", 0); 983 984 if (set_max_ncpus) { 985 max_ncpus = set_max_ncpus(); 986 if (max_ncpus < ncpunode) 987 max_ncpus = ncpunode; 988 boot_max_ncpus = ncpunode; 989 } else { 990 max_ncpus = ncpunode; 991 } 992 } else { 993 cmn_err(CE_NOTE, "MP not supported on mismatched modules," 994 " booting UP only"); 995 996 for (i = 0; i < NCPU; i++) { 997 if (cpunodes[i].nodeid == 0) 998 continue; 999 1000 cmn_err(CE_NOTE, "cpu%d: %s version 0x%x", i, 1001 cpunodes[i].name, cpunodes[i].version); 1002 } 1003 1004 max_ncpus = 1; 1005 } 1006 } 1007 1008 /* 1009 * The first sysio must always programmed up for the system clock and error 1010 * handling purposes, referenced by v_sysio_addr in machdep.c. 1011 */ 1012 static void 1013 have_sbus(pnode_t node) 1014 { 1015 int size; 1016 uint_t portid; 1017 1018 size = GETPROPLEN(node, "upa-portid"); 1019 if (size == -1 || size > sizeof (portid)) 1020 cmn_err(CE_PANIC, "upa-portid size"); 1021 if (GETPROP(node, "upa-portid", (caddr_t)&portid) == -1) 1022 cmn_err(CE_PANIC, "upa-portid"); 1023 1024 niobus++; 1025 1026 /* 1027 * need one physical TSB 1028 */ 1029 niommu_tsbs++; 1030 } 1031 1032 1033 #define IOMMU_PER_SCHIZO 2 1034 1035 /* 1036 * The first psycho must always programmed up for the system clock and error 1037 * handling purposes. 1038 */ 1039 static void 1040 have_pci(pnode_t node) 1041 { 1042 int size; 1043 uint_t portid; 1044 char compatible[OBP_MAXDRVNAME]; 1045 1046 size = GETPROPLEN(node, "portid"); 1047 if (size == -1) size = GETPROPLEN(node, "upa-portid"); 1048 if (size == -1) 1049 return; 1050 if (size > sizeof (portid)) 1051 cmn_err(CE_PANIC, "portid size wrong"); 1052 1053 if (GETPROP(node, "portid", (caddr_t)&portid) == -1) 1054 if (GETPROP(node, "upa-portid", (caddr_t)&portid) == -1) 1055 cmn_err(CE_PANIC, "portid not found"); 1056 1057 niobus++; 1058 1059 1060 /* 1061 * Need two physical TSBs for Schizo compatible nodes, 1062 * one otherwise. 1063 */ 1064 compatible[0] = '\0'; 1065 (void) prom_getprop(node, OBP_COMPATIBLE, compatible); 1066 if (strcmp(compatible, "pci108e,8001") == 0) 1067 niommu_tsbs += IOMMU_PER_SCHIZO; 1068 else 1069 niommu_tsbs++; 1070 } 1071 1072 /* 1073 * The first eeprom is used as the TOD clock, referenced 1074 * by v_eeprom_addr in locore.s. 1075 */ 1076 static void 1077 have_eeprom(pnode_t node) 1078 { 1079 int size; 1080 uint32_t eaddr; 1081 1082 /* 1083 * "todmostek" module will be selected based on finding a "model" 1084 * property value of "mk48t59" in the "eeprom" node. 1085 */ 1086 if (tod_module_name == NULL) { 1087 char buf[MAXSYSNAME]; 1088 1089 if ((GETPROP(node, "model", buf) != -1) && 1090 (strcmp(buf, "mk48t59") == 0)) 1091 tod_module_name = "todmostek"; 1092 } 1093 1094 /* 1095 * If we have found two distinct eeprom's, then we're done. 1096 */ 1097 if (v_eeprom_addr && v_timecheck_addr != v_eeprom_addr) 1098 return; 1099 1100 /* 1101 * multiple eeproms may exist but at least 1102 * one must have an "address" property 1103 */ 1104 if ((size = GETPROPLEN(node, OBP_ADDRESS)) == -1) 1105 return; 1106 if (size != sizeof (eaddr)) 1107 cmn_err(CE_PANIC, "eeprom addr size"); 1108 if (GETPROP(node, OBP_ADDRESS, (caddr_t)&eaddr) == -1) 1109 cmn_err(CE_PANIC, "eeprom addr"); 1110 1111 /* 1112 * If we have a chosen eeprom and it is not this node, keep looking. 1113 */ 1114 if (chosen_eeprom != NULL && chosen_eeprom != node) { 1115 v_timecheck_addr = (caddr_t)(uintptr_t)eaddr; 1116 return; 1117 } 1118 1119 v_eeprom_addr = (caddr_t)(uintptr_t)eaddr; 1120 1121 /* 1122 * If we don't find an I/O board to use to check the clock, 1123 * we'll fall back on whichever TOD is available. 1124 */ 1125 if (v_timecheck_addr == NULL) 1126 v_timecheck_addr = v_eeprom_addr; 1127 1128 /* 1129 * Does this eeprom have watchdog support? 1130 */ 1131 if (GETPROPLEN(node, WATCHDOG_ENABLE) != -1) 1132 watchdog_available = 1; 1133 } 1134 1135 static void 1136 have_rtc(pnode_t node) 1137 { 1138 int size; 1139 uint32_t eaddr; 1140 1141 /* 1142 * "ds1287" module will be selected based on finding a "model" 1143 * property value of "ds1287" in the "rtc" node. 1144 */ 1145 if (tod_module_name == NULL) { 1146 char buf[MAXSYSNAME]; 1147 1148 if (GETPROP(node, "model", buf) != -1) { 1149 if ((strcmp(buf, "m5819p") == 0) || 1150 (strcmp(buf, "m5823") == 0)) 1151 tod_module_name = "todm5823"; 1152 else if (strcmp(buf, "ds1287") == 0) 1153 tod_module_name = "todds1287"; 1154 } 1155 } 1156 1157 /* 1158 * XXX - drives on if address prop doesn't exist, later falls 1159 * over in tod module 1160 */ 1161 if ((size = GETPROPLEN(node, OBP_ADDRESS)) == -1) 1162 return; 1163 if (size != sizeof (eaddr)) 1164 cmn_err(CE_PANIC, "rtc addr size"); 1165 if (GETPROP(node, OBP_ADDRESS, (caddr_t)&eaddr) == -1) 1166 cmn_err(CE_PANIC, "rtc addr"); 1167 1168 v_rtc_addr_reg = (caddr_t)(uintptr_t)eaddr; 1169 v_rtc_data_reg = (volatile unsigned char *)(uintptr_t)eaddr + 1; 1170 1171 /* 1172 * Does this rtc have watchdog support? 1173 */ 1174 if (GETPROPLEN(node, WATCHDOG_ENABLE) != -1) 1175 watchdog_available = 1; 1176 } 1177 1178 static void 1179 have_pmc(pnode_t node) 1180 { 1181 uint32_t vaddr; 1182 pnode_t root; 1183 1184 /* 1185 * Watchdog property is in the root node. 1186 */ 1187 root = prom_nextnode((pnode_t)0); 1188 if (GETPROPLEN(root, WATCHDOG_ENABLE) != -1) { 1189 /* 1190 * The hardware watchdog timer resides within logical 1191 * unit 8 of SuperI/O. The address property of the node 1192 * contains the virtual address that we use to program 1193 * the timer. 1194 */ 1195 if (GETPROP(node, OBP_ADDRESS, (caddr_t)&vaddr) == -1) { 1196 watchdog_available = 0; 1197 return; 1198 } 1199 v_pmc_addr_reg = (volatile uint8_t *)(uintptr_t)vaddr; 1200 v_pmc_data_reg = (volatile uint8_t *)(uintptr_t)vaddr + 1; 1201 watchdog_available = 1; 1202 } 1203 } 1204 1205 static void 1206 have_auxio(pnode_t node) 1207 { 1208 size_t size, n; 1209 uint32_t addr[5]; 1210 1211 /* 1212 * Get the size of the auzio's address property. 1213 * On some platforms, the address property contains one 1214 * entry and on others it contains five entries. 1215 * In all cases, the first entries are compatible. 1216 * 1217 * This routine gets the address property for the auxio 1218 * node and stores the first entry in v_auxio_addr which 1219 * is used by the routine set_auxioreg in sun4u/ml/locore.s. 1220 */ 1221 if ((size = GETPROPLEN(node, OBP_ADDRESS)) == -1) 1222 cmn_err(CE_PANIC, "no auxio address property"); 1223 1224 switch (n = (size / sizeof (addr[0]))) { 1225 case 1: 1226 break; 1227 case 5: 1228 break; 1229 default: 1230 cmn_err(CE_PANIC, "auxio addr has %lu entries?", n); 1231 } 1232 1233 if (GETPROP(node, OBP_ADDRESS, (caddr_t)addr) == -1) 1234 cmn_err(CE_PANIC, "auxio addr"); 1235 1236 v_auxio_addr = (caddr_t)(uintptr_t)(addr[0]); /* make into pointer */ 1237 } 1238 1239 static void 1240 have_tod(pnode_t node) 1241 { 1242 static char tod_name[MAXSYSNAME]; 1243 1244 if (GETPROP(node, OBP_NAME, (caddr_t)tod_name) == -1) 1245 cmn_err(CE_PANIC, "tod name"); 1246 /* 1247 * This is a node with "device_type" property value of "tod". 1248 * Name of the tod module is the name from the node. 1249 */ 1250 tod_module_name = tod_name; 1251 } 1252