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 2007 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 #include <sys/cpuvar.h> 29 #include <sys/systm.h> 30 #include <sys/sysmacros.h> 31 #include <sys/promif.h> 32 #include <sys/platform_module.h> 33 #include <sys/cmn_err.h> 34 #include <sys/errno.h> 35 #include <sys/machsystm.h> 36 #include <sys/bootconf.h> 37 #include <sys/nvpair.h> 38 #include <sys/kobj.h> 39 #include <sys/mem_cage.h> 40 #include <sys/opl.h> 41 #include <sys/scfd/scfostoescf.h> 42 #include <sys/cpu_sgnblk_defs.h> 43 #include <sys/utsname.h> 44 #include <sys/ddi.h> 45 #include <sys/sunndi.h> 46 #include <sys/lgrp.h> 47 #include <sys/memnode.h> 48 #include <sys/sysmacros.h> 49 #include <sys/time.h> 50 #include <sys/cpu.h> 51 #include <vm/vm_dep.h> 52 53 int (*opl_get_mem_unum)(int, uint64_t, char *, int, int *); 54 int (*opl_get_mem_sid)(char *unum, char *buf, int buflen, int *lenp); 55 int (*opl_get_mem_offset)(uint64_t paddr, uint64_t *offp); 56 int (*opl_get_mem_addr)(char *unum, char *sid, 57 uint64_t offset, uint64_t *paddr); 58 59 /* Memory for fcode claims. 16k times # maximum possible IO units */ 60 #define EFCODE_SIZE (OPL_MAX_BOARDS * OPL_MAX_IO_UNITS_PER_BOARD * 0x4000) 61 int efcode_size = EFCODE_SIZE; 62 63 #define OPL_MC_MEMBOARD_SHIFT 38 /* Boards on 256BG boundary */ 64 65 /* Set the maximum number of boards for DR */ 66 int opl_boards = OPL_MAX_BOARDS; 67 68 void sgn_update_all_cpus(ushort_t, uchar_t, uchar_t); 69 70 extern int tsb_lgrp_affinity; 71 72 int opl_tsb_spares = (OPL_MAX_BOARDS) * (OPL_MAX_PCICH_UNITS_PER_BOARD) * 73 (OPL_MAX_TSBS_PER_PCICH); 74 75 pgcnt_t opl_startup_cage_size = 0; 76 77 static opl_model_info_t opl_models[] = { 78 { "FF1", OPL_MAX_BOARDS_FF1, FF1, STD_DISPATCH_TABLE }, 79 { "FF2", OPL_MAX_BOARDS_FF2, FF2, STD_DISPATCH_TABLE }, 80 { "DC1", OPL_MAX_BOARDS_DC1, DC1, STD_DISPATCH_TABLE }, 81 { "DC2", OPL_MAX_BOARDS_DC2, DC2, EXT_DISPATCH_TABLE }, 82 { "DC3", OPL_MAX_BOARDS_DC3, DC3, EXT_DISPATCH_TABLE }, 83 }; 84 static int opl_num_models = sizeof (opl_models)/sizeof (opl_model_info_t); 85 86 /* 87 * opl_cur_model 88 */ 89 static opl_model_info_t *opl_cur_model = NULL; 90 91 static struct memlist *opl_memlist_per_board(struct memlist *ml); 92 93 /* 94 * Note FF/DC out-of-order instruction engine takes only a 95 * single cycle to execute each spin loop 96 * for comparison, Panther takes 6 cycles for same loop 97 * 1500 approx nsec for OPL sleep instruction 98 * if spin count = OPL_BOFF_SLEEP*OPL_BOFF_SPIN then 99 * spin time should be equal to OPL_BOFF_TM nsecs 100 * Listed values tuned for 2.15GHz to 2.4GHz systems 101 * Value may change for future systems 102 */ 103 #define OPL_BOFF_SPIN 720 104 #define OPL_BOFF_BASE 1 105 #define OPL_BOFF_SLEEP 5 106 #define OPL_BOFF_CAP1 20 107 #define OPL_BOFF_CAP2 60 108 #define OPL_BOFF_MAX (40 * OPL_BOFF_SLEEP) 109 #define OPL_BOFF_TM 1500 110 111 int 112 set_platform_max_ncpus(void) 113 { 114 return (OPL_MAX_CPU_PER_BOARD * OPL_MAX_BOARDS); 115 } 116 117 int 118 set_platform_tsb_spares(void) 119 { 120 return (MIN(opl_tsb_spares, MAX_UPA)); 121 } 122 123 static void 124 set_model_info() 125 { 126 extern int ts_dispatch_extended; 127 char name[MAXSYSNAME]; 128 int i; 129 130 /* 131 * Get model name from the root node. 132 * 133 * We are using the prom device tree since, at this point, 134 * the Solaris device tree is not yet setup. 135 */ 136 (void) prom_getprop(prom_rootnode(), "model", (caddr_t)name); 137 138 for (i = 0; i < opl_num_models; i++) { 139 if (strncmp(name, opl_models[i].model_name, MAXSYSNAME) == 0) { 140 opl_cur_model = &opl_models[i]; 141 break; 142 } 143 } 144 145 if (i == opl_num_models) 146 halt("No valid OPL model is found!"); 147 148 if ((opl_cur_model->model_cmds & EXT_DISPATCH_TABLE) && 149 (ts_dispatch_extended == -1)) { 150 /* 151 * Based on a platform model, select a dispatch table. 152 * Only DC2 and DC3 systems uses the alternate/extended 153 * TS dispatch table. 154 * FF1, FF2 and DC1 systems used standard dispatch tables. 155 */ 156 ts_dispatch_extended = 1; 157 } 158 159 } 160 161 static void 162 set_max_mmu_ctxdoms() 163 { 164 extern uint_t max_mmu_ctxdoms; 165 int max_boards; 166 167 /* 168 * From the model, get the maximum number of boards 169 * supported and set the value accordingly. If the model 170 * could not be determined or recognized, we assume the max value. 171 */ 172 if (opl_cur_model == NULL) 173 max_boards = OPL_MAX_BOARDS; 174 else 175 max_boards = opl_cur_model->model_max_boards; 176 177 /* 178 * On OPL, cores and MMUs are one-to-one. 179 */ 180 max_mmu_ctxdoms = OPL_MAX_CORE_UNITS_PER_BOARD * max_boards; 181 } 182 183 #pragma weak mmu_init_large_pages 184 185 void 186 set_platform_defaults(void) 187 { 188 extern char *tod_module_name; 189 extern void cpu_sgn_update(ushort_t, uchar_t, uchar_t, int); 190 extern void mmu_init_large_pages(size_t); 191 192 /* Set the CPU signature function pointer */ 193 cpu_sgn_func = cpu_sgn_update; 194 195 /* Set appropriate tod module for OPL platform */ 196 ASSERT(tod_module_name == NULL); 197 tod_module_name = "todopl"; 198 199 if ((mmu_page_sizes == max_mmu_page_sizes) && 200 (mmu_ism_pagesize != DEFAULT_ISM_PAGESIZE)) { 201 if (&mmu_init_large_pages) 202 mmu_init_large_pages(mmu_ism_pagesize); 203 } 204 205 tsb_lgrp_affinity = 1; 206 207 set_max_mmu_ctxdoms(); 208 } 209 210 /* 211 * Convert logical a board number to a physical one. 212 */ 213 214 #define LSBPROP "board#" 215 #define PSBPROP "physical-board#" 216 217 int 218 opl_get_physical_board(int id) 219 { 220 dev_info_t *root_dip, *dip = NULL; 221 char *dname = NULL; 222 int circ; 223 224 pnode_t pnode; 225 char pname[MAXSYSNAME] = {0}; 226 227 int lsb_id; /* Logical System Board ID */ 228 int psb_id; /* Physical System Board ID */ 229 230 231 /* 232 * This function is called on early stage of bootup when the 233 * kernel device tree is not initialized yet, and also 234 * later on when the device tree is up. We want to try 235 * the fast track first. 236 */ 237 root_dip = ddi_root_node(); 238 if (root_dip) { 239 /* Get from devinfo node */ 240 ndi_devi_enter(root_dip, &circ); 241 for (dip = ddi_get_child(root_dip); dip; 242 dip = ddi_get_next_sibling(dip)) { 243 244 dname = ddi_node_name(dip); 245 if (strncmp(dname, "pseudo-mc", 9) != 0) 246 continue; 247 248 if ((lsb_id = (int)ddi_getprop(DDI_DEV_T_ANY, dip, 249 DDI_PROP_DONTPASS, LSBPROP, -1)) == -1) 250 continue; 251 252 if (id == lsb_id) { 253 if ((psb_id = (int)ddi_getprop(DDI_DEV_T_ANY, 254 dip, DDI_PROP_DONTPASS, PSBPROP, -1)) 255 == -1) { 256 ndi_devi_exit(root_dip, circ); 257 return (-1); 258 } else { 259 ndi_devi_exit(root_dip, circ); 260 return (psb_id); 261 } 262 } 263 } 264 ndi_devi_exit(root_dip, circ); 265 } 266 267 /* 268 * We do not have the kernel device tree, or we did not 269 * find the node for some reason (let's say the kernel 270 * device tree was modified), let's try the OBP tree. 271 */ 272 pnode = prom_rootnode(); 273 for (pnode = prom_childnode(pnode); pnode; 274 pnode = prom_nextnode(pnode)) { 275 276 if ((prom_getprop(pnode, "name", (caddr_t)pname) == -1) || 277 (strncmp(pname, "pseudo-mc", 9) != 0)) 278 continue; 279 280 if (prom_getprop(pnode, LSBPROP, (caddr_t)&lsb_id) == -1) 281 continue; 282 283 if (id == lsb_id) { 284 if (prom_getprop(pnode, PSBPROP, 285 (caddr_t)&psb_id) == -1) { 286 return (-1); 287 } else { 288 return (psb_id); 289 } 290 } 291 } 292 293 return (-1); 294 } 295 296 /* 297 * For OPL it's possible that memory from two or more successive boards 298 * will be contiguous across the boards, and therefore represented as a 299 * single chunk. 300 * This function splits such chunks down the board boundaries. 301 */ 302 static struct memlist * 303 opl_memlist_per_board(struct memlist *ml) 304 { 305 uint64_t ssize, low, high, boundary; 306 struct memlist *head, *tail, *new; 307 308 ssize = (1ull << OPL_MC_MEMBOARD_SHIFT); 309 310 head = tail = NULL; 311 312 for (; ml; ml = ml->next) { 313 low = (uint64_t)ml->address; 314 high = low+(uint64_t)(ml->size); 315 while (low < high) { 316 boundary = roundup(low+1, ssize); 317 boundary = MIN(high, boundary); 318 new = kmem_zalloc(sizeof (struct memlist), KM_SLEEP); 319 new->address = low; 320 new->size = boundary - low; 321 if (head == NULL) 322 head = new; 323 if (tail) { 324 tail->next = new; 325 new->prev = tail; 326 } 327 tail = new; 328 low = boundary; 329 } 330 } 331 return (head); 332 } 333 334 void 335 set_platform_cage_params(void) 336 { 337 extern pgcnt_t total_pages; 338 extern struct memlist *phys_avail; 339 struct memlist *ml, *tml; 340 int ret; 341 342 if (kernel_cage_enable) { 343 pgcnt_t preferred_cage_size; 344 345 preferred_cage_size = 346 MAX(opl_startup_cage_size, total_pages / 256); 347 348 ml = opl_memlist_per_board(phys_avail); 349 350 kcage_range_lock(); 351 /* 352 * Note: we are assuming that post has load the 353 * whole show in to the high end of memory. Having 354 * taken this leap, we copy the whole of phys_avail 355 * the glist and arrange for the cage to grow 356 * downward (descending pfns). 357 */ 358 ret = kcage_range_init(ml, 1); 359 360 /* free the memlist */ 361 do { 362 tml = ml->next; 363 kmem_free(ml, sizeof (struct memlist)); 364 ml = tml; 365 } while (ml != NULL); 366 367 if (ret == 0) 368 kcage_init(preferred_cage_size); 369 kcage_range_unlock(); 370 } 371 372 if (kcage_on) 373 cmn_err(CE_NOTE, "!DR Kernel Cage is ENABLED"); 374 else 375 cmn_err(CE_NOTE, "!DR Kernel Cage is DISABLED"); 376 } 377 378 /*ARGSUSED*/ 379 int 380 plat_cpu_poweron(struct cpu *cp) 381 { 382 int (*opl_cpu_poweron)(struct cpu *) = NULL; 383 384 opl_cpu_poweron = 385 (int (*)(struct cpu *))kobj_getsymvalue("drmach_cpu_poweron", 0); 386 387 if (opl_cpu_poweron == NULL) 388 return (ENOTSUP); 389 else 390 return ((opl_cpu_poweron)(cp)); 391 392 } 393 394 /*ARGSUSED*/ 395 int 396 plat_cpu_poweroff(struct cpu *cp) 397 { 398 int (*opl_cpu_poweroff)(struct cpu *) = NULL; 399 400 opl_cpu_poweroff = 401 (int (*)(struct cpu *))kobj_getsymvalue("drmach_cpu_poweroff", 0); 402 403 if (opl_cpu_poweroff == NULL) 404 return (ENOTSUP); 405 else 406 return ((opl_cpu_poweroff)(cp)); 407 408 } 409 410 int 411 plat_max_boards(void) 412 { 413 return (OPL_MAX_BOARDS); 414 } 415 416 int 417 plat_max_cpu_units_per_board(void) 418 { 419 return (OPL_MAX_CPU_PER_BOARD); 420 } 421 422 int 423 plat_max_mem_units_per_board(void) 424 { 425 return (OPL_MAX_MEM_UNITS_PER_BOARD); 426 } 427 428 int 429 plat_max_io_units_per_board(void) 430 { 431 return (OPL_MAX_IO_UNITS_PER_BOARD); 432 } 433 434 int 435 plat_max_cmp_units_per_board(void) 436 { 437 return (OPL_MAX_CMP_UNITS_PER_BOARD); 438 } 439 440 int 441 plat_max_core_units_per_board(void) 442 { 443 return (OPL_MAX_CORE_UNITS_PER_BOARD); 444 } 445 446 int 447 plat_pfn_to_mem_node(pfn_t pfn) 448 { 449 return (pfn >> mem_node_pfn_shift); 450 } 451 452 /* ARGSUSED */ 453 void 454 plat_build_mem_nodes(u_longlong_t *list, size_t nelems) 455 { 456 size_t elem; 457 pfn_t basepfn; 458 pgcnt_t npgs; 459 uint64_t boundary, ssize; 460 uint64_t low, high; 461 462 /* 463 * OPL mem slices are always aligned on a 256GB boundary. 464 */ 465 mem_node_pfn_shift = OPL_MC_MEMBOARD_SHIFT - MMU_PAGESHIFT; 466 mem_node_physalign = 0; 467 468 /* 469 * Boot install lists are arranged <addr, len>, <addr, len>, ... 470 */ 471 ssize = (1ull << OPL_MC_MEMBOARD_SHIFT); 472 for (elem = 0; elem < nelems; elem += 2) { 473 low = (uint64_t)list[elem]; 474 high = low+(uint64_t)(list[elem+1]); 475 while (low < high) { 476 boundary = roundup(low+1, ssize); 477 boundary = MIN(high, boundary); 478 basepfn = btop(low); 479 npgs = btop(boundary - low); 480 mem_node_add_slice(basepfn, basepfn + npgs - 1); 481 low = boundary; 482 } 483 } 484 } 485 486 /* 487 * Find the CPU associated with a slice at boot-time. 488 */ 489 void 490 plat_fill_mc(pnode_t nodeid) 491 { 492 int board; 493 int memnode; 494 struct { 495 uint64_t addr; 496 uint64_t size; 497 } mem_range; 498 499 if (prom_getprop(nodeid, "board#", (caddr_t)&board) < 0) { 500 panic("Can not find board# property in mc node %x", nodeid); 501 } 502 if (prom_getprop(nodeid, "sb-mem-ranges", (caddr_t)&mem_range) < 0) { 503 panic("Can not find sb-mem-ranges property in mc node %x", 504 nodeid); 505 } 506 memnode = mem_range.addr >> OPL_MC_MEMBOARD_SHIFT; 507 plat_assign_lgrphand_to_mem_node(board, memnode); 508 } 509 510 /* 511 * Return the platform handle for the lgroup containing the given CPU 512 * 513 * For OPL, lgroup platform handle == board #. 514 */ 515 516 extern int mpo_disabled; 517 extern lgrp_handle_t lgrp_default_handle; 518 519 lgrp_handle_t 520 plat_lgrp_cpu_to_hand(processorid_t id) 521 { 522 lgrp_handle_t plathand; 523 524 /* 525 * Return the real platform handle for the CPU until 526 * such time as we know that MPO should be disabled. 527 * At that point, we set the "mpo_disabled" flag to true, 528 * and from that point on, return the default handle. 529 * 530 * By the time we know that MPO should be disabled, the 531 * first CPU will have already been added to a leaf 532 * lgroup, but that's ok. The common lgroup code will 533 * double check that the boot CPU is in the correct place, 534 * and in the case where mpo should be disabled, will move 535 * it to the root if necessary. 536 */ 537 if (mpo_disabled) { 538 /* If MPO is disabled, return the default (UMA) handle */ 539 plathand = lgrp_default_handle; 540 } else 541 plathand = (lgrp_handle_t)LSB_ID(id); 542 return (plathand); 543 } 544 545 /* 546 * Platform specific lgroup initialization 547 */ 548 void 549 plat_lgrp_init(void) 550 { 551 extern uint32_t lgrp_expand_proc_thresh; 552 extern uint32_t lgrp_expand_proc_diff; 553 554 /* 555 * Set tuneables for the OPL architecture 556 * 557 * lgrp_expand_proc_thresh is the minimum load on the lgroups 558 * this process is currently running on before considering 559 * expanding threads to another lgroup. 560 * 561 * lgrp_expand_proc_diff determines how much less the remote lgroup 562 * must be loaded before expanding to it. 563 * 564 * Since remote latencies can be costly, attempt to keep 3 threads 565 * within the same lgroup before expanding to the next lgroup. 566 */ 567 lgrp_expand_proc_thresh = LGRP_LOADAVG_THREAD_MAX * 3; 568 lgrp_expand_proc_diff = LGRP_LOADAVG_THREAD_MAX; 569 } 570 571 /* 572 * Platform notification of lgroup (re)configuration changes 573 */ 574 /*ARGSUSED*/ 575 void 576 plat_lgrp_config(lgrp_config_flag_t evt, uintptr_t arg) 577 { 578 update_membounds_t *umb; 579 lgrp_config_mem_rename_t lmr; 580 int sbd, tbd; 581 lgrp_handle_t hand, shand, thand; 582 int mnode, snode, tnode; 583 pfn_t start, end; 584 585 if (mpo_disabled) 586 return; 587 588 switch (evt) { 589 590 case LGRP_CONFIG_MEM_ADD: 591 /* 592 * Establish the lgroup handle to memnode translation. 593 */ 594 umb = (update_membounds_t *)arg; 595 596 hand = umb->u_board; 597 mnode = plat_pfn_to_mem_node(umb->u_base >> MMU_PAGESHIFT); 598 plat_assign_lgrphand_to_mem_node(hand, mnode); 599 600 break; 601 602 case LGRP_CONFIG_MEM_DEL: 603 /* 604 * Special handling for possible memory holes. 605 */ 606 umb = (update_membounds_t *)arg; 607 hand = umb->u_board; 608 if ((mnode = plat_lgrphand_to_mem_node(hand)) != -1) { 609 if (mem_node_config[mnode].exists) { 610 start = mem_node_config[mnode].physbase; 611 end = mem_node_config[mnode].physmax; 612 mem_node_pre_del_slice(start, end); 613 mem_node_post_del_slice(start, end, 0); 614 } 615 } 616 617 break; 618 619 case LGRP_CONFIG_MEM_RENAME: 620 /* 621 * During a DR copy-rename operation, all of the memory 622 * on one board is moved to another board -- but the 623 * addresses/pfns and memnodes don't change. This means 624 * the memory has changed locations without changing identity. 625 * 626 * Source is where we are copying from and target is where we 627 * are copying to. After source memnode is copied to target 628 * memnode, the physical addresses of the target memnode are 629 * renamed to match what the source memnode had. Then target 630 * memnode can be removed and source memnode can take its 631 * place. 632 * 633 * To do this, swap the lgroup handle to memnode mappings for 634 * the boards, so target lgroup will have source memnode and 635 * source lgroup will have empty target memnode which is where 636 * its memory will go (if any is added to it later). 637 * 638 * Then source memnode needs to be removed from its lgroup 639 * and added to the target lgroup where the memory was living 640 * but under a different name/memnode. The memory was in the 641 * target memnode and now lives in the source memnode with 642 * different physical addresses even though it is the same 643 * memory. 644 */ 645 sbd = arg & 0xffff; 646 tbd = (arg & 0xffff0000) >> 16; 647 shand = sbd; 648 thand = tbd; 649 snode = plat_lgrphand_to_mem_node(shand); 650 tnode = plat_lgrphand_to_mem_node(thand); 651 652 /* 653 * Special handling for possible memory holes. 654 */ 655 if (tnode != -1 && mem_node_config[tnode].exists) { 656 start = mem_node_config[tnode].physbase; 657 end = mem_node_config[tnode].physmax; 658 mem_node_pre_del_slice(start, end); 659 mem_node_post_del_slice(start, end, 0); 660 } 661 662 plat_assign_lgrphand_to_mem_node(thand, snode); 663 plat_assign_lgrphand_to_mem_node(shand, tnode); 664 665 lmr.lmem_rename_from = shand; 666 lmr.lmem_rename_to = thand; 667 668 /* 669 * Remove source memnode of copy rename from its lgroup 670 * and add it to its new target lgroup 671 */ 672 lgrp_config(LGRP_CONFIG_MEM_RENAME, (uintptr_t)snode, 673 (uintptr_t)&lmr); 674 675 break; 676 677 default: 678 break; 679 } 680 } 681 682 /* 683 * Return latency between "from" and "to" lgroups 684 * 685 * This latency number can only be used for relative comparison 686 * between lgroups on the running system, cannot be used across platforms, 687 * and may not reflect the actual latency. It is platform and implementation 688 * specific, so platform gets to decide its value. It would be nice if the 689 * number was at least proportional to make comparisons more meaningful though. 690 * NOTE: The numbers below are supposed to be load latencies for uncached 691 * memory divided by 10. 692 * 693 */ 694 int 695 plat_lgrp_latency(lgrp_handle_t from, lgrp_handle_t to) 696 { 697 /* 698 * Return min remote latency when there are more than two lgroups 699 * (root and child) and getting latency between two different lgroups 700 * or root is involved 701 */ 702 if (lgrp_optimizations() && (from != to || 703 from == LGRP_DEFAULT_HANDLE || to == LGRP_DEFAULT_HANDLE)) 704 return (42); 705 else 706 return (35); 707 } 708 709 /* 710 * Return platform handle for root lgroup 711 */ 712 lgrp_handle_t 713 plat_lgrp_root_hand(void) 714 { 715 if (mpo_disabled) 716 return (lgrp_default_handle); 717 718 return (LGRP_DEFAULT_HANDLE); 719 } 720 721 /*ARGSUSED*/ 722 void 723 plat_freelist_process(int mnode) 724 { 725 } 726 727 void 728 load_platform_drivers(void) 729 { 730 (void) i_ddi_attach_pseudo_node("dr"); 731 } 732 733 /* 734 * No platform drivers on this platform 735 */ 736 char *platform_module_list[] = { 737 (char *)0 738 }; 739 740 /*ARGSUSED*/ 741 void 742 plat_tod_fault(enum tod_fault_type tod_bad) 743 { 744 } 745 746 /*ARGSUSED*/ 747 void 748 cpu_sgn_update(ushort_t sgn, uchar_t state, uchar_t sub_state, int cpuid) 749 { 750 static void (*scf_panic_callback)(int); 751 static void (*scf_shutdown_callback)(int); 752 753 /* 754 * This is for notifing system panic/shutdown to SCF. 755 * In case of shutdown and panic, SCF call back 756 * function should be called. 757 * <SCF call back functions> 758 * scf_panic_callb() : panicsys()->panic_quiesce_hw() 759 * scf_shutdown_callb(): halt() or power_down() or reboot_machine() 760 * cpuid should be -1 and state should be SIGST_EXIT. 761 */ 762 if (state == SIGST_EXIT && cpuid == -1) { 763 764 /* 765 * find the symbol for the SCF panic callback routine in driver 766 */ 767 if (scf_panic_callback == NULL) 768 scf_panic_callback = (void (*)(int)) 769 modgetsymvalue("scf_panic_callb", 0); 770 if (scf_shutdown_callback == NULL) 771 scf_shutdown_callback = (void (*)(int)) 772 modgetsymvalue("scf_shutdown_callb", 0); 773 774 switch (sub_state) { 775 case SIGSUBST_PANIC: 776 if (scf_panic_callback == NULL) { 777 cmn_err(CE_NOTE, "!cpu_sgn_update: " 778 "scf_panic_callb not found\n"); 779 return; 780 } 781 scf_panic_callback(SIGSUBST_PANIC); 782 break; 783 784 case SIGSUBST_HALT: 785 if (scf_shutdown_callback == NULL) { 786 cmn_err(CE_NOTE, "!cpu_sgn_update: " 787 "scf_shutdown_callb not found\n"); 788 return; 789 } 790 scf_shutdown_callback(SIGSUBST_HALT); 791 break; 792 793 case SIGSUBST_ENVIRON: 794 if (scf_shutdown_callback == NULL) { 795 cmn_err(CE_NOTE, "!cpu_sgn_update: " 796 "scf_shutdown_callb not found\n"); 797 return; 798 } 799 scf_shutdown_callback(SIGSUBST_ENVIRON); 800 break; 801 802 case SIGSUBST_REBOOT: 803 if (scf_shutdown_callback == NULL) { 804 cmn_err(CE_NOTE, "!cpu_sgn_update: " 805 "scf_shutdown_callb not found\n"); 806 return; 807 } 808 scf_shutdown_callback(SIGSUBST_REBOOT); 809 break; 810 } 811 } 812 } 813 814 /*ARGSUSED*/ 815 int 816 plat_get_mem_unum(int synd_code, uint64_t flt_addr, int flt_bus_id, 817 int flt_in_memory, ushort_t flt_status, 818 char *buf, int buflen, int *lenp) 819 { 820 /* 821 * check if it's a Memory error. 822 */ 823 if (flt_in_memory) { 824 if (opl_get_mem_unum != NULL) { 825 return (opl_get_mem_unum(synd_code, flt_addr, 826 buf, buflen, lenp)); 827 } else { 828 return (ENOTSUP); 829 } 830 } else { 831 return (ENOTSUP); 832 } 833 } 834 835 /*ARGSUSED*/ 836 int 837 plat_get_cpu_unum(int cpuid, char *buf, int buflen, int *lenp) 838 { 839 int ret = 0; 840 uint_t sb; 841 int plen; 842 843 sb = opl_get_physical_board(LSB_ID(cpuid)); 844 if (sb == -1) { 845 return (ENXIO); 846 } 847 848 /* 849 * opl_cur_model is assigned here 850 */ 851 if (opl_cur_model == NULL) { 852 set_model_info(); 853 } 854 855 ASSERT((opl_cur_model - opl_models) == (opl_cur_model->model_type)); 856 857 switch (opl_cur_model->model_type) { 858 case FF1: 859 plen = snprintf(buf, buflen, "/%s/CPUM%d", "MBU_A", 860 CHIP_ID(cpuid) / 2); 861 break; 862 863 case FF2: 864 plen = snprintf(buf, buflen, "/%s/CPUM%d", "MBU_B", 865 (CHIP_ID(cpuid) / 2) + (sb * 2)); 866 break; 867 868 case DC1: 869 case DC2: 870 case DC3: 871 plen = snprintf(buf, buflen, "/%s%02d/CPUM%d", "CMU", sb, 872 CHIP_ID(cpuid)); 873 break; 874 875 default: 876 /* This should never happen */ 877 return (ENODEV); 878 } 879 880 if (plen >= buflen) { 881 ret = ENOSPC; 882 } else { 883 if (lenp) 884 *lenp = strlen(buf); 885 } 886 return (ret); 887 } 888 889 #define SCF_PUTINFO(f, s, p) \ 890 f(KEY_ESCF, 0x01, 0, s, p) 891 void 892 plat_nodename_set(void) 893 { 894 void *datap; 895 static int (*scf_service_function)(uint32_t, uint8_t, 896 uint32_t, uint32_t, void *); 897 int counter = 5; 898 899 /* 900 * find the symbol for the SCF put routine in driver 901 */ 902 if (scf_service_function == NULL) 903 scf_service_function = 904 (int (*)(uint32_t, uint8_t, uint32_t, uint32_t, void *)) 905 modgetsymvalue("scf_service_putinfo", 0); 906 907 /* 908 * If the symbol was found, call it. Otherwise, log a note (but not to 909 * the console). 910 */ 911 912 if (scf_service_function == NULL) { 913 cmn_err(CE_NOTE, 914 "!plat_nodename_set: scf_service_putinfo not found\n"); 915 return; 916 } 917 918 datap = 919 (struct utsname *)kmem_zalloc(sizeof (struct utsname), KM_SLEEP); 920 921 if (datap == NULL) { 922 return; 923 } 924 925 bcopy((struct utsname *)&utsname, 926 (struct utsname *)datap, sizeof (struct utsname)); 927 928 while ((SCF_PUTINFO(scf_service_function, 929 sizeof (struct utsname), datap) == EBUSY) && (counter-- > 0)) { 930 delay(10 * drv_usectohz(1000000)); 931 } 932 if (counter == 0) 933 cmn_err(CE_NOTE, 934 "!plat_nodename_set: " 935 "scf_service_putinfo not responding\n"); 936 937 kmem_free(datap, sizeof (struct utsname)); 938 } 939 940 caddr_t efcode_vaddr = NULL; 941 942 /* 943 * Preallocate enough memory for fcode claims. 944 */ 945 946 caddr_t 947 efcode_alloc(caddr_t alloc_base) 948 { 949 caddr_t efcode_alloc_base = (caddr_t)roundup((uintptr_t)alloc_base, 950 MMU_PAGESIZE); 951 caddr_t vaddr; 952 953 /* 954 * allocate the physical memory for the Oberon fcode. 955 */ 956 if ((vaddr = (caddr_t)BOP_ALLOC(bootops, efcode_alloc_base, 957 efcode_size, MMU_PAGESIZE)) == NULL) 958 cmn_err(CE_PANIC, "Cannot allocate Efcode Memory"); 959 960 efcode_vaddr = vaddr; 961 962 return (efcode_alloc_base + efcode_size); 963 } 964 965 caddr_t 966 plat_startup_memlist(caddr_t alloc_base) 967 { 968 caddr_t tmp_alloc_base; 969 970 tmp_alloc_base = efcode_alloc(alloc_base); 971 tmp_alloc_base = 972 (caddr_t)roundup((uintptr_t)tmp_alloc_base, ecache_alignsize); 973 return (tmp_alloc_base); 974 } 975 976 void 977 startup_platform(void) 978 { 979 } 980 981 void 982 plat_cpuid_to_mmu_ctx_info(processorid_t cpuid, mmu_ctx_info_t *info) 983 { 984 int impl; 985 986 impl = cpunodes[cpuid].implementation; 987 if (IS_OLYMPUS_C(impl)) { 988 info->mmu_idx = MMU_ID(cpuid); 989 info->mmu_nctxs = 8192; 990 } else { 991 cmn_err(CE_PANIC, "Unknown processor %d", impl); 992 } 993 } 994 995 int 996 plat_get_mem_sid(char *unum, char *buf, int buflen, int *lenp) 997 { 998 if (opl_get_mem_sid == NULL) { 999 return (ENOTSUP); 1000 } 1001 return (opl_get_mem_sid(unum, buf, buflen, lenp)); 1002 } 1003 1004 int 1005 plat_get_mem_offset(uint64_t paddr, uint64_t *offp) 1006 { 1007 if (opl_get_mem_offset == NULL) { 1008 return (ENOTSUP); 1009 } 1010 return (opl_get_mem_offset(paddr, offp)); 1011 } 1012 1013 int 1014 plat_get_mem_addr(char *unum, char *sid, uint64_t offset, uint64_t *addrp) 1015 { 1016 if (opl_get_mem_addr == NULL) { 1017 return (ENOTSUP); 1018 } 1019 return (opl_get_mem_addr(unum, sid, offset, addrp)); 1020 } 1021 1022 void 1023 plat_lock_delay(int *backoff) 1024 { 1025 int i; 1026 int cnt; 1027 int flag; 1028 int ctr; 1029 hrtime_t delay_start; 1030 /* 1031 * Platform specific lock delay code for OPL 1032 * 1033 * Using staged linear increases in the delay. 1034 * The sleep instruction is the preferred method of delay, 1035 * but is too large of granularity for the initial backoff. 1036 */ 1037 1038 if (*backoff == 0) *backoff = OPL_BOFF_BASE; 1039 1040 flag = !*backoff; 1041 1042 if (*backoff < OPL_BOFF_CAP1) { 1043 /* 1044 * If desired backoff is long enough, 1045 * use sleep for most of it 1046 */ 1047 for (cnt = *backoff; 1048 cnt >= OPL_BOFF_SLEEP; 1049 cnt -= OPL_BOFF_SLEEP) { 1050 cpu_smt_pause(); 1051 } 1052 /* 1053 * spin for small remainder of backoff 1054 * 1055 * fake call to nulldev included to prevent 1056 * compiler from optimizing out the spin loop 1057 */ 1058 for (ctr = cnt * OPL_BOFF_SPIN; ctr; ctr--) { 1059 if (flag) (void) nulldev(); 1060 } 1061 } else { 1062 /* backoff is very large. Fill it by sleeping */ 1063 delay_start = gethrtime(); 1064 cnt = *backoff/OPL_BOFF_SLEEP; 1065 /* 1066 * use sleep instructions for delay 1067 */ 1068 for (i = 0; i < cnt; i++) { 1069 cpu_smt_pause(); 1070 } 1071 1072 /* 1073 * Note: if the other strand executes a sleep instruction, 1074 * then the sleep ends immediately with a minimum time of 1075 * 42 clocks. We check gethrtime to insure we have 1076 * waited long enough. And we include both a short 1077 * spin loop and a sleep for any final delay time. 1078 */ 1079 1080 while ((gethrtime() - delay_start) < cnt * OPL_BOFF_TM) { 1081 cpu_smt_pause(); 1082 for (ctr = OPL_BOFF_SPIN; ctr; ctr--) { 1083 if (flag) (void) nulldev(); 1084 } 1085 } 1086 } 1087 1088 /* 1089 * We adjust the backoff in three linear stages 1090 * The initial stage has small increases as this phase is 1091 * usually handle locks with light contention. We don't want 1092 * to have a long backoff on a lock that is available. 1093 * 1094 * In the second stage, we are in transition, unsure whether 1095 * the lock is under heavy contention. As the failures to 1096 * obtain the lock increase, we back off further. 1097 * 1098 * For the final stage, we are in a heavily contended or 1099 * long held long so we want to reduce the number of tries. 1100 */ 1101 if (*backoff < OPL_BOFF_CAP1) { 1102 *backoff += 1; 1103 } else { 1104 if (*backoff < OPL_BOFF_CAP2) { 1105 *backoff += OPL_BOFF_SLEEP; 1106 } else { 1107 *backoff += 2 * OPL_BOFF_SLEEP; 1108 } 1109 if (*backoff > OPL_BOFF_MAX) { 1110 *backoff = OPL_BOFF_MAX; 1111 } 1112 } 1113 } 1114