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