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