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 /* 27 * CPU functions to the Safari Configurator (gptwo_cpu) 28 */ 29 30 #include <sys/types.h> 31 #include <sys/cred.h> 32 #include <sys/mman.h> 33 #include <sys/kmem.h> 34 #include <sys/conf.h> 35 #include <sys/ddi.h> 36 #include <sys/sunddi.h> 37 #include <sys/sunndi.h> 38 #include <sys/modctl.h> 39 #include <sys/stat.h> 40 #include <sys/param.h> 41 #include <sys/autoconf.h> 42 #include <sys/ksynch.h> 43 #include <sys/promif.h> 44 #include <sys/ndi_impldefs.h> 45 #include <sys/ddi_impldefs.h> 46 #include <sys/machsystm.h> 47 #include <sys/gp2cfg.h> 48 #include <sys/gptwo_cpu.h> 49 #include <sys/cheetahregs.h> 50 51 #ifdef DEBUG 52 int gptwo_cpu_debug = 0; 53 54 static void debug(char *, uintptr_t, uintptr_t, 55 uintptr_t, uintptr_t, uintptr_t); 56 57 #define GPTWO_DEBUG0(level, flag, s) if (gptwo_cpu_debug >= level) \ 58 cmn_err(flag, s) 59 #define GPTWO_DEBUG1(level, flag, fmt, a1) if (gptwo_cpu_debug >= level) \ 60 debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0); 61 #define GPTWO_DEBUG2(level, flag, fmt, a1, a2) if (gptwo_cpu_debug >= level) \ 62 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0); 63 #define GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3) \ 64 if (gptwo_cpu_debug >= level) \ 65 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), (uintptr_t)(a3), 0, 0); 66 #else 67 #define GPTWO_DEBUG0(level, flag, s) 68 #define GPTWO_DEBUG1(level, flag, fmt, a1) 69 #define GPTWO_DEBUG2(level, flag, fmt, a1, a2) 70 #define GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3) 71 #endif 72 73 /* 74 * Devinfo branch create arg 75 */ 76 struct bca { 77 spcd_t *pcd; 78 uint_t portid; 79 uint_t cpuid; 80 uint_t coreid; 81 uint_t impl; 82 dev_info_t *new_child; 83 }; 84 85 static dev_info_t *gptwocfg_create_cpu_node(dev_info_t *, spcd_t *, 86 uint_t, uint_t, uint_t, uint_t); 87 static dev_info_t *gptwocfg_create_mc_node(dev_info_t *, spcd_t *, uint_t); 88 static dev_info_t *gptwocfg_create_cmp_node(dev_info_t *, spcd_t *, uint_t); 89 static int gptwocfg_create_core_node(dev_info_t *, spcd_t *, uint_t, uint_t); 90 static int set_mc_props(dev_info_t *new_child, void *arg, uint_t flags); 91 static int set_cmp_props(dev_info_t *new_child, void *arg, uint_t flags); 92 static int set_cpu_props(dev_info_t *new_child, void *arg, uint_t flags); 93 static int set_cpu_common_props(dev_info_t *new_child, struct bca *bcp); 94 static int set_cpu_us3_props(dev_info_t *new_child, struct bca *bcp); 95 static int set_cpu_us4_props(dev_info_t *new_child, struct bca *bcp); 96 static void get_new_child(dev_info_t *rdip, void *arg, uint_t flags); 97 98 99 /* 100 * Module linkage information for the kernel. 101 */ 102 103 extern struct mod_ops mod_miscops; 104 105 static struct modlmisc modlmisc = { 106 &mod_miscops, /* Type of module */ 107 "gptwo->cpu configurator", 108 }; 109 110 static struct modlinkage modlinkage = { 111 MODREV_1, (void *)&modlmisc, NULL 112 }; 113 114 int 115 _init(void) 116 { 117 int err = 0; 118 119 /* register device with the configurator */ 120 gptwocfg_register_ops(SAFPTYPE_CPU, gptwocfg_configure_cpu, NULL); 121 122 if ((err = mod_install(&modlinkage)) != 0) { 123 GPTWO_DEBUG1(1, CE_WARN, "gptwo_cpu (CPU/MC Functions) " 124 "failed to load, error=%d\n", err); 125 gptwocfg_unregister_ops(SAFPTYPE_CPU); 126 } else { 127 GPTWO_DEBUG0(1, CE_WARN, "gptwo_cpu (CPU/MC Functions) " 128 "has been loaded.\n"); 129 } 130 return (err); 131 } 132 133 int 134 _fini(void) 135 { 136 /* cleanup/freeup structs with configurator */ 137 gptwocfg_unregister_ops(SAFPTYPE_CPU); 138 return (mod_remove(&modlinkage)); 139 } 140 141 int 142 _info(struct modinfo *modinfop) 143 { 144 return (mod_info(&modlinkage, modinfop)); 145 } 146 147 gptwo_new_nodes_t * 148 gptwocfg_configure_cpu(dev_info_t *ap, spcd_t *pcd, uint_t portid) 149 { 150 dev_info_t *cpu_node[AGENTS_PER_PORT], *mc_node[AGENTS_PER_PORT]; 151 dev_info_t *cmp_node = NULL; 152 gptwo_new_nodes_t *new_nodes; 153 int nodes = 0; 154 int i, j = 0; 155 uint_t implementation; 156 157 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_configure_cpu: portid=%x pcd=%lx\n", 158 portid, pcd); 159 160 for (i = 0; i < AGENTS_PER_PORT; i++) { 161 cpu_node[i] = NULL; 162 mc_node[i] = NULL; 163 } 164 165 implementation = (pcd->spcd_ver_reg >> 32) & 0x000000000000ffff; 166 167 switch (implementation) { 168 case CHEETAH_IMPL: 169 case CHEETAH_PLUS_IMPL: 170 case JAGUAR_IMPL: 171 case PANTHER_IMPL: 172 break; 173 default: 174 cmn_err(CE_WARN, "Unsupported cpu implementation=0x%x : " 175 "skipping configure of portid=0x%x", implementation, 176 portid); 177 ASSERT(0); 178 return (NULL); 179 } 180 181 if (CPU_IMPL_IS_CMP(implementation)) { 182 if (cmp_node = gptwocfg_create_cmp_node(ap, pcd, portid)) 183 nodes++; 184 else 185 return (NULL); 186 } 187 188 for (i = 0; i < AGENTS_PER_PORT; i++) { 189 if (pcd->spcd_agent[i] != SPCD_RSV_PASS) 190 continue; 191 192 if (cpu_node[i] = gptwocfg_create_cpu_node(cmp_node ? 193 cmp_node : ap, pcd, portid, pcd->spcd_cpuid[i], i, 194 implementation)) { 195 /* 196 * If the CPU is a CMP, the entire branch is 197 * manipulated using just the top node. Thus, 198 * the dips of the individual cores do not need 199 * to be held or stored in the new node list. 200 */ 201 if (cmp_node) { 202 e_ddi_branch_rele(cpu_node[i]); 203 } else { 204 nodes++; 205 } 206 } 207 } 208 209 /* current implementations have 1 MC node per Safari port */ 210 if (pcd->spcd_prsv == SPCD_RSV_PASS && 211 (mc_node[0] = gptwocfg_create_mc_node(ap, pcd, portid))) 212 nodes++; 213 214 new_nodes = gptwocfg_allocate_node_list(nodes); 215 216 j = 0; 217 for (i = 0; i < AGENTS_PER_PORT; i++) { 218 if ((cpu_node[i] != NULL) && (!CPU_IMPL_IS_CMP(implementation))) 219 new_nodes->gptwo_nodes[j++] = cpu_node[i]; 220 if (mc_node[i] != NULL) 221 new_nodes->gptwo_nodes[j++] = mc_node[i]; 222 } 223 224 if (cmp_node) 225 new_nodes->gptwo_nodes[j++] = cmp_node; 226 227 return (new_nodes); 228 } 229 230 231 static dev_info_t * 232 gptwocfg_create_cmp_node(dev_info_t *ap, spcd_t *pcd, uint_t portid) 233 { 234 struct bca arg; 235 devi_branch_t b; 236 237 arg.pcd = pcd; 238 arg.portid = portid; 239 arg.cpuid = 0; 240 arg.coreid = 0; 241 arg.new_child = NULL; 242 243 b.arg = &arg; 244 b.type = DEVI_BRANCH_SID; 245 b.create.sid_branch_create = set_cmp_props; 246 b.devi_branch_callback = get_new_child; 247 248 if (e_ddi_branch_create(ap, &b, NULL, 0)) 249 return (NULL); 250 251 return (arg.new_child); 252 } 253 254 /*ARGSUSED*/ 255 static int 256 set_cmp_props(dev_info_t *new_child, void *arg, uint_t flags) 257 { 258 struct bca *bap = (struct bca *)arg; 259 gptwo_regspec_t reg; 260 spcd_t *pcd; 261 uint_t portid; 262 263 pcd = bap->pcd; 264 portid = bap->portid; 265 266 GPTWO_DEBUG2(1, CE_CONT, "set_cmp_props: portid=%x pcd=%lx\n", 267 portid, pcd); 268 269 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child, 270 "name", "cmp") != DDI_SUCCESS) { 271 GPTWO_DEBUG0(1, CE_CONT, "set_cmp_props: failed to " 272 "create name property\n"); 273 return (DDI_WALK_ERROR); 274 } 275 276 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 277 "portid", portid) != DDI_SUCCESS) { 278 GPTWO_DEBUG0(1, CE_CONT, "set_cmp_props: failed to " 279 "create portid property\n"); 280 return (DDI_WALK_ERROR); 281 } 282 283 reg.gptwo_phys_hi = 0x400 | (portid >> 9); 284 reg.gptwo_phys_low = (portid << 23); 285 reg.gptwo_size_hi = 0; 286 reg.gptwo_size_low = 0x10000; 287 288 if (ndi_prop_update_int_array(DDI_DEV_T_NONE, 289 new_child, "reg", (int *)®, 290 sizeof (gptwo_regspec_t) / sizeof (int)) != DDI_SUCCESS) { 291 GPTWO_DEBUG0(1, CE_CONT, "set_cmp_props: failed to " 292 "create reg property\n"); 293 return (DDI_WALK_ERROR); 294 } 295 296 return (DDI_WALK_TERMINATE); 297 } 298 299 static dev_info_t * 300 gptwocfg_create_cpu_node(dev_info_t *ap, spcd_t *pcd, uint_t portid, 301 uint_t cpuid, uint_t coreid, uint_t impl) 302 { 303 struct bca arg; 304 devi_branch_t b = {0}; 305 306 arg.pcd = pcd; 307 arg.portid = portid; 308 arg.cpuid = cpuid; 309 arg.coreid = coreid; 310 arg.impl = impl; 311 arg.new_child = NULL; 312 313 b.arg = &arg; 314 b.type = DEVI_BRANCH_SID; 315 b.create.sid_branch_create = set_cpu_props; 316 b.devi_branch_callback = get_new_child; 317 318 if (e_ddi_branch_create(ap, &b, NULL, 0)) 319 return (NULL); 320 321 return (arg.new_child); 322 } 323 324 /*ARGSUSED*/ 325 static int 326 set_cpu_props(dev_info_t *new_child, void *arg, uint_t flags) 327 { 328 struct bca *bcp = arg; 329 uint_t impl = bcp->impl; 330 int rc; 331 332 if (set_cpu_common_props(new_child, bcp) != DDI_WALK_CONTINUE) 333 return (DDI_WALK_ERROR); 334 335 switch (impl) { 336 case CHEETAH_IMPL: 337 case CHEETAH_PLUS_IMPL: 338 rc = set_cpu_us3_props(new_child, bcp); 339 break; 340 case JAGUAR_IMPL: 341 case PANTHER_IMPL: 342 rc = set_cpu_us4_props(new_child, bcp); 343 break; 344 default: 345 ASSERT(0); 346 return (DDI_WALK_ERROR); 347 } 348 349 return (rc); 350 } 351 352 /* 353 * Set properties common to cpu (non-CMP) and core (CMP) nodes. 354 * 355 * cpuid 356 * device_type 357 * manufacturer# 358 * implementation# 359 * mask# 360 * sparc-version 361 * clock-frequency 362 * #dtlb-entries 363 * #itlb-entries 364 */ 365 static int 366 set_cpu_common_props(dev_info_t *new_child, struct bca *bcp) 367 { 368 uint_t cpuid, impl; 369 spcd_t *pcd; 370 int mask, manufacturer; 371 372 cpuid = bcp->cpuid; 373 pcd = bcp->pcd; 374 impl = bcp->impl; 375 376 mask = (pcd->spcd_ver_reg >> 24) & 0x00000000000000ff; 377 manufacturer = (pcd->spcd_ver_reg >> 48) & 0x000000000000ffff; 378 379 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 380 "cpuid", cpuid) != DDI_SUCCESS) { 381 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed " 382 "to create cpuid property\n"); 383 return (DDI_WALK_ERROR); 384 } 385 386 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child, 387 "device_type", "cpu") != DDI_SUCCESS) { 388 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed " 389 "to create device_type property\n"); 390 return (DDI_WALK_ERROR); 391 } 392 393 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, "manufacturer#", 394 manufacturer) != DDI_SUCCESS) { 395 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed " 396 "to create manufacturer# property\n"); 397 return (DDI_WALK_ERROR); 398 } 399 400 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, "implementation#", 401 impl) != DDI_SUCCESS) { 402 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed " 403 "to create implementation# property\n"); 404 return (DDI_WALK_ERROR); 405 } 406 407 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, "mask#", 408 mask) != DDI_SUCCESS) { 409 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed " 410 "to create mask# property\n"); 411 return (DDI_WALK_ERROR); 412 } 413 414 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 415 "sparc-version", 9) != DDI_SUCCESS) { 416 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed " 417 "to create sparc-version property\n"); 418 return (DDI_WALK_ERROR); 419 } 420 421 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 422 "clock-frequency", (pcd->spcd_afreq * 1000000)) != DDI_SUCCESS) { 423 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed " 424 "to create clock-frequency property\n"); 425 return (DDI_WALK_ERROR); 426 } 427 428 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 429 "#dtlb-entries", 0x10) != DDI_SUCCESS) { 430 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed " 431 "to create #dtlb-entries property\n"); 432 return (DDI_WALK_ERROR); 433 } 434 435 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 436 "#itlb-entries", 0x10) != DDI_SUCCESS) { 437 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed " 438 "to create #itlb-entries property\n"); 439 return (DDI_WALK_ERROR); 440 } 441 442 return (DDI_WALK_CONTINUE); 443 } 444 445 /* 446 * Set cpu node properties for Cheetah and Cheetah+. 447 * 448 * name 449 * portid 450 * reg 451 * icache-size 452 * icache-line-size 453 * icache-associativity 454 * dcache-size 455 * dcache-line-size 456 * dcache-associativity 457 * ecache-size 458 * ecache-line-size 459 * ecache-associativity 460 */ 461 static int 462 set_cpu_us3_props(dev_info_t *new_child, struct bca *bcp) 463 { 464 char *node_name; 465 gptwo_regspec_t reg; 466 int ecache_size, ecache_line_size; 467 int dimms, ecache_assoc; 468 spcd_t *pcd; 469 uint_t portid, impl; 470 471 pcd = bcp->pcd; 472 portid = bcp->portid; 473 impl = bcp->impl; 474 475 ASSERT(IS_CHEETAH(impl) || IS_CHEETAH_PLUS(impl)); 476 477 switch (impl) { 478 case CHEETAH_IMPL: 479 ecache_assoc = CH_ECACHE_NWAY; 480 node_name = "SUNW,UltraSPARC-III"; 481 break; 482 case CHEETAH_PLUS_IMPL: 483 /* 484 * Hard coding the ecache-associativity to 2 for Cheetah+. 485 * We probably should add this to the PCD. 486 */ 487 ecache_assoc = CHP_ECACHE_NWAY; 488 node_name = "SUNW,UltraSPARC-III+"; 489 break; 490 default: 491 GPTWO_DEBUG1(1, CE_CONT, "set_cpu_us3_props: invalid " 492 "implementation=0x%x\n", impl); 493 return (DDI_WALK_ERROR); 494 } 495 496 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child, 497 "name", node_name) != DDI_SUCCESS) { 498 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed " 499 "to create name property\n"); 500 return (DDI_WALK_ERROR); 501 } 502 503 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 504 "portid", portid) != DDI_SUCCESS) { 505 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed " 506 "to create portid property\n"); 507 return (DDI_WALK_ERROR); 508 } 509 510 reg.gptwo_phys_hi = 0x400 | (portid >> 9); 511 reg.gptwo_phys_low = (portid << 23); 512 reg.gptwo_size_hi = 0; 513 reg.gptwo_size_low = 0x10000; 514 515 if (ndi_prop_update_int_array(DDI_DEV_T_NONE, 516 new_child, "reg", (int *)®, 517 sizeof (gptwo_regspec_t) / sizeof (int)) != DDI_SUCCESS) { 518 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed " 519 "to create reg property\n"); 520 return (DDI_WALK_ERROR); 521 } 522 523 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 524 "icache-size", CH_ICACHE_SIZE) != DDI_SUCCESS) { 525 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed " 526 "to create icache-size property\n"); 527 return (DDI_WALK_ERROR); 528 } 529 530 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 531 "icache-line-size", CH_ICACHE_LSIZE) != DDI_SUCCESS) { 532 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed " 533 "to create icache-line-size property\n"); 534 return (DDI_WALK_ERROR); 535 } 536 537 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 538 "icache-associativity", CH_ICACHE_NWAY) != DDI_SUCCESS) { 539 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed " 540 "to create icache-associativity property\n"); 541 return (DDI_WALK_ERROR); 542 } 543 544 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 545 "dcache-size", CH_DCACHE_SIZE) != DDI_SUCCESS) { 546 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed " 547 "to create dcache-size property\n"); 548 return (DDI_WALK_ERROR); 549 } 550 551 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 552 "dcache-line-size", CH_DCACHE_LSIZE) != DDI_SUCCESS) { 553 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed " 554 "to create dcache-line-size property\n"); 555 return (DDI_WALK_ERROR); 556 } 557 558 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 559 "dcache-associativity", CH_DCACHE_NWAY) != DDI_SUCCESS) { 560 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed " 561 "to create dcache-associativity property\n"); 562 return (DDI_WALK_ERROR); 563 } 564 565 /* 566 * Get the External Cache Size from the Common PCD. 567 */ 568 ecache_size = pcd->spcd_cache * 0x100000; 569 570 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 571 "ecache-size", ecache_size) != DDI_SUCCESS) { 572 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed " 573 "to create ecache-line-size property\n"); 574 return (DDI_WALK_ERROR); 575 } 576 577 switch (ecache_size) { 578 case CH_ECACHE_1M_SIZE: 579 ecache_line_size = 64; 580 break; 581 case CH_ECACHE_4M_SIZE: 582 ecache_line_size = 256; 583 break; 584 case CH_ECACHE_8M_SIZE: 585 ecache_line_size = 512; 586 break; 587 default: 588 GPTWO_DEBUG1(1, CE_CONT, "set_cpu_us3_props: invalid " 589 "ecache-size 0x%x\b", ecache_size); 590 return (DDI_WALK_ERROR); 591 } 592 593 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 594 "ecache-line-size", ecache_line_size) != DDI_SUCCESS) { 595 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed " 596 "to create ecache-line-size property\n"); 597 return (DDI_WALK_ERROR); 598 } 599 600 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 601 "ecache-associativity", ecache_assoc) != DDI_SUCCESS) { 602 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed " 603 "to create ecache-associativity property\n"); 604 return (DDI_WALK_ERROR); 605 } 606 607 /* 608 * Create the ecache-dimm-label property. 609 */ 610 dimms = 0; 611 612 while ((pcd->sprd_ecache_dimm_label[dimms] != NULL) && 613 (dimms < MAX_DIMMS_PER_PORT)) 614 dimms++; 615 616 if (dimms) { 617 (void) ndi_prop_update_string_array(DDI_DEV_T_NONE, new_child, 618 "ecache-dimm-label", (char **)pcd->sprd_ecache_dimm_label, 619 dimms); 620 } 621 622 return (DDI_WALK_TERMINATE); 623 } 624 625 /* 626 * Set cmp core node properties for Jaguar and Panther. 627 * 628 * name 629 * compatible 630 * reg 631 * l1-icache-size 632 * l1-icache-line-size 633 * l1-icache-associativity 634 * l1-dcache-size 635 * l1-dcache-line-size 636 * l1-dcache-associativity 637 * l2-cache-size 638 * l2-cache-line-size 639 * l2-cache-associativity 640 * l2-cache-sharing 641 * l3-cache-size 642 * l3-cache-line-size 643 * l3-cache-associativity 644 * l3-cache-sharing 645 */ 646 static int 647 set_cpu_us4_props(dev_info_t *new_child, struct bca *bcp) 648 { 649 uint_t l1_icache_size, l1_icache_line_size; 650 uint_t l2_cache_size, l2_cache_line_size, l2_cache_assoc; 651 uint_t l2_cache_share; 652 uint_t pcd_cache_size; 653 uint_t coreid, impl; 654 spcd_t *pcd; 655 char *compatible; 656 int dimms; 657 int i; 658 659 pcd = bcp->pcd; 660 coreid = bcp->coreid; 661 impl = bcp->impl; 662 663 ASSERT(IS_JAGUAR(impl) || IS_PANTHER(impl)); 664 665 /* 666 * Get the External Cache Size from the Common PCD. 667 */ 668 pcd_cache_size = pcd->spcd_cache * 0x100000; 669 670 switch (impl) { 671 case JAGUAR_IMPL: 672 compatible = "SUNW,UltraSPARC-IV"; 673 l1_icache_size = CH_ICACHE_SIZE; 674 l1_icache_line_size = CH_ICACHE_LSIZE; 675 l2_cache_assoc = CHP_ECACHE_NWAY; 676 677 /* 678 * Jaguar has no logical sharing of L2 cache, so the sharing 679 * bit-map will represent this core only. 680 */ 681 l2_cache_share = coreid ? 0x2 : 0x1; 682 683 /* 684 * Jaguar has a split ecache, so the total ecache must be 685 * divided in half to get the ecache for the individual core. 686 */ 687 l2_cache_size = pcd_cache_size / 2; 688 689 switch (l2_cache_size) { 690 case JG_ECACHE_4M_SIZE: 691 l2_cache_line_size = 64; 692 break; 693 case JG_ECACHE_8M_SIZE: 694 l2_cache_line_size = 128; 695 break; 696 default: 697 GPTWO_DEBUG1(1, CE_CONT, "set_cpu_us4_props: " 698 "invalid l2_cache-size 0x%x\n", l2_cache_size); 699 return (DDI_WALK_ERROR); 700 } 701 break; 702 case PANTHER_IMPL: 703 ASSERT(pcd_cache_size == PN_L3_SIZE); 704 compatible = "SUNW,UltraSPARC-IV+"; 705 l1_icache_size = PN_ICACHE_SIZE; 706 l1_icache_line_size = PN_ICACHE_LSIZE; 707 l2_cache_size = PN_L2_SIZE; 708 l2_cache_line_size = PN_L2_LINESIZE; 709 l2_cache_assoc = PN_ECACHE_NWAY; 710 711 /* 712 * For Panther, the L2 and L3 caches are logically shared by 713 * all enabled cores, so the sharing bit-map will represent 714 * all enabled cores. Panther split-mode is still considered 715 * shared. 716 * 717 * Check the PCD status to determine enabled cores. 718 */ 719 ASSERT(pcd->spcd_ptype == SAFPTYPE_CPU); 720 l2_cache_share = 0; 721 for (i = 0; i < AGENTS_PER_PORT; i++) { 722 if (pcd->spcd_agent[i] == SPCD_RSV_PASS) { 723 l2_cache_share |= (1 << i); 724 } 725 } 726 727 break; 728 default: 729 GPTWO_DEBUG1(1, CE_CONT, "set_cpu_us4_props: invalid " 730 "implementation=0x%x\n", impl); 731 return (DDI_WALK_ERROR); 732 } 733 734 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child, 735 "name", "cpu") != DDI_SUCCESS) { 736 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed " 737 "to create name property\n"); 738 return (DDI_WALK_ERROR); 739 } 740 741 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child, 742 "compatible", compatible) != DDI_SUCCESS) { 743 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed " 744 "to create compatible property\n"); 745 return (DDI_WALK_ERROR); 746 } 747 748 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 749 "reg", coreid) != DDI_SUCCESS) { 750 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed " 751 "to create reg property\n"); 752 return (DDI_WALK_ERROR); 753 } 754 755 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 756 "l1-icache-size", l1_icache_size) != DDI_SUCCESS) { 757 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed " 758 "to create l1-icache-size property\n"); 759 return (DDI_WALK_ERROR); 760 } 761 762 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 763 "l1-icache-line-size", l1_icache_line_size) != DDI_SUCCESS) { 764 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed " 765 "to create icache-line-size property\n"); 766 return (DDI_WALK_ERROR); 767 } 768 769 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 770 "l1-icache-associativity", CH_ICACHE_NWAY) != DDI_SUCCESS) { 771 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed " 772 "to create l1-icache-associativity property\n"); 773 return (DDI_WALK_ERROR); 774 } 775 776 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 777 "l1-dcache-size", CH_DCACHE_SIZE) != DDI_SUCCESS) { 778 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed " 779 "to create l1-dcache-size property\n"); 780 return (DDI_WALK_ERROR); 781 } 782 783 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 784 "l1-dcache-line-size", CH_DCACHE_LSIZE) != DDI_SUCCESS) { 785 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed " 786 "to create dcache-line-size property\n"); 787 return (DDI_WALK_ERROR); 788 } 789 790 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 791 "l1-dcache-associativity", CH_DCACHE_NWAY) != DDI_SUCCESS) { 792 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed " 793 "to create l1-dcache-associativity property\n"); 794 return (DDI_WALK_ERROR); 795 } 796 797 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 798 "l2-cache-size", l2_cache_size) != DDI_SUCCESS) { 799 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed " 800 "to create l2-cache-size property\n"); 801 return (DDI_WALK_ERROR); 802 } 803 804 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 805 "l2-cache-line-size", l2_cache_line_size) != DDI_SUCCESS) { 806 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed " 807 "to create l2_cache-line-size property\n"); 808 return (DDI_WALK_ERROR); 809 } 810 811 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 812 "l2-cache-associativity", l2_cache_assoc) != DDI_SUCCESS) { 813 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed " 814 "to create l2-cache-associativity property\n"); 815 return (DDI_WALK_ERROR); 816 } 817 818 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 819 "l2-cache-sharing", l2_cache_share) != DDI_SUCCESS) { 820 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed " 821 "to create l2-cache-sharing property\n"); 822 return (DDI_WALK_ERROR); 823 } 824 825 /* 826 * Create the ecache-dimm-label property. 827 */ 828 dimms = 0; 829 830 while ((pcd->sprd_ecache_dimm_label[dimms] != NULL) && 831 (dimms < MAX_DIMMS_PER_PORT)) 832 dimms++; 833 834 if (dimms) { 835 (void) ndi_prop_update_string_array(DDI_DEV_T_NONE, new_child, 836 "ecache-dimm-label", (char **)pcd->sprd_ecache_dimm_label, 837 dimms); 838 } 839 840 if (IS_PANTHER(impl)) { 841 int l3_cache_share = l2_cache_share; 842 843 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 844 "l3-cache-size", PN_L3_SIZE) != DDI_SUCCESS) { 845 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: " 846 "failed to create l3-cache-size property\n"); 847 return (DDI_WALK_ERROR); 848 } 849 850 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 851 "l3-cache-line-size", PN_L3_LINESIZE) != DDI_SUCCESS) { 852 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: " 853 "failed to create l3-cache-line-size property\n"); 854 return (DDI_WALK_ERROR); 855 } 856 857 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 858 "l3-cache-associativity", PN_ECACHE_NWAY) != DDI_SUCCESS) { 859 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: " 860 "failed to create l3-cache-associativity " 861 "property\n"); 862 return (DDI_WALK_ERROR); 863 } 864 865 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 866 "l3-cache-sharing", l3_cache_share) != DDI_SUCCESS) { 867 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: " 868 "failed to create l3-cache-sharing property\n"); 869 return (DDI_WALK_ERROR); 870 } 871 } 872 873 return (DDI_WALK_TERMINATE); 874 } 875 876 static dev_info_t * 877 gptwocfg_create_mc_node(dev_info_t *ap, spcd_t *pcd, uint_t portid) 878 { 879 struct bca arg; 880 devi_branch_t b = {0}; 881 882 arg.pcd = pcd; 883 arg.portid = portid; 884 arg.cpuid = portid; 885 arg.new_child = NULL; 886 887 b.arg = &arg; 888 b.type = DEVI_BRANCH_SID; 889 b.create.sid_branch_create = set_mc_props; 890 b.devi_branch_callback = get_new_child; 891 892 if (e_ddi_branch_create(ap, &b, NULL, 0)) 893 return (NULL); 894 895 return (arg.new_child); 896 } 897 898 /*ARGSUSED*/ 899 static int 900 set_mc_props(dev_info_t *new_child, void *arg, uint_t flags) 901 { 902 struct bca *bcp = arg; 903 gptwo_regspec_t reg; 904 int banks, dimms; 905 spcd_t *pcd = bcp->pcd; 906 uint_t portid = bcp->portid; 907 uint_t cpuid = bcp->cpuid; 908 909 GPTWO_DEBUG3(1, CE_CONT, "set_mc_props: ap=0x%lx portid=0x%x " 910 "cpuid=0x%x\n", ddi_get_parent(new_child), portid, cpuid); 911 912 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child, 913 "name", "memory-controller") != DDI_SUCCESS) { 914 GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed " 915 "to create name property\n"); 916 return (DDI_WALK_ERROR); 917 } 918 919 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child, 920 "compatible", "SUNW,UltraSPARC-III,mc") != DDI_SUCCESS) { 921 GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed " 922 "to create compatible property\n"); 923 return (DDI_WALK_ERROR); 924 } 925 926 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child, 927 "device_type", "memory-controller") != DDI_SUCCESS) { 928 GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed " 929 "to create device_type property\n"); 930 return (DDI_WALK_ERROR); 931 } 932 933 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 934 "portid", portid) != DDI_SUCCESS) { 935 GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed " 936 "to create portid property\n"); 937 return (DDI_WALK_ERROR); 938 } 939 940 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, 941 "cpuid", cpuid) != DDI_SUCCESS) { 942 GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed " 943 "to create cpuid property\n"); 944 return (DDI_WALK_ERROR); 945 } 946 947 reg.gptwo_phys_hi = 0x400 | (portid >> 9); 948 reg.gptwo_phys_low = (portid << 23) | 0x400000; 949 reg.gptwo_size_hi = 0; 950 reg.gptwo_size_low = 0x48; 951 952 if (ndi_prop_update_int_array(DDI_DEV_T_NONE, 953 new_child, "reg", (int *)®, 954 sizeof (gptwo_regspec_t) / sizeof (int)) != DDI_SUCCESS) { 955 GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed " 956 "to create reg property\n"); 957 return (DDI_WALK_ERROR); 958 } 959 960 if (pcd->memory_layout) { 961 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, 962 new_child, "memory-layout", (uchar_t *)pcd->memory_layout, 963 pcd->memory_layout_size) != DDI_SUCCESS) { 964 965 GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed " 966 "to create memory-layout property\n"); 967 968 return (DDI_WALK_ERROR); 969 } 970 } 971 972 /* 973 * Create the bank-status property. 974 */ 975 banks = 0; 976 977 while ((pcd->sprd_bank_rsv[banks] != NULL) && 978 (banks < MAX_BANKS_PER_PORT)) 979 banks++; 980 981 if (banks) { 982 (void) ndi_prop_update_string_array(DDI_DEV_T_NONE, new_child, 983 "bank-status", (char **)pcd->sprd_bank_rsv, banks); 984 } 985 986 /* 987 * Create the dimm-status property. 988 */ 989 dimms = 0; 990 991 while ((pcd->sprd_dimm[dimms] != NULL) && 992 (dimms < MAX_DIMMS_PER_PORT)) 993 dimms++; 994 995 if (dimms) { 996 (void) ndi_prop_update_string_array(DDI_DEV_T_NONE, new_child, 997 "dimm-status", (char **)pcd->sprd_dimm, dimms); 998 } 999 1000 1001 return (DDI_WALK_TERMINATE); 1002 } 1003 1004 /*ARGSUSED*/ 1005 static void 1006 get_new_child(dev_info_t *rdip, void *arg, uint_t flags) 1007 { 1008 struct bca *bcp = arg; 1009 1010 bcp->new_child = rdip; 1011 1012 } 1013 1014 #ifdef DEBUG 1015 static void 1016 debug(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3, 1017 uintptr_t a4, uintptr_t a5) 1018 { 1019 cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5); 1020 } 1021 #endif 1022