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