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 /* 23 * Copyright 2008 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/time.h> 30 #include <sys/cpuvar.h> 31 #include <sys/dditypes.h> 32 #include <sys/ddipropdefs.h> 33 #include <sys/ddi_impldefs.h> 34 #include <sys/sunddi.h> 35 #include <sys/esunddi.h> 36 #include <sys/sunndi.h> 37 #include <sys/platform_module.h> 38 #include <sys/errno.h> 39 #include <sys/conf.h> 40 #include <sys/modctl.h> 41 #include <sys/promif.h> 42 #include <sys/promimpl.h> 43 #include <sys/prom_plat.h> 44 #include <sys/cmn_err.h> 45 #include <sys/sysmacros.h> 46 #include <sys/mem_cage.h> 47 #include <sys/kobj.h> 48 #include <sys/utsname.h> 49 #include <sys/cpu_sgnblk_defs.h> 50 #include <sys/atomic.h> 51 #include <sys/kdi_impl.h> 52 53 #include <sys/sgsbbc.h> 54 #include <sys/sgsbbc_iosram.h> 55 #include <sys/sgsbbc_iosram_priv.h> 56 #include <sys/sgsbbc_mailbox.h> 57 #include <sys/sgsgn.h> 58 #include <sys/sgcn.h> 59 #include <sys/serengeti.h> 60 #include <sys/sgfrutypes.h> 61 #include <sys/machsystm.h> 62 #include <sys/sbd_ioctl.h> 63 #include <sys/sbd.h> 64 #include <sys/sbdp_mem.h> 65 66 #include <sys/memnode.h> 67 #include <vm/vm_dep.h> 68 #include <vm/page.h> 69 70 #include <sys/cheetahregs.h> 71 #include <sys/plat_ecc_unum.h> 72 #include <sys/plat_ecc_dimm.h> 73 74 #include <sys/lgrp.h> 75 76 static int sg_debug = 0; 77 78 #ifdef DEBUG 79 #define DCMNERR if (sg_debug) cmn_err 80 #else 81 #define DCMNERR 82 #endif 83 84 int (*p2get_mem_unum)(int, uint64_t, char *, int, int *); 85 86 /* local functions */ 87 static void cpu_sgn_update(ushort_t sgn, uchar_t state, 88 uchar_t sub_state, int cpuid); 89 90 91 /* 92 * Local data. 93 * 94 * iosram_write_ptr is a pointer to iosram_write(). Because of 95 * kernel dynamic linking, we can't get to the function by name, 96 * but we can look up its address, and store it in this variable 97 * instead. 98 * 99 * We include the extern for iosram_write() here not because we call 100 * it, but to force compilation errors if its prototype doesn't 101 * match the prototype of iosram_write_ptr. 102 * 103 * The same issues apply to iosram_read() and iosram_read_ptr. 104 */ 105 /*CSTYLED*/ 106 extern int iosram_write (int, uint32_t, caddr_t, uint32_t); 107 static int (*iosram_write_ptr)(int, uint32_t, caddr_t, uint32_t) = NULL; 108 /*CSTYLED*/ 109 extern int iosram_read (int, uint32_t, caddr_t, uint32_t); 110 static int (*iosram_read_ptr)(int, uint32_t, caddr_t, uint32_t) = NULL; 111 112 113 /* 114 * Variable to indicate if the date should be obtained from the SC or not. 115 */ 116 int todsg_use_sc = FALSE; /* set the false at the beginning */ 117 118 /* 119 * Preallocation of spare tsb's for DR 120 * 121 * We don't allocate spares for Wildcat since TSBs should come 122 * out of memory local to the node. 123 */ 124 #define IOMMU_PER_SCHIZO 2 125 int serengeti_tsb_spares = (SG_MAX_IO_BDS * SG_SCHIZO_PER_IO_BD * 126 IOMMU_PER_SCHIZO); 127 128 /* 129 * sg_max_ncpus is the maximum number of CPUs supported on Serengeti. 130 * sg_max_ncpus is set to be smaller than NCPU to reduce the amount of 131 * memory the logs take up until we have a dynamic log memory allocation 132 * solution. 133 */ 134 int sg_max_ncpus = (24 * 2); /* (max # of processors * # of cores/proc) */ 135 136 /* 137 * variables to control mailbox message timeouts. 138 * These can be patched via /etc/system or mdb. 139 */ 140 int sbbc_mbox_default_timeout = MBOX_DEFAULT_TIMEOUT; 141 int sbbc_mbox_min_timeout = MBOX_MIN_TIMEOUT; 142 143 /* cached 'chosen' node_id */ 144 pnode_t chosen_nodeid = (pnode_t)0; 145 146 static void (*sg_ecc_taskq_func)(sbbc_ecc_mbox_t *) = NULL; 147 static int (*sg_ecc_mbox_func)(sbbc_ecc_mbox_t *) = NULL; 148 149 /* 150 * Table that maps memory slices to a specific memnode. 151 */ 152 int slice_to_memnode[SG_MAX_SLICE]; 153 154 plat_dimm_sid_board_t domain_dimm_sids[SG_MAX_CPU_BDS]; 155 156 157 int 158 set_platform_tsb_spares() 159 { 160 return (MIN(serengeti_tsb_spares, MAX_UPA)); 161 } 162 163 #pragma weak mmu_init_large_pages 164 165 void 166 set_platform_defaults(void) 167 { 168 extern int watchdog_enable; 169 extern uint64_t xc_tick_limit_scale; 170 extern void mmu_init_large_pages(size_t); 171 172 #ifdef DEBUG 173 char *todsg_name = "todsg"; 174 ce_verbose_memory = 2; 175 ce_verbose_other = 2; 176 #endif /* DEBUG */ 177 178 watchdog_enable = TRUE; 179 watchdog_available = TRUE; 180 181 cpu_sgn_func = cpu_sgn_update; 182 183 #ifdef DEBUG 184 /* tod_module_name should be set to "todsg" from OBP property */ 185 if (tod_module_name && (strcmp(tod_module_name, todsg_name) == 0)) 186 prom_printf("Using todsg driver\n"); 187 else { 188 prom_printf("Force using todsg driver\n"); 189 tod_module_name = todsg_name; 190 } 191 #endif /* DEBUG */ 192 193 /* Serengeti does not support forthdebug */ 194 forthdebug_supported = 0; 195 196 197 /* 198 * Some DR operations require the system to be sync paused. 199 * Sync pause on Serengeti could potentially take up to 4 200 * seconds to complete depending on the load on the SC. To 201 * avoid send_mond panics during such operations, we need to 202 * increase xc_tick_limit to a larger value on Serengeti by 203 * setting xc_tick_limit_scale to 5. 204 */ 205 xc_tick_limit_scale = 5; 206 207 if ((mmu_page_sizes == max_mmu_page_sizes) && 208 (mmu_ism_pagesize != DEFAULT_ISM_PAGESIZE)) { 209 if (&mmu_init_large_pages) 210 mmu_init_large_pages(mmu_ism_pagesize); 211 } 212 } 213 214 void 215 load_platform_modules(void) 216 { 217 if (modload("misc", "pcihp") < 0) { 218 cmn_err(CE_NOTE, "pcihp driver failed to load"); 219 } 220 } 221 222 /*ARGSUSED*/ 223 int 224 plat_cpu_poweron(struct cpu *cp) 225 { 226 int (*serengeti_cpu_poweron)(struct cpu *) = NULL; 227 228 serengeti_cpu_poweron = 229 (int (*)(struct cpu *))modgetsymvalue("sbdp_cpu_poweron", 0); 230 231 if (serengeti_cpu_poweron == NULL) 232 return (ENOTSUP); 233 else 234 return ((serengeti_cpu_poweron)(cp)); 235 } 236 237 /*ARGSUSED*/ 238 int 239 plat_cpu_poweroff(struct cpu *cp) 240 { 241 int (*serengeti_cpu_poweroff)(struct cpu *) = NULL; 242 243 serengeti_cpu_poweroff = 244 (int (*)(struct cpu *))modgetsymvalue("sbdp_cpu_poweroff", 0); 245 246 if (serengeti_cpu_poweroff == NULL) 247 return (ENOTSUP); 248 else 249 return ((serengeti_cpu_poweroff)(cp)); 250 } 251 252 #ifdef DEBUG 253 pgcnt_t serengeti_cage_size_limit; 254 #endif 255 256 /* Preferred minimum cage size (expressed in pages)... for DR */ 257 pgcnt_t serengeti_minimum_cage_size = 0; 258 259 void 260 set_platform_cage_params(void) 261 { 262 extern pgcnt_t total_pages; 263 extern struct memlist *phys_avail; 264 265 if (kernel_cage_enable) { 266 pgcnt_t preferred_cage_size; 267 268 preferred_cage_size = 269 MAX(serengeti_minimum_cage_size, total_pages / 256); 270 #ifdef DEBUG 271 if (serengeti_cage_size_limit) 272 preferred_cage_size = serengeti_cage_size_limit; 273 #endif 274 /* 275 * Post copies obp into the lowest slice. This requires the 276 * cage to grow upwards 277 */ 278 kcage_range_init(phys_avail, KCAGE_UP, preferred_cage_size); 279 } 280 281 kcage_startup_dir = KCAGE_UP; 282 283 /* Only note when the cage is off since it should always be on. */ 284 if (!kcage_on) 285 cmn_err(CE_NOTE, "!DR Kernel Cage is DISABLED"); 286 } 287 288 #define ALIGN(x, a) ((a) == 0 ? (uint64_t)(x) : \ 289 (((uint64_t)(x) + (uint64_t)(a) - 1l) & ~((uint64_t)(a) - 1l))) 290 291 void 292 update_mem_bounds(int brd, uint64_t base, uint64_t sz) 293 { 294 uint64_t end; 295 int mnode; 296 297 end = base + sz - 1; 298 299 /* 300 * First see if this board already has a memnode associated 301 * with it. If not, see if this slice has a memnode. This 302 * covers the cases where a single slice covers multiple 303 * boards (cross-board interleaving) and where a single 304 * board has multiple slices (1+GB DIMMs). 305 */ 306 if ((mnode = plat_lgrphand_to_mem_node(brd)) == -1) { 307 if ((mnode = slice_to_memnode[PA_2_SLICE(base)]) == -1) 308 mnode = mem_node_alloc(); 309 plat_assign_lgrphand_to_mem_node(brd, mnode); 310 } 311 312 /* 313 * Align base at 16GB boundary 314 */ 315 base = ALIGN(base, (1ul << PA_SLICE_SHIFT)); 316 317 while (base < end) { 318 slice_to_memnode[PA_2_SLICE(base)] = mnode; 319 base += (1ul << PA_SLICE_SHIFT); 320 } 321 } 322 323 /* 324 * Dynamically detect memory slices in the system by decoding 325 * the cpu memory decoder registers at boot time. 326 */ 327 void 328 plat_fill_mc(pnode_t nodeid) 329 { 330 uint64_t mc_addr, mask; 331 uint64_t mc_decode[SG_MAX_BANKS_PER_MC]; 332 uint64_t base, size; 333 uint32_t regs[4]; 334 int len; 335 int local_mc; 336 int portid; 337 int boardid; 338 int i; 339 340 if ((prom_getprop(nodeid, "portid", (caddr_t)&portid) < 0) || 341 (portid == -1)) 342 return; 343 344 /* 345 * Decode the board number from the MC portid 346 */ 347 boardid = SG_PORTID_TO_BOARD_NUM(portid); 348 349 /* 350 * The "reg" property returns 4 32-bit values. The first two are 351 * combined to form a 64-bit address. The second two are for a 352 * 64-bit size, but we don't actually need to look at that value. 353 */ 354 len = prom_getproplen(nodeid, "reg"); 355 if (len != (sizeof (uint32_t) * 4)) { 356 prom_printf("Warning: malformed 'reg' property\n"); 357 return; 358 } 359 if (prom_getprop(nodeid, "reg", (caddr_t)regs) < 0) 360 return; 361 mc_addr = ((uint64_t)regs[0]) << 32; 362 mc_addr |= (uint64_t)regs[1]; 363 364 /* 365 * Figure out whether the memory controller we are examining 366 * belongs to this CPU or a different one. 367 */ 368 if (portid == cpunodes[CPU->cpu_id].portid) 369 local_mc = 1; 370 else 371 local_mc = 0; 372 373 for (i = 0; i < SG_MAX_BANKS_PER_MC; i++) { 374 mask = SG_REG_2_OFFSET(i); 375 376 /* 377 * If the memory controller is local to this CPU, we use 378 * the special ASI to read the decode registers. 379 * Otherwise, we load the values from a magic address in 380 * I/O space. 381 */ 382 if (local_mc) 383 mc_decode[i] = lddmcdecode(mask & MC_OFFSET_MASK); 384 else 385 mc_decode[i] = lddphysio((mc_addr | mask)); 386 387 if (mc_decode[i] >> MC_VALID_SHIFT) { 388 /* 389 * The memory decode register is a bitmask field, 390 * so we can decode that into both a base and 391 * a span. 392 */ 393 base = MC_BASE(mc_decode[i]) << PHYS2UM_SHIFT; 394 size = MC_UK2SPAN(mc_decode[i]); 395 update_mem_bounds(boardid, base, size); 396 } 397 } 398 } 399 400 /* 401 * This routine is run midway through the boot process. By the time we get 402 * here, we know about all the active CPU boards in the system, and we have 403 * extracted information about each board's memory from the memory 404 * controllers. We have also figured out which ranges of memory will be 405 * assigned to which memnodes, so we walk the slice table to build the table 406 * of memnodes. 407 */ 408 /* ARGSUSED */ 409 void 410 plat_build_mem_nodes(prom_memlist_t *list, size_t nelems) 411 { 412 int slice; 413 pfn_t basepfn; 414 pgcnt_t npgs; 415 416 mem_node_pfn_shift = PFN_SLICE_SHIFT; 417 mem_node_physalign = (1ull << PA_SLICE_SHIFT); 418 419 for (slice = 0; slice < SG_MAX_SLICE; slice++) { 420 if (slice_to_memnode[slice] == -1) 421 continue; 422 basepfn = (uint64_t)slice << PFN_SLICE_SHIFT; 423 npgs = 1ull << PFN_SLICE_SHIFT; 424 mem_node_add_slice(basepfn, basepfn + npgs - 1); 425 } 426 } 427 428 int 429 plat_pfn_to_mem_node(pfn_t pfn) 430 { 431 int node; 432 433 node = slice_to_memnode[PFN_2_SLICE(pfn)]; 434 435 return (node); 436 } 437 438 /* 439 * Serengeti support for lgroups. 440 * 441 * On Serengeti, an lgroup platform handle == board number. 442 * 443 * Mappings between lgroup handles and memnodes are managed 444 * in addition to mappings between memory slices and memnodes 445 * to support cross-board interleaving as well as multiple 446 * slices per board (e.g. >1GB DIMMs). The initial mapping 447 * of memnodes to lgroup handles is determined at boot time. 448 * A DR addition of memory adds a new mapping. A DR copy-rename 449 * swaps mappings. 450 */ 451 452 /* 453 * Macro for extracting the board number from the CPU id 454 */ 455 #define CPUID_TO_BOARD(id) (((id) >> 2) & 0x7) 456 457 /* 458 * Return the platform handle for the lgroup containing the given CPU 459 * 460 * For Serengeti, lgroup platform handle == board number 461 */ 462 lgrp_handle_t 463 plat_lgrp_cpu_to_hand(processorid_t id) 464 { 465 return (CPUID_TO_BOARD(id)); 466 } 467 468 /* 469 * Platform specific lgroup initialization 470 */ 471 void 472 plat_lgrp_init(void) 473 { 474 int i; 475 extern uint32_t lgrp_expand_proc_thresh; 476 extern uint32_t lgrp_expand_proc_diff; 477 478 /* 479 * Initialize lookup tables to invalid values so we catch 480 * any illegal use of them. 481 */ 482 for (i = 0; i < SG_MAX_SLICE; i++) { 483 slice_to_memnode[i] = -1; 484 } 485 486 /* 487 * Set tuneables for Serengeti architecture 488 * 489 * lgrp_expand_proc_thresh is the minimum load on the lgroups 490 * this process is currently running on before considering 491 * expanding threads to another lgroup. 492 * 493 * lgrp_expand_proc_diff determines how much less the remote lgroup 494 * must be loaded before expanding to it. 495 * 496 * Bandwidth is maximized on Serengeti by spreading load across 497 * the machine. The impact to inter-thread communication isn't 498 * too costly since remote latencies are relatively low. These 499 * values equate to one CPU's load and so attempt to spread the 500 * load out across as many lgroups as possible one CPU at a time. 501 */ 502 lgrp_expand_proc_thresh = LGRP_LOADAVG_THREAD_MAX; 503 lgrp_expand_proc_diff = LGRP_LOADAVG_THREAD_MAX; 504 } 505 506 /* 507 * Platform notification of lgroup (re)configuration changes 508 */ 509 /*ARGSUSED*/ 510 void 511 plat_lgrp_config(lgrp_config_flag_t evt, uintptr_t arg) 512 { 513 update_membounds_t *umb; 514 lgrp_config_mem_rename_t lmr; 515 lgrp_handle_t shand, thand; 516 int snode, tnode; 517 518 switch (evt) { 519 520 case LGRP_CONFIG_MEM_ADD: 521 umb = (update_membounds_t *)arg; 522 update_mem_bounds(umb->u_board, umb->u_base, umb->u_len); 523 524 break; 525 526 case LGRP_CONFIG_MEM_DEL: 527 /* We don't have to do anything */ 528 break; 529 530 case LGRP_CONFIG_MEM_RENAME: 531 /* 532 * During a DR copy-rename operation, all of the memory 533 * on one board is moved to another board -- but the 534 * addresses/pfns and memnodes don't change. This means 535 * the memory has changed locations without changing identity. 536 * 537 * Source is where we are copying from and target is where we 538 * are copying to. After source memnode is copied to target 539 * memnode, the physical addresses of the target memnode are 540 * renamed to match what the source memnode had. Then target 541 * memnode can be removed and source memnode can take its 542 * place. 543 * 544 * To do this, swap the lgroup handle to memnode mappings for 545 * the boards, so target lgroup will have source memnode and 546 * source lgroup will have empty target memnode which is where 547 * its memory will go (if any is added to it later). 548 * 549 * Then source memnode needs to be removed from its lgroup 550 * and added to the target lgroup where the memory was living 551 * but under a different name/memnode. The memory was in the 552 * target memnode and now lives in the source memnode with 553 * different physical addresses even though it is the same 554 * memory. 555 */ 556 shand = arg & 0xffff; 557 thand = (arg & 0xffff0000) >> 16; 558 snode = plat_lgrphand_to_mem_node(shand); 559 tnode = plat_lgrphand_to_mem_node(thand); 560 561 plat_assign_lgrphand_to_mem_node(thand, snode); 562 plat_assign_lgrphand_to_mem_node(shand, tnode); 563 564 /* 565 * Remove source memnode of copy rename from its lgroup 566 * and add it to its new target lgroup 567 */ 568 lmr.lmem_rename_from = shand; 569 lmr.lmem_rename_to = thand; 570 571 lgrp_config(LGRP_CONFIG_MEM_RENAME, (uintptr_t)snode, 572 (uintptr_t)&lmr); 573 574 break; 575 576 default: 577 break; 578 } 579 } 580 581 /* 582 * Return latency between "from" and "to" lgroups 583 * 584 * This latency number can only be used for relative comparison 585 * between lgroups on the running system, cannot be used across platforms, 586 * and may not reflect the actual latency. It is platform and implementation 587 * specific, so platform gets to decide its value. It would be nice if the 588 * number was at least proportional to make comparisons more meaningful though. 589 * NOTE: The numbers below are supposed to be load latencies for uncached 590 * memory divided by 10. 591 */ 592 int 593 plat_lgrp_latency(lgrp_handle_t from, lgrp_handle_t to) 594 { 595 /* 596 * Return min remote latency when there are more than two lgroups 597 * (root and child) and getting latency between two different lgroups 598 * or root is involved 599 */ 600 if (lgrp_optimizations() && (from != to || 601 from == LGRP_DEFAULT_HANDLE || to == LGRP_DEFAULT_HANDLE)) 602 return (28); 603 else 604 return (23); 605 } 606 607 /* ARGSUSED */ 608 void 609 plat_freelist_process(int mnode) 610 { 611 } 612 613 /* 614 * Find dip for chosen IOSRAM 615 */ 616 dev_info_t * 617 find_chosen_dip(void) 618 { 619 dev_info_t *dip; 620 char master_sbbc[MAXNAMELEN]; 621 pnode_t nodeid; 622 uint_t tunnel; 623 624 /* 625 * find the /chosen SBBC node, prom interface will handle errors 626 */ 627 nodeid = prom_chosennode(); 628 629 /* 630 * get the 'iosram' property from the /chosen node 631 */ 632 if (prom_getprop(nodeid, IOSRAM_CHOSEN_PROP, (caddr_t)&tunnel) <= 0) { 633 SBBC_ERR(CE_PANIC, "No iosram property found! \n"); 634 } 635 636 if (prom_phandle_to_path((phandle_t)tunnel, master_sbbc, 637 sizeof (master_sbbc)) < 0) { 638 SBBC_ERR1(CE_PANIC, "prom_phandle_to_path(%d) failed\n", 639 tunnel); 640 } 641 642 chosen_nodeid = nodeid; 643 644 /* 645 * load and attach the sgsbbc driver. 646 * This will also attach all the sgsbbc driver instances 647 */ 648 if (i_ddi_attach_hw_nodes("sgsbbc") != DDI_SUCCESS) { 649 cmn_err(CE_WARN, "sgsbbc failed to load\n"); 650 } 651 652 /* translate a path name to a dev_info_t */ 653 dip = e_ddi_hold_devi_by_path(master_sbbc, 0); 654 if ((dip == NULL) || (ddi_get_nodeid(dip) != tunnel)) { 655 cmn_err(CE_PANIC, "i_ddi_path_to_devi(%x) failed for SBBC\n", 656 tunnel); 657 } 658 659 /* make sure devi_ref is ZERO */ 660 ndi_rele_devi(dip); 661 662 DCMNERR(CE_CONT, "Chosen IOSRAM is at %s \n", master_sbbc); 663 664 return (dip); 665 } 666 667 void 668 load_platform_drivers(void) 669 { 670 int ret; 671 672 /* 673 * Load and attach the mc-us3 memory driver. 674 */ 675 if (i_ddi_attach_hw_nodes("mc-us3") != DDI_SUCCESS) 676 cmn_err(CE_WARN, "mc-us3 failed to load"); 677 else 678 (void) ddi_hold_driver(ddi_name_to_major("mc-us3")); 679 680 /* 681 * Initialize the chosen IOSRAM before its clients 682 * are loaded. 683 */ 684 (void) find_chosen_dip(); 685 686 /* 687 * Ideally, we'd do this in set_platform_defaults(), but 688 * at that point it's too early to look up symbols. 689 */ 690 iosram_write_ptr = (int (*)(int, uint32_t, caddr_t, uint32_t)) 691 modgetsymvalue("iosram_write", 0); 692 693 if (iosram_write_ptr == NULL) { 694 DCMNERR(CE_WARN, "load_platform_defaults: iosram_write()" 695 " not found; signatures will not be updated\n"); 696 } else { 697 /* 698 * The iosram read ptr is only needed if we can actually 699 * write CPU signatures, so only bother setting it if we 700 * set a valid write pointer, above. 701 */ 702 iosram_read_ptr = (int (*)(int, uint32_t, caddr_t, uint32_t)) 703 modgetsymvalue("iosram_read", 0); 704 705 if (iosram_read_ptr == NULL) 706 DCMNERR(CE_WARN, "load_platform_defaults: iosram_read()" 707 " not found\n"); 708 } 709 710 /* 711 * Set todsg_use_sc to TRUE so that we will be getting date 712 * from the SC. 713 */ 714 todsg_use_sc = TRUE; 715 716 /* 717 * Now is a good time to activate hardware watchdog (if one exists). 718 */ 719 mutex_enter(&tod_lock); 720 if (watchdog_enable) 721 ret = tod_ops.tod_set_watchdog_timer(watchdog_timeout_seconds); 722 mutex_exit(&tod_lock); 723 if (ret != 0) 724 printf("Hardware watchdog enabled\n"); 725 726 /* 727 * Load and attach the schizo pci bus nexus driver. 728 */ 729 if (i_ddi_attach_hw_nodes("pcisch") != DDI_SUCCESS) 730 cmn_err(CE_WARN, "pcisch failed to load"); 731 732 plat_ecc_init(); 733 } 734 735 /* 736 * No platform drivers on this platform 737 */ 738 char *platform_module_list[] = { 739 (char *)0 740 }; 741 742 /*ARGSUSED*/ 743 void 744 plat_tod_fault(enum tod_fault_type tod_bad) 745 { 746 } 747 int 748 plat_max_boards() 749 { 750 return (SG_MAX_BDS); 751 } 752 int 753 plat_max_io_units_per_board() 754 { 755 return (SG_MAX_IO_PER_BD); 756 } 757 int 758 plat_max_cmp_units_per_board() 759 { 760 return (SG_MAX_CMPS_PER_BD); 761 } 762 int 763 plat_max_cpu_units_per_board() 764 { 765 return (SG_MAX_CPUS_PER_BD); 766 } 767 768 int 769 plat_max_mc_units_per_board() 770 { 771 return (SG_MAX_CMPS_PER_BD); /* each CPU die has a memory controller */ 772 } 773 774 int 775 plat_max_mem_units_per_board() 776 { 777 return (SG_MAX_MEM_PER_BD); 778 } 779 780 int 781 plat_max_cpumem_boards(void) 782 { 783 return (SG_MAX_CPU_BDS); 784 } 785 786 int 787 set_platform_max_ncpus(void) 788 { 789 return (sg_max_ncpus); 790 } 791 792 void 793 plat_dmv_params(uint_t *hwint, uint_t *swint) 794 { 795 *hwint = MAX_UPA; 796 *swint = 0; 797 } 798 799 /* 800 * Our nodename has been set, pass it along to the SC. 801 */ 802 void 803 plat_nodename_set(void) 804 { 805 sbbc_msg_t req; /* request */ 806 sbbc_msg_t resp; /* response */ 807 int rv; /* return value from call to mbox */ 808 struct nodename_info { 809 int32_t namelen; 810 char nodename[_SYS_NMLN]; 811 } nni; 812 int (*sg_mbox)(sbbc_msg_t *, sbbc_msg_t *, time_t) = NULL; 813 814 /* 815 * find the symbol for the mailbox routine 816 */ 817 sg_mbox = (int (*)(sbbc_msg_t *, sbbc_msg_t *, time_t)) 818 modgetsymvalue("sbbc_mbox_request_response", 0); 819 820 if (sg_mbox == NULL) { 821 cmn_err(CE_NOTE, "!plat_nodename_set: sg_mbox not found\n"); 822 return; 823 } 824 825 /* 826 * construct the message telling the SC our nodename 827 */ 828 (void) strcpy(nni.nodename, utsname.nodename); 829 nni.namelen = (int32_t)strlen(nni.nodename); 830 831 req.msg_type.type = INFO_MBOX; 832 req.msg_type.sub_type = INFO_MBOX_NODENAME; 833 req.msg_status = 0; 834 req.msg_len = (int)(nni.namelen + sizeof (nni.namelen)); 835 req.msg_bytes = 0; 836 req.msg_buf = (caddr_t)&nni; 837 req.msg_data[0] = 0; 838 req.msg_data[1] = 0; 839 840 /* 841 * initialize the response back from the SC 842 */ 843 resp.msg_type.type = INFO_MBOX; 844 resp.msg_type.sub_type = INFO_MBOX_NODENAME; 845 resp.msg_status = 0; 846 resp.msg_len = 0; 847 resp.msg_bytes = 0; 848 resp.msg_buf = (caddr_t)0; 849 resp.msg_data[0] = 0; 850 resp.msg_data[1] = 0; 851 852 /* 853 * ship it and check for success 854 */ 855 rv = (sg_mbox)(&req, &resp, sbbc_mbox_default_timeout); 856 857 if (rv != 0) { 858 cmn_err(CE_NOTE, "!plat_nodename_set: sg_mbox retval %d\n", rv); 859 } else if (resp.msg_status != 0) { 860 cmn_err(CE_NOTE, "!plat_nodename_set: msg_status %d\n", 861 resp.msg_status); 862 } else { 863 DCMNERR(CE_NOTE, "!plat_nodename_set was successful\n"); 864 865 /* 866 * It is necessary to exchange the capability bitmap 867 * with SC before sending any ecc error information and 868 * indictment. We are calling the plat_ecc_capability_send() 869 * here just after sending the nodename successfully. 870 */ 871 rv = plat_ecc_capability_send(); 872 if (rv == 0) { 873 DCMNERR(CE_NOTE, "!plat_ecc_capability_send was" 874 " successful\n"); 875 } 876 } 877 } 878 879 /* 880 * flag to allow users switch between using OBP's 881 * prom_get_unum() and mc-us3 driver's p2get_mem_unum() 882 * (for main memory errors only). 883 */ 884 int sg_use_prom_get_unum = 0; 885 886 /* 887 * Debugging flag: set to 1 to call into obp for get_unum, or set it to 0 888 * to call into the unum cache system. This is the E$ equivalent of 889 * sg_use_prom_get_unum. 890 */ 891 int sg_use_prom_ecache_unum = 0; 892 893 /* used for logging ECC errors to the SC */ 894 #define SG_MEMORY_ECC 1 895 #define SG_ECACHE_ECC 2 896 #define SG_UNKNOWN_ECC (-1) 897 898 /* 899 * plat_get_mem_unum() generates a string identifying either the 900 * memory or E$ DIMM(s) during error logging. Depending on whether 901 * the error is E$ or memory related, the appropriate support 902 * routine is called to assist in the string generation. 903 * 904 * - For main memory errors we can use the mc-us3 drivers p2getunum() 905 * (or prom_get_unum() for debugging purposes). 906 * 907 * - For E$ errors we call sg_get_ecacheunum() to generate the unum (or 908 * prom_serengeti_get_ecacheunum() for debugging purposes). 909 */ 910 911 static int 912 sg_prom_get_unum(int synd_code, uint64_t paddr, char *buf, int buflen, 913 int *lenp) 914 { 915 if ((prom_get_unum(synd_code, (unsigned long long)paddr, 916 buf, buflen, lenp)) != 0) 917 return (EIO); 918 else if (*lenp <= 1) 919 return (EINVAL); 920 else 921 return (0); 922 } 923 924 /*ARGSUSED*/ 925 int 926 plat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id, 927 int flt_in_memory, ushort_t flt_status, char *buf, int buflen, int *lenp) 928 { 929 /* 930 * unum_func will either point to the memory drivers p2get_mem_unum() 931 * or to prom_get_unum() for memory errors. 932 */ 933 int (*unum_func)(int synd_code, uint64_t paddr, char *buf, 934 int buflen, int *lenp) = p2get_mem_unum; 935 936 /* 937 * check if it's a Memory or an Ecache error. 938 */ 939 if (flt_in_memory) { 940 /* 941 * It's a main memory error. 942 * 943 * For debugging we allow the user to switch between 944 * using OBP's get_unum and the memory driver's get_unum 945 * so we create a pointer to the functions and switch 946 * depending on the sg_use_prom_get_unum flag. 947 */ 948 if (sg_use_prom_get_unum) { 949 DCMNERR(CE_NOTE, "Using prom_get_unum from OBP"); 950 return (sg_prom_get_unum(synd_code, 951 P2ALIGN(flt_addr, 8), buf, buflen, lenp)); 952 } else if (unum_func != NULL) { 953 return (unum_func(synd_code, P2ALIGN(flt_addr, 8), 954 buf, buflen, lenp)); 955 } else { 956 return (ENOTSUP); 957 } 958 } else if (flt_status & ECC_ECACHE) { 959 /* 960 * It's an E$ error. 961 */ 962 if (sg_use_prom_ecache_unum) { 963 /* 964 * We call to OBP to handle this. 965 */ 966 DCMNERR(CE_NOTE, 967 "Using prom_serengeti_get_ecacheunum from OBP"); 968 if (prom_serengeti_get_ecacheunum(flt_bus_id, 969 P2ALIGN(flt_addr, 8), buf, buflen, lenp) != 0) { 970 return (EIO); 971 } 972 } else { 973 return (sg_get_ecacheunum(flt_bus_id, flt_addr, 974 buf, buflen, lenp)); 975 } 976 } else { 977 return (ENOTSUP); 978 } 979 980 return (0); 981 } 982 983 /* 984 * This platform hook gets called from mc_add_mem_unum_label() in the mc-us3 985 * driver giving each platform the opportunity to add platform 986 * specific label information to the unum for ECC error logging purposes. 987 */ 988 void 989 plat_add_mem_unum_label(char *unum, int mcid, int bank, int dimm) 990 { 991 char new_unum[UNUM_NAMLEN] = ""; 992 int node = SG_PORTID_TO_NODEID(mcid); 993 int board = SG_CPU_BD_PORTID_TO_BD_NUM(mcid); 994 int position = SG_PORTID_TO_CPU_POSN(mcid); 995 996 /* 997 * The mc-us3 driver deals with logical banks but for unum 998 * purposes we need to use physical banks so that the correct 999 * dimm can be physically located. Logical banks 0 and 2 1000 * make up physical bank 0. Logical banks 1 and 3 make up 1001 * physical bank 1. Here we do the necessary conversion. 1002 */ 1003 bank = (bank % 2); 1004 1005 if (dimm == -1) { 1006 SG_SET_FRU_NAME_NODE(new_unum, node); 1007 SG_SET_FRU_NAME_CPU_BOARD(new_unum, board); 1008 SG_SET_FRU_NAME_MODULE(new_unum, position); 1009 SG_SET_FRU_NAME_BANK(new_unum, bank); 1010 1011 } else { 1012 SG_SET_FRU_NAME_NODE(new_unum, node); 1013 SG_SET_FRU_NAME_CPU_BOARD(new_unum, board); 1014 SG_SET_FRU_NAME_MODULE(new_unum, position); 1015 SG_SET_FRU_NAME_BANK(new_unum, bank); 1016 SG_SET_FRU_NAME_DIMM(new_unum, dimm); 1017 1018 strcat(new_unum, " "); 1019 strcat(new_unum, unum); 1020 } 1021 1022 strcpy(unum, new_unum); 1023 } 1024 1025 int 1026 plat_get_cpu_unum(int cpuid, char *buf, int buflen, int *lenp) 1027 { 1028 int node = SG_PORTID_TO_NODEID(cpuid); 1029 int board = SG_CPU_BD_PORTID_TO_BD_NUM(cpuid); 1030 1031 if (snprintf(buf, buflen, "/N%d/%s%d", node, 1032 SG_HPU_TYPE_CPU_BOARD_ID, board) >= buflen) { 1033 return (ENOSPC); 1034 } else { 1035 *lenp = strlen(buf); 1036 return (0); 1037 } 1038 } 1039 1040 /* 1041 * We log all ECC events to the SC so we send a mailbox 1042 * message to the SC passing it the relevant data. 1043 * ECC mailbox messages are sent via a taskq mechanism to 1044 * prevent impaired system performance during ECC floods. 1045 * Indictments have already passed through a taskq, so they 1046 * are not queued here. 1047 */ 1048 int 1049 plat_send_ecc_mailbox_msg(plat_ecc_message_type_t msg_type, void *datap) 1050 { 1051 sbbc_ecc_mbox_t *msgp; 1052 size_t msg_size; 1053 uint16_t msg_subtype; 1054 int sleep_flag, log_error; 1055 1056 if (sg_ecc_taskq_func == NULL) { 1057 sg_ecc_taskq_func = (void (*)(sbbc_ecc_mbox_t *)) 1058 modgetsymvalue("sbbc_mbox_queue_ecc_event", 0); 1059 if (sg_ecc_taskq_func == NULL) { 1060 cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: " 1061 "sbbc_mbox_queue_ecc_event not found"); 1062 return (ENODEV); 1063 } 1064 } 1065 if (sg_ecc_mbox_func == NULL) { 1066 sg_ecc_mbox_func = (int (*)(sbbc_ecc_mbox_t *)) 1067 modgetsymvalue("sbbc_mbox_ecc_output", 0); 1068 if (sg_ecc_mbox_func == NULL) { 1069 cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: " 1070 "sbbc_mbox_ecc_output not found"); 1071 return (ENODEV); 1072 } 1073 } 1074 1075 /* 1076 * Initialize the request and response structures 1077 */ 1078 switch (msg_type) { 1079 case PLAT_ECC_ERROR_MESSAGE: 1080 msg_subtype = INFO_MBOX_ERROR_ECC; 1081 msg_size = sizeof (plat_ecc_error_data_t); 1082 sleep_flag = KM_NOSLEEP; 1083 log_error = 1; 1084 break; 1085 case PLAT_ECC_ERROR2_MESSAGE: 1086 msg_subtype = INFO_MBOX_ECC; 1087 msg_size = sizeof (plat_ecc_error2_data_t); 1088 sleep_flag = KM_NOSLEEP; 1089 log_error = 1; 1090 break; 1091 case PLAT_ECC_INDICTMENT_MESSAGE: 1092 msg_subtype = INFO_MBOX_ERROR_INDICT; 1093 msg_size = sizeof (plat_ecc_indictment_data_t); 1094 sleep_flag = KM_SLEEP; 1095 log_error = 0; 1096 break; 1097 case PLAT_ECC_INDICTMENT2_MESSAGE: 1098 msg_subtype = INFO_MBOX_ECC; 1099 msg_size = sizeof (plat_ecc_indictment2_data_t); 1100 sleep_flag = KM_SLEEP; 1101 log_error = 0; 1102 break; 1103 case PLAT_ECC_CAPABILITY_MESSAGE: 1104 msg_subtype = INFO_MBOX_ECC_CAP; 1105 msg_size = sizeof (plat_capability_data_t) + 1106 strlen(utsname.release) + strlen(utsname.version) + 2; 1107 sleep_flag = KM_SLEEP; 1108 log_error = 0; 1109 break; 1110 case PLAT_ECC_DIMM_SID_MESSAGE: 1111 msg_subtype = INFO_MBOX_ECC; 1112 msg_size = sizeof (plat_dimm_sid_request_data_t); 1113 sleep_flag = KM_SLEEP; 1114 log_error = 0; 1115 break; 1116 default: 1117 return (EINVAL); 1118 } 1119 1120 msgp = (sbbc_ecc_mbox_t *)kmem_zalloc(sizeof (sbbc_ecc_mbox_t), 1121 sleep_flag); 1122 if (msgp == NULL) { 1123 cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: " 1124 "unable to allocate sbbc_ecc_mbox"); 1125 return (ENOMEM); 1126 } 1127 1128 msgp->ecc_log_error = log_error; 1129 1130 msgp->ecc_req.msg_type.type = INFO_MBOX; 1131 msgp->ecc_req.msg_type.sub_type = msg_subtype; 1132 msgp->ecc_req.msg_status = 0; 1133 msgp->ecc_req.msg_len = (int)msg_size; 1134 msgp->ecc_req.msg_bytes = 0; 1135 msgp->ecc_req.msg_buf = (caddr_t)kmem_zalloc(msg_size, sleep_flag); 1136 msgp->ecc_req.msg_data[0] = 0; 1137 msgp->ecc_req.msg_data[1] = 0; 1138 1139 if (msgp->ecc_req.msg_buf == NULL) { 1140 cmn_err(CE_NOTE, "!plat_send_ecc_mailbox_msg: " 1141 "unable to allocate request msg_buf"); 1142 kmem_free((void *)msgp, sizeof (sbbc_ecc_mbox_t)); 1143 return (ENOMEM); 1144 } 1145 bcopy(datap, (void *)msgp->ecc_req.msg_buf, msg_size); 1146 1147 /* 1148 * initialize the response back from the SC 1149 */ 1150 msgp->ecc_resp.msg_type.type = INFO_MBOX; 1151 msgp->ecc_resp.msg_type.sub_type = msg_subtype; 1152 msgp->ecc_resp.msg_status = 0; 1153 msgp->ecc_resp.msg_len = 0; 1154 msgp->ecc_resp.msg_bytes = 0; 1155 msgp->ecc_resp.msg_buf = NULL; 1156 msgp->ecc_resp.msg_data[0] = 0; 1157 msgp->ecc_resp.msg_data[1] = 0; 1158 1159 switch (msg_type) { 1160 case PLAT_ECC_ERROR_MESSAGE: 1161 case PLAT_ECC_ERROR2_MESSAGE: 1162 /* 1163 * For Error Messages, we go through a taskq. 1164 * Queue up the message for processing 1165 */ 1166 (*sg_ecc_taskq_func)(msgp); 1167 return (0); 1168 1169 case PLAT_ECC_CAPABILITY_MESSAGE: 1170 /* 1171 * For indictment and capability messages, we've already gone 1172 * through the taskq, so we can call the mailbox routine 1173 * directly. Find the symbol for the routine that sends 1174 * the mailbox msg 1175 */ 1176 msgp->ecc_resp.msg_len = (int)msg_size; 1177 msgp->ecc_resp.msg_buf = (caddr_t)kmem_zalloc(msg_size, 1178 sleep_flag); 1179 /* FALLTHRU */ 1180 1181 case PLAT_ECC_INDICTMENT_MESSAGE: 1182 case PLAT_ECC_INDICTMENT2_MESSAGE: 1183 return ((*sg_ecc_mbox_func)(msgp)); 1184 1185 case PLAT_ECC_DIMM_SID_MESSAGE: 1186 msgp->ecc_resp.msg_len = sizeof (plat_dimm_sid_board_data_t); 1187 msgp->ecc_resp.msg_buf = (caddr_t)kmem_zalloc( 1188 sizeof (plat_dimm_sid_board_data_t), sleep_flag); 1189 return ((*sg_ecc_mbox_func)(msgp)); 1190 1191 default: 1192 ASSERT(0); 1193 return (EINVAL); 1194 } 1195 } 1196 1197 /* 1198 * m is redundant on serengeti as the multiplier is always 4 1199 */ 1200 /*ARGSUSED*/ 1201 int 1202 plat_make_fru_cpuid(int sb, int m, int proc) 1203 { 1204 return (MAKE_CPUID(sb, proc)); 1205 } 1206 1207 /* 1208 * board number for a given proc 1209 */ 1210 int 1211 plat_make_fru_boardnum(int proc) 1212 { 1213 return (SG_CPU_BD_PORTID_TO_BD_NUM(proc)); 1214 } 1215 1216 static 1217 void 1218 cpu_sgn_update(ushort_t sig, uchar_t state, uchar_t sub_state, int cpuid) 1219 { 1220 uint32_t signature = CPU_SIG_BLD(sig, state, sub_state); 1221 sig_state_t current_sgn; 1222 int i; 1223 1224 if (iosram_write_ptr == NULL) { 1225 /* 1226 * If the IOSRAM write pointer isn't set, we won't be able 1227 * to write signatures to ANYTHING, so we may as well just 1228 * write out an error message (if desired) and exit this 1229 * routine now... 1230 */ 1231 DCMNERR(CE_WARN, 1232 "cpu_sgn_update: iosram_write() not found;" 1233 " cannot write signature 0x%x for CPU(s) or domain\n", 1234 signature); 1235 return; 1236 } 1237 1238 1239 /* 1240 * Differentiate a panic reboot from a non-panic reboot in the 1241 * setting of the substate of the signature. 1242 * 1243 * If the new substate is REBOOT and we're rebooting due to a panic, 1244 * then set the new substate to a special value indicating a panic 1245 * reboot, SIGSUBST_PANIC_REBOOT. 1246 * 1247 * A panic reboot is detected by a current (previous) domain signature 1248 * state of SIGST_EXIT, and a new signature substate of SIGSUBST_REBOOT. 1249 * The domain signature state SIGST_EXIT is used as the panic flow 1250 * progresses. 1251 * 1252 * At the end of the panic flow, the reboot occurs but we should now 1253 * one that was involuntary, something that may be quite useful to know 1254 * at OBP level. 1255 */ 1256 if (sub_state == SIGSUBST_REBOOT) { 1257 if (iosram_read_ptr == NULL) { 1258 DCMNERR(CE_WARN, 1259 "cpu_sgn_update: iosram_read() not found;" 1260 " could not check current domain signature\n"); 1261 } else { 1262 (void) (*iosram_read_ptr)(SBBC_SIGBLCK_KEY, 1263 SG_SGNBLK_DOMAINSIG_OFFSET, 1264 (char *)¤t_sgn, sizeof (current_sgn)); 1265 if (current_sgn.state_t.state == SIGST_EXIT) 1266 signature = CPU_SIG_BLD(sig, state, 1267 SIGSUBST_PANIC_REBOOT); 1268 } 1269 } 1270 1271 /* 1272 * cpuid == -1 indicates that the operation applies to all cpus. 1273 */ 1274 if (cpuid >= 0) { 1275 (void) (*iosram_write_ptr)(SBBC_SIGBLCK_KEY, 1276 SG_SGNBLK_CPUSIG_OFFSET(cpuid), (char *)&signature, 1277 sizeof (signature)); 1278 } else { 1279 for (i = 0; i < NCPU; i++) { 1280 if (cpu[i] == NULL || !(cpu[i]->cpu_flags & 1281 (CPU_EXISTS|CPU_QUIESCED))) { 1282 continue; 1283 } 1284 (void) (*iosram_write_ptr)(SBBC_SIGBLCK_KEY, 1285 SG_SGNBLK_CPUSIG_OFFSET(i), (char *)&signature, 1286 sizeof (signature)); 1287 } 1288 } 1289 1290 if (state == SIGST_OFFLINE || state == SIGST_DETACHED) { 1291 return; 1292 } 1293 1294 (void) (*iosram_write_ptr)(SBBC_SIGBLCK_KEY, 1295 SG_SGNBLK_DOMAINSIG_OFFSET, (char *)&signature, 1296 sizeof (signature)); 1297 } 1298 1299 void 1300 startup_platform(void) 1301 { 1302 /* set per-platform constants for mutex backoff */ 1303 mutex_backoff_base = 1; 1304 mutex_cap_factor = 32; 1305 } 1306 1307 /* 1308 * A routine to convert a number (represented as a string) to 1309 * the integer value it represents. 1310 */ 1311 1312 static int 1313 isdigit(int ch) 1314 { 1315 return (ch >= '0' && ch <= '9'); 1316 } 1317 1318 #define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') 1319 1320 static int 1321 strtoi(char *p, char **pos) 1322 { 1323 int n; 1324 int c, neg = 0; 1325 1326 if (!isdigit(c = *p)) { 1327 while (isspace(c)) 1328 c = *++p; 1329 switch (c) { 1330 case '-': 1331 neg++; 1332 /* FALLTHROUGH */ 1333 case '+': 1334 c = *++p; 1335 } 1336 if (!isdigit(c)) { 1337 if (pos != NULL) 1338 *pos = p; 1339 return (0); 1340 } 1341 } 1342 for (n = '0' - c; isdigit(c = *++p); ) { 1343 n *= 10; /* two steps to avoid unnecessary overflow */ 1344 n += '0' - c; /* accum neg to avoid surprises at MAX */ 1345 } 1346 if (pos != NULL) 1347 *pos = p; 1348 return (neg ? n : -n); 1349 } 1350 1351 /* 1352 * Get the three parts of the Serengeti PROM version. 1353 * Used for feature readiness tests. 1354 * 1355 * Return 0 if version extracted successfully, -1 otherwise. 1356 */ 1357 1358 int 1359 sg_get_prom_version(int *sysp, int *intfp, int *bldp) 1360 { 1361 int plen; 1362 char vers[512]; 1363 static pnode_t node; 1364 static char version[] = "version"; 1365 char *verp, *ep; 1366 1367 node = prom_finddevice("/openprom"); 1368 if (node == OBP_BADNODE) 1369 return (-1); 1370 1371 plen = prom_getproplen(node, version); 1372 if (plen <= 0 || plen >= sizeof (vers)) 1373 return (-1); 1374 (void) prom_getprop(node, version, vers); 1375 vers[plen] = '\0'; 1376 1377 /* Make sure it's an OBP flashprom */ 1378 if (vers[0] != 'O' && vers[1] != 'B' && vers[2] != 'P') { 1379 cmn_err(CE_WARN, "sg_get_prom_version: " 1380 "unknown <version> string in </openprom>\n"); 1381 return (-1); 1382 } 1383 verp = &vers[4]; 1384 1385 *sysp = strtoi(verp, &ep); 1386 if (ep == verp || *ep != '.') 1387 return (-1); 1388 verp = ep + 1; 1389 1390 *intfp = strtoi(verp, &ep); 1391 if (ep == verp || *ep != '.') 1392 return (-1); 1393 verp = ep + 1; 1394 1395 *bldp = strtoi(verp, &ep); 1396 if (ep == verp || (*ep != '\0' && !isspace(*ep))) 1397 return (-1); 1398 return (0); 1399 } 1400 1401 /* 1402 * Return 0 if system board Dynamic Reconfiguration 1403 * is supported by the firmware, -1 otherwise. 1404 */ 1405 int 1406 sg_prom_sb_dr_check(void) 1407 { 1408 static int prom_res = 1; 1409 1410 if (prom_res == 1) { 1411 int sys, intf, bld; 1412 int rv; 1413 1414 rv = sg_get_prom_version(&sys, &intf, &bld); 1415 if (rv == 0 && sys == 5 && 1416 (intf >= 12 || (intf == 11 && bld >= 200))) { 1417 prom_res = 0; 1418 } else { 1419 prom_res = -1; 1420 } 1421 } 1422 return (prom_res); 1423 } 1424 1425 /* 1426 * Return 0 if cPCI Dynamic Reconfiguration 1427 * is supported by the firmware, -1 otherwise. 1428 */ 1429 int 1430 sg_prom_cpci_dr_check(void) 1431 { 1432 /* 1433 * The version check is currently the same as for 1434 * system boards. Since the two DR sub-systems are 1435 * independent, this could change. 1436 */ 1437 return (sg_prom_sb_dr_check()); 1438 } 1439 1440 /* 1441 * KDI functions - used by the in-situ kernel debugger (kmdb) to perform 1442 * platform-specific operations. These functions execute when the world is 1443 * stopped, and as such cannot make any blocking calls, hold locks, etc. 1444 * promif functions are a special case, and may be used. 1445 */ 1446 1447 /* 1448 * Our implementation of this KDI op updates the CPU signature in the system 1449 * controller. Note that we set the signature to OBP_SIG, rather than DBG_SIG. 1450 * The Forth words we execute will, among other things, transform our OBP_SIG 1451 * into DBG_SIG. They won't function properly if we try to use DBG_SIG. 1452 */ 1453 static void 1454 sg_system_claim(void) 1455 { 1456 prom_interpret("sigb-sig! my-sigb-sig!", OBP_SIG, OBP_SIG, 0, 0, 0); 1457 } 1458 1459 static void 1460 sg_system_release(void) 1461 { 1462 prom_interpret("sigb-sig! my-sigb-sig!", OS_SIG, OS_SIG, 0, 0, 0); 1463 } 1464 1465 static void 1466 sg_console_claim(void) 1467 { 1468 prom_serengeti_set_console_input(SGCN_OBP_STR); 1469 } 1470 1471 static void 1472 sg_console_release(void) 1473 { 1474 prom_serengeti_set_console_input(SGCN_CLNT_STR); 1475 } 1476 1477 void 1478 plat_kdi_init(kdi_t *kdi) 1479 { 1480 kdi->pkdi_system_claim = sg_system_claim; 1481 kdi->pkdi_system_release = sg_system_release; 1482 kdi->pkdi_console_claim = sg_console_claim; 1483 kdi->pkdi_console_release = sg_console_release; 1484 } 1485