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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * Copyright (c) 2016 by Delphix. All rights reserved. 26 */ 27 28 /* 29 * CPU management for serengeti DR 30 * 31 * There are three states a CPU can be in: 32 * 33 * disconnected: In reset 34 * connect,unconfigured: Idling in OBP's idle loop 35 * configured: Running Solaris 36 * 37 * State transitions: 38 * 39 * connect configure 40 * ------------> ------------> 41 * disconnected connected configured 42 * unconfigured 43 * <----------- <------------- 44 * disconnect unconfigure 45 * 46 * Firmware involvements 47 * 48 * start_cpu(SC) 49 * prom_serengeti_wakeupcpu(OBP) 50 * ------------> -------------------------> 51 * disconnected connected configured 52 * unconfigured 53 * <----------- <------------------------- 54 * prom_serengeti_cpu_off(OBP) prom_serengeti_cpu_off(OBP) 55 * stop_cpu(SC) prom_serengeti_wakeupcpu(OBP) 56 * 57 * SIR (Software Initiated Reset) is used to unconfigure a CPU. 58 * After the CPU has completed flushing the caches, it issues an 59 * sir instruction to put itself through POST. POST detects that 60 * it is an SIR, and re-enters OBP as a slave. When the operation 61 * completes successfully, the CPU will be idling in OBP. 62 */ 63 64 #include <sys/obpdefs.h> 65 #include <sys/types.h> 66 #include <sys/cmn_err.h> 67 #include <sys/cpuvar.h> 68 #include <sys/membar.h> 69 #include <sys/x_call.h> 70 #include <sys/machsystm.h> 71 #include <sys/cpu_sgnblk_defs.h> 72 #include <sys/pte.h> 73 #include <vm/hat_sfmmu.h> 74 #include <sys/promif.h> 75 #include <sys/note.h> 76 #include <sys/vmsystm.h> 77 #include <vm/seg_kmem.h> 78 79 #include <sys/sbd_ioctl.h> 80 #include <sys/sbd.h> 81 #include <sys/sbdp_priv.h> 82 #include <sys/sbdp_mem.h> 83 #include <sys/sbdp_error.h> 84 #include <sys/sgsbbc_iosram.h> 85 #include <sys/prom_plat.h> 86 #include <sys/cheetahregs.h> 87 88 uint64_t *sbdp_valp; 89 extern uint64_t va_to_pa(void *); 90 static int sbdp_cpu_ntries = 50000; 91 static int sbdp_cpu_delay = 100; 92 void sbdp_get_cpu_sram_addr(uint64_t, uint64_t); 93 static int cpusram_map(caddr_t *, pgcnt_t *); 94 static void cpusram_unmap(caddr_t *, pgcnt_t); 95 extern int prom_serengeti_wakeupcpu(pnode_t); 96 extern int prom_serengeti_cpu_off(pnode_t); 97 extern sbdp_wnode_t *sbdp_get_wnodep(int); 98 extern caddr_t sbdp_shutdown_va; 99 static int sbdp_prom_get_cpu(void *arg, int changed); 100 static void sbdp_cpu_shutdown_self(void); 101 102 int 103 sbdp_disconnect_cpu(sbdp_handle_t *hp, dev_info_t *dip, processorid_t cpuid) 104 { 105 pnode_t nodeid; 106 int bd, wnode; 107 sbdp_wnode_t *wnodep; 108 sbdp_bd_t *bdp = NULL; 109 int rv = 0; 110 processorid_t cpu = cpuid; 111 processorid_t portid; 112 static fn_t f = "sbdp_disconnect_cpu"; 113 114 SBDP_DBG_FUNC("%s\n", f); 115 116 nodeid = ddi_get_nodeid(dip); 117 118 /* 119 * Get board number and node number 120 * The check for determining if nodeid is valid is done inside 121 * sbdp_get_bd_and_wnode_num. 122 */ 123 if (SBDP_INJECT_ERROR(f, 0) || 124 sbdp_get_bd_and_wnode_num(nodeid, &bd, &wnode) != 0) { 125 126 rv = -1; 127 goto out; 128 } 129 130 /* 131 * Grab the lock to prevent status threads from accessing 132 * registers on the CPU when it is being put into reset. 133 */ 134 wnodep = sbdp_get_wnodep(wnode); 135 bdp = &wnodep->bds[bd]; 136 ASSERT(bdp); 137 mutex_enter(&bdp->bd_mutex); 138 139 /* 140 * Mark the CPU in reset. This should be done before calling 141 * the SC because we won't know at which stage it failed if 142 * the SC call returns failure. 143 */ 144 sbdp_cpu_in_reset(wnode, bd, SG_CPUID_TO_CPU_UNIT(cpuid), 1); 145 146 /* 147 * Ask OBP to mark the CPU as in POST 148 */ 149 if (SBDP_INJECT_ERROR(f, 1) || prom_serengeti_cpu_off(nodeid) != 0) { 150 151 rv = -1; 152 goto out; 153 } 154 155 /* 156 * Ask the SC to put the CPU into reset. If the first 157 * core is not present, the stop CPU interface needs 158 * to be called with the portid rather than the cpuid. 159 */ 160 portid = SG_CPUID_TO_PORTID(cpuid); 161 if (!SBDP_IS_CPU_PRESENT(bdp, SG_CPUID_TO_CPU_UNIT(portid))) { 162 cpu = portid; 163 } 164 165 if (SBDP_INJECT_ERROR(f, 2) || sbdp_stop_cpu(cpu) != 0) { 166 167 rv = -1; 168 goto out; 169 } 170 171 out: 172 if (bdp != NULL) { 173 mutex_exit(&bdp->bd_mutex); 174 } 175 176 if (rv != 0) { 177 sbdp_set_err(hp->h_err, ESGT_STOPCPU, NULL); 178 } 179 180 return (rv); 181 } 182 183 int 184 sbdp_connect_cpu(sbdp_handle_t *hp, dev_info_t *dip, processorid_t cpuid) 185 { 186 pnode_t nodeid; 187 sbd_error_t *sep; 188 int i; 189 int bd, wnode; 190 int rv = 0; 191 static fn_t f = "sbdp_connect_cpu"; 192 193 SBDP_DBG_FUNC("%s\n", f); 194 195 sep = hp->h_err; 196 197 nodeid = ddi_get_nodeid(dip); 198 199 /* 200 * The check for determining if nodeid is valid is done inside 201 * sbdp_get_bd_and_wnode_num. 202 */ 203 if (SBDP_INJECT_ERROR(f, 0) || 204 sbdp_get_bd_and_wnode_num(nodeid, &bd, &wnode) != 0) { 205 206 rv = -1; 207 goto out; 208 } 209 210 /* 211 * Ask the SC to bring the CPU out of reset. 212 * At this point, the sb_dev_present bit is not set for the CPU. 213 * From sbd point of view the CPU is not present yet. No 214 * status threads will try to read registers off the CPU. 215 * Since we are already holding sb_mutex, it is not necessary 216 * to grab the board mutex when checking and setting the 217 * cpus_in_reset bit. 218 */ 219 if (sbdp_is_cpu_in_reset(wnode, bd, SG_CPUID_TO_CPU_UNIT(cpuid))) { 220 221 sbdp_wnode_t *wnodep; 222 sbdp_bd_t *bdp = NULL; 223 processorid_t cpu = cpuid; 224 processorid_t portid; 225 226 wnodep = sbdp_get_wnodep(wnode); 227 bdp = &wnodep->bds[bd]; 228 ASSERT(bdp); 229 230 /* 231 * If the first core is not present, the start CPU 232 * interface needs to be called with the portid rather 233 * than the cpuid. 234 */ 235 portid = SG_CPUID_TO_PORTID(cpuid); 236 if (!SBDP_IS_CPU_PRESENT(bdp, SG_CPUID_TO_CPU_UNIT(portid))) { 237 cpu = portid; 238 } 239 240 if (SBDP_INJECT_ERROR(f, 1) || sbdp_start_cpu(cpu) != 0) { 241 242 rv = -1; 243 goto out; 244 } 245 246 if (SBDP_INJECT_ERROR(f, 2) || 247 prom_serengeti_wakeupcpu(nodeid) != 0) { 248 249 rv = -1; 250 goto out; 251 } 252 } 253 254 /* 255 * Mark the CPU out of reset. 256 */ 257 sbdp_cpu_in_reset(wnode, bd, SG_CPUID_TO_CPU_UNIT(cpuid), 0); 258 259 /* 260 * Refresh the bd info 261 * we need to wait until all cpus are out of reset 262 */ 263 for (i = 0; i < SG_MAX_CPUS_PER_BD; i++) 264 if (sbdp_is_cpu_present(wnode, bd, i) && 265 sbdp_is_cpu_in_reset(wnode, bd, i) == 1) { 266 break; 267 } 268 269 if (i == SG_MAX_CPUS_PER_BD) { 270 /* 271 * All cpus are out of reset so it is safe to 272 * update the bd info 273 */ 274 sbdp_add_new_bd_info(wnode, bd); 275 } 276 277 out: 278 if (rv != 0) 279 sbdp_set_err(sep, ESGT_WAKEUPCPU, NULL); 280 281 return (rv); 282 } 283 284 int 285 sbdp_cpu_poweron(struct cpu *cp) 286 { 287 int cpuid; 288 int ntries; 289 pnode_t nodeid; 290 extern void restart_other_cpu(int); 291 static fn_t f = "sbdp_cpu_poweron"; 292 293 SBDP_DBG_FUNC("%s\n", f); 294 295 ASSERT(MUTEX_HELD(&cpu_lock)); 296 297 ntries = sbdp_cpu_ntries; 298 cpuid = cp->cpu_id; 299 300 nodeid = cpunodes[cpuid].nodeid; 301 ASSERT(nodeid != (pnode_t)0); 302 303 /* 304 * This is a safe guard in case the CPU has taken a trap 305 * and idling in POST. 306 */ 307 if (SBDP_INJECT_ERROR(f, 0) || 308 prom_serengeti_wakeupcpu(nodeid) != 0) { 309 310 return (EBUSY); 311 } 312 313 cp->cpu_flags &= ~CPU_POWEROFF; 314 315 /* 316 * NOTE: restart_other_cpu pauses cpus during the 317 * slave cpu start. This helps to quiesce the 318 * bus traffic a bit which makes the tick sync 319 * routine in the prom more robust. 320 */ 321 SBDP_DBG_CPU("%s: COLD START for cpu (%d)\n", f, cpuid); 322 323 restart_other_cpu(cpuid); 324 325 SBDP_DBG_CPU("after restarting other cpus\n"); 326 327 /* 328 * Wait for the cpu to reach its idle thread before 329 * we zap it with a request to blow away the mappings 330 * it (might) have for the sbdp_shutdown_asm code 331 * it may have executed on unconfigure. 332 */ 333 while ((cp->cpu_thread != cp->cpu_idle_thread) && (ntries > 0)) { 334 DELAY(sbdp_cpu_delay); 335 ntries--; 336 } 337 338 SBDP_DBG_CPU("%s: waited %d out of %d loops for cpu %d\n", 339 f, sbdp_cpu_ntries - ntries, sbdp_cpu_ntries, cpuid); 340 341 return (0); 342 } 343 344 345 #define SBDP_CPU_SRAM_ADDR 0x7fff0900000ull 346 #define SBDP_CPU_SRAM_SIZE 0x20000ull 347 348 static const char cpyren_key[] = "COPYREN"; 349 350 static uint64_t bbsram_pa; 351 static uint_t bbsram_size; 352 353 typedef struct { 354 caddr_t vaddr; 355 pgcnt_t npages; 356 uint64_t *pa; 357 uint_t *size; 358 } sbdp_cpu_sram_map_t; 359 360 int 361 sbdp_cpu_poweroff(struct cpu *cp) 362 { 363 processorid_t cpuid; 364 pnode_t nodeid; 365 sbdp_cpu_sram_map_t map; 366 static fn_t f = "sbdp_cpu_poweroff"; 367 368 SBDP_DBG_FUNC("%s\n", f); 369 370 ASSERT(MUTEX_HELD(&cpu_lock)); 371 372 /* 373 * Capture all CPUs (except for detaching proc) to prevent 374 * crosscalls to the detaching proc until it has cleared its 375 * bit in cpu_ready_set. 376 */ 377 cpuid = cp->cpu_id; 378 379 nodeid = cpunodes[cpuid].nodeid; 380 ASSERT(nodeid != (pnode_t)0); 381 382 *sbdp_valp = 0ull; 383 /* 384 * Do the cpu sram mapping now. This avoids problems with 385 * mutexes and high PILS 386 */ 387 if (SBDP_INJECT_ERROR(f, 0) || 388 cpusram_map(&map.vaddr, &map.npages) != DDI_SUCCESS) { 389 return (EBUSY); 390 } 391 392 map.pa = &bbsram_pa; 393 map.size = &bbsram_size; 394 395 /* 396 * Do a cross call to the cpu so it obtains the base address 397 */ 398 xc_one(cpuid, sbdp_get_cpu_sram_addr, (uint64_t)&map, 399 (uint64_t)NULL); 400 401 cpusram_unmap(&map.vaddr, map.npages); 402 403 if (SBDP_INJECT_ERROR(f, 1) || bbsram_size == 0) { 404 cmn_err(CE_WARN, "cpu%d: Key \"%s\" missing from CPU SRAM TOC", 405 cpuid, cpyren_key); 406 return (EBUSY); 407 } 408 409 if ((bbsram_pa & MMU_PAGEOFFSET) != 0) { 410 cmn_err(CE_WARN, "cpu%d: CPU SRAM key \"%s\" not page aligned, " 411 "offset = 0x%lx", cpuid, cpyren_key, 412 (bbsram_pa - (uint64_t)SBDP_CPU_SRAM_ADDR)); 413 return (EBUSY); 414 } 415 416 if (bbsram_size < MMU_PAGESIZE) { 417 cmn_err(CE_WARN, "cpu%d: CPU SRAM key \"%s\" too small, " 418 "size = 0x%x", cpuid, cpyren_key, bbsram_size); 419 return (EBUSY); 420 } 421 422 /* 423 * Capture all CPUs (except for detaching proc) to prevent 424 * crosscalls to the detaching proc until it has cleared its 425 * bit in cpu_ready_set. 426 * 427 * The CPU's remain paused and the prom_mutex is known to be free. 428 * This prevents the x-trap victim from blocking when doing prom 429 * IEEE-1275 calls at a high PIL level. 430 */ 431 432 promsafe_pause_cpus(); 433 434 /* 435 * Quiesce interrupts on the target CPU. We do this by setting 436 * the CPU 'not ready'- (i.e. removing the CPU from cpu_ready_set) to 437 * prevent it from receiving cross calls and cross traps. 438 * This prevents the processor from receiving any new soft interrupts. 439 */ 440 441 mp_cpu_quiesce(cp); 442 443 /* tell the prom the cpu is going away */ 444 if (SBDP_INJECT_ERROR(f, 2) || prom_serengeti_cpu_off(nodeid) != 0) 445 return (EBUSY); 446 447 /* 448 * An sir instruction is issued at the end of the shutdown 449 * routine to make the CPU go through POST and re-enter OBP. 450 */ 451 xt_one_unchecked(cp->cpu_id, (xcfunc_t *)idle_stop_xcall, 452 (uint64_t)sbdp_cpu_shutdown_self, 0); 453 454 *sbdp_valp = 3ull; 455 456 start_cpus(); 457 458 /* 459 * Wait until we reach the OBP idle loop or time out. 460 * prom_serengeti_wakeupcpu waits for up to 60 seconds for the 461 * CPU to reach OBP idle loop. 462 */ 463 if (SBDP_INJECT_ERROR(f, 3) || 464 prom_serengeti_wakeupcpu(nodeid) != 0) { 465 466 /* 467 * If it fails here, we still consider the unconfigure 468 * operation as successful. 469 */ 470 cmn_err(CE_WARN, "cpu%d: CPU failed to enter OBP idle loop.\n", 471 cpuid); 472 } 473 474 ASSERT(!(CPU_IN_SET(cpu_ready_set, cpuid))); 475 476 bbsram_pa = 0; 477 bbsram_size = 0; 478 479 return (0); 480 } 481 482 processorid_t 483 sbdp_get_cpuid(sbdp_handle_t *hp, dev_info_t *dip) 484 { 485 int cpuid; 486 char type[OBP_MAXPROPNAME]; 487 pnode_t nodeid; 488 sbd_error_t *sep; 489 static fn_t f = "sbdp_get_cpuid"; 490 491 SBDP_DBG_FUNC("%s\n", f); 492 493 nodeid = ddi_get_nodeid(dip); 494 if (sbdp_is_node_bad(nodeid)) 495 return (-1); 496 497 sep = hp->h_err; 498 499 if (prom_getproplen(nodeid, "device_type") < OBP_MAXPROPNAME) 500 (void) prom_getprop(nodeid, "device_type", (caddr_t)type); 501 else { 502 sbdp_set_err(sep, ESGT_NO_DEV_TYPE, NULL); 503 return (-1); 504 } 505 506 if (strcmp(type, "cpu") != 0) { 507 sbdp_set_err(sep, ESGT_NOT_CPUTYPE, NULL); 508 return (-1); 509 } 510 511 /* 512 * Check to see if property "cpuid" exists first. 513 * If not, check for "portid". 514 */ 515 if (prom_getprop(nodeid, "cpuid", (caddr_t)&cpuid) == -1) 516 if (prom_getprop(nodeid, "portid", (caddr_t)&cpuid) == -1) { 517 518 return (-1); 519 } 520 521 return ((processorid_t)cpuid & SG_CPU_ID_MASK); 522 } 523 524 int 525 sbdp_cpu_get_impl(sbdp_handle_t *hp, dev_info_t *dip) 526 { 527 int impl; 528 char type[OBP_MAXPROPNAME]; 529 pnode_t nodeid; 530 sbd_error_t *sep; 531 static fn_t f = "sbdp_cpu_get_impl"; 532 533 SBDP_DBG_FUNC("%s\n", f); 534 535 nodeid = ddi_get_nodeid(dip); 536 if (sbdp_is_node_bad(nodeid)) 537 return (-1); 538 539 sep = hp->h_err; 540 541 if (prom_getproplen(nodeid, "device_type") < OBP_MAXPROPNAME) 542 (void) prom_getprop(nodeid, "device_type", (caddr_t)type); 543 else { 544 sbdp_set_err(sep, ESGT_NO_DEV_TYPE, NULL); 545 return (-1); 546 } 547 548 if (strcmp(type, "cpu") != 0) { 549 sbdp_set_err(sep, ESGT_NOT_CPUTYPE, NULL); 550 return (-1); 551 } 552 553 /* 554 * Get the implementation# property. 555 */ 556 if (prom_getprop(nodeid, "implementation#", (caddr_t)&impl) == -1) 557 return (-1); 558 559 return (impl); 560 } 561 562 struct sbdp_prom_get_node_args { 563 pnode_t node; /* current node */ 564 processorid_t portid; /* portid we are looking for */ 565 pnode_t result_node; /* node found with the above portid */ 566 }; 567 568 pnode_t 569 sbdp_find_nearby_cpu_by_portid(pnode_t nodeid, processorid_t portid) 570 { 571 struct sbdp_prom_get_node_args arg; 572 static fn_t f = "sbdp_find_nearby_cpu_by_portid"; 573 574 SBDP_DBG_FUNC("%s\n", f); 575 576 arg.node = nodeid; 577 arg.portid = portid; 578 (void) prom_tree_access(sbdp_prom_get_cpu, &arg, NULL); 579 580 return (arg.result_node); 581 } 582 583 /*ARGSUSED*/ 584 static int 585 sbdp_prom_get_cpu(void *arg, int changed) 586 { 587 int portid; 588 pnode_t parent, cur_node; 589 struct sbdp_prom_get_node_args *argp = arg; 590 static fn_t f = "sbdp_prom_get_cpu"; 591 592 SBDP_DBG_FUNC("%s\n", f); 593 594 parent = prom_parentnode(argp->node); 595 596 for (cur_node = prom_childnode(parent); cur_node != OBP_NONODE; 597 cur_node = prom_nextnode(cur_node)) { 598 599 if (prom_getprop(cur_node, OBP_PORTID, (caddr_t)&portid) < 0) 600 continue; 601 602 if ((portid == argp->portid) && (cur_node != argp->node)) 603 break; 604 } 605 606 argp->result_node = cur_node; 607 608 return (0); 609 } 610 611 612 /* 613 * A detaching CPU is xcalled with an xtrap to sbdp_cpu_stop_self() after 614 * it has been offlined. The function of this routine is to get the cpu 615 * spinning in a safe place. The requirement is that the system will not 616 * reference anything on the detaching board (memory and i/o is detached 617 * elsewhere) and that the CPU not reference anything on any other board 618 * in the system. This isolation is required during and after the writes 619 * to the domain masks to remove the board from the domain. 620 * 621 * To accomplish this isolation the following is done: 622 * 0) Map the CPUSRAM to obtain the correct address in SRAM 623 * 1) Create a locked mapping to a location in CPU SRAM where 624 * the cpu will execute. 625 * 2) Copy the target function (sbdp_shutdown_asm) in which 626 * the cpu will execute into CPU SRAM. 627 * 3) Jump into function with CPU SRAM. 628 * Function will: 629 * 3.1) Flush its Ecache (displacement). 630 * 3.2) Flush its Dcache with HW mechanism. 631 * 3.3) Flush its Icache with HW mechanism. 632 * 3.4) Flush all valid and _unlocked_ D-TLB entries. 633 * 3.5) Flush all valid and _unlocked_ I-TLB entries. 634 * 4) Jump into a tight loop. 635 */ 636 637 static void 638 sbdp_cpu_stop_self(uint64_t pa) 639 { 640 cpu_t *cp = CPU; 641 int cpuid = cp->cpu_id; 642 tte_t tte; 643 volatile uint_t *src, *dst; 644 size_t funclen; 645 sbdp_shutdown_t sht; 646 uint_t bbsram_pfn; 647 uint64_t bbsram_addr; 648 void (*bbsram_func)(sbdp_shutdown_t *); 649 extern void sbdp_shutdown_asm(sbdp_shutdown_t *); 650 extern void sbdp_shutdown_asm_end(void); 651 652 funclen = (uintptr_t)sbdp_shutdown_asm_end - 653 (uintptr_t)sbdp_shutdown_asm; 654 ASSERT(funclen <= MMU_PAGESIZE); 655 ASSERT(bbsram_pa != 0); 656 ASSERT((bbsram_pa & MMU_PAGEOFFSET) == 0); 657 ASSERT(bbsram_size >= MMU_PAGESIZE); 658 659 stdphys(pa, 3); 660 bbsram_pfn = (uint_t)(bbsram_pa >> MMU_PAGESHIFT); 661 662 bbsram_addr = (uint64_t)sbdp_shutdown_va; 663 sht.estack = bbsram_addr + MMU_PAGESIZE; 664 sht.flushaddr = ecache_flushaddr; 665 666 tte.tte_inthi = TTE_VALID_INT | TTE_SZ_INT(TTE8K) | 667 TTE_PFN_INTHI(bbsram_pfn); 668 tte.tte_intlo = TTE_PFN_INTLO(bbsram_pfn) | 669 TTE_HWWR_INT | TTE_PRIV_INT | TTE_LCK_INT; 670 sfmmu_dtlb_ld_kva(sbdp_shutdown_va, &tte); /* load dtlb */ 671 sfmmu_itlb_ld_kva(sbdp_shutdown_va, &tte); /* load itlb */ 672 673 for (src = (uint_t *)sbdp_shutdown_asm, dst = (uint_t *)bbsram_addr; 674 src < (uint_t *)sbdp_shutdown_asm_end; src++, dst++) 675 *dst = *src; 676 677 bbsram_func = (void (*)())bbsram_addr; 678 sht.size = (uint32_t)cpunodes[cpuid].ecache_size << 1; 679 sht.linesize = (uint32_t)cpunodes[cpuid].ecache_linesize; 680 sht.physaddr = pa; 681 682 /* 683 * Signal to sbdp_cpu_poweroff() that we're just 684 * about done. 685 */ 686 cp->cpu_m.in_prom = 1; 687 688 stdphys(pa, 4); 689 (*bbsram_func)(&sht); 690 } 691 692 /* ARGSUSED */ 693 void 694 sbdp_get_cpu_sram_addr(uint64_t arg1, uint64_t arg2) 695 { 696 uint64_t *pap; 697 uint_t *sizep; 698 struct iosram_toc *tocp; 699 uint_t offset; 700 uint_t size; 701 sbdp_cpu_sram_map_t *map; 702 int i; 703 fn_t f = "sbdp_get_cpu_sram_addr"; 704 705 SBDP_DBG_FUNC("%s\n", f); 706 707 map = (sbdp_cpu_sram_map_t *)arg1; 708 tocp = (struct iosram_toc *)map->vaddr; 709 pap = map->pa; 710 sizep = map->size; 711 712 for (i = 0; i < tocp->iosram_tagno; i++) { 713 if (strcmp(tocp->iosram_keys[i].key, cpyren_key) == 0) 714 break; 715 } 716 if (i == tocp->iosram_tagno) { 717 *pap = 0; 718 *sizep = 0; 719 return; 720 } 721 offset = tocp->iosram_keys[i].offset; 722 size = tocp->iosram_keys[i].size; 723 724 /* 725 * The address we want is the begining of cpusram + offset 726 */ 727 *pap = SBDP_CPU_SRAM_ADDR + offset; 728 729 *sizep = size; 730 } 731 732 static int 733 cpusram_map(caddr_t *vaddrp, pgcnt_t *npp) 734 { 735 uint_t pgoffset; 736 pgcnt_t npages; 737 pfn_t pfn; 738 uint64_t base; 739 caddr_t kaddr; 740 uint_t mapping_attr; 741 742 base = (uint64_t)SBDP_CPU_SRAM_ADDR & (~MMU_PAGEOFFSET); 743 pfn = mmu_btop(base); 744 745 /* 746 * Do a quick sanity check to make sure we are in I/O space. 747 */ 748 if (pf_is_memory(pfn)) 749 return (DDI_FAILURE); 750 751 pgoffset = (ulong_t)SBDP_CPU_SRAM_ADDR & MMU_PAGEOFFSET; 752 npages = mmu_btopr(SBDP_CPU_SRAM_SIZE + pgoffset); 753 754 kaddr = vmem_alloc(heap_arena, ptob(npages), VM_NOSLEEP); 755 if (kaddr == NULL) 756 return (DDI_ME_NORESOURCES); 757 758 mapping_attr = PROT_READ; 759 /* 760 * Now map in the pages we've allocated... 761 */ 762 hat_devload(kas.a_hat, kaddr, ptob(npages), pfn, mapping_attr, 763 HAT_LOAD_LOCK); 764 765 *vaddrp = kaddr + pgoffset; 766 *npp = npages; 767 768 return (DDI_SUCCESS); 769 } 770 771 static void 772 cpusram_unmap(caddr_t *vaddrp, pgcnt_t npages) 773 { 774 uint_t pgoffset; 775 caddr_t base; 776 caddr_t addr = *vaddrp; 777 778 779 pgoffset = (ulong_t)SBDP_CPU_SRAM_ADDR & MMU_PAGEOFFSET; 780 base = addr - pgoffset; 781 hat_unload(kas.a_hat, base, ptob(npages), HAT_UNLOAD_UNLOCK); 782 vmem_free(heap_arena, base, ptob(npages)); 783 784 *vaddrp = 0; 785 } 786 787 788 static void 789 sbdp_cpu_shutdown_self(void) 790 { 791 cpu_t *cp = CPU; 792 int cpuid = cp->cpu_id; 793 extern void flush_windows(void); 794 uint64_t pa = va_to_pa((void *)sbdp_valp); 795 796 stdphys(pa, 8); 797 flush_windows(); 798 799 (void) spl8(); 800 801 stdphys(pa, 6); 802 803 ASSERT(cp->cpu_intr_actv == 0); 804 ASSERT(cp->cpu_thread == cp->cpu_idle_thread || 805 cp->cpu_thread == cp->cpu_startup_thread); 806 807 cp->cpu_flags = CPU_OFFLINE | CPU_QUIESCED | CPU_POWEROFF; 808 809 CPU_SIGNATURE(OS_SIG, SIGST_DETACHED, SIGSUBST_NULL, cpuid); 810 811 stdphys(pa, 7); 812 sbdp_cpu_stop_self(pa); 813 814 cmn_err(CE_PANIC, "sbdp_cpu_shutdown_self: CPU %d FAILED TO SHUTDOWN", 815 cpuid); 816 } 817 818 typedef struct { 819 int node; 820 int board; 821 int non_panther_cpus; 822 } sbdp_node_walk_t; 823 824 static int 825 sbdp_find_non_panther_cpus(dev_info_t *dip, void *node_args) 826 { 827 int impl, cpuid, portid; 828 int buflen; 829 char buf[OBP_MAXPROPNAME]; 830 sbdp_node_walk_t *args = (sbdp_node_walk_t *)node_args; 831 832 if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 833 DDI_PROP_DONTPASS, OBP_DEVICETYPE, (caddr_t)buf, 834 &buflen) != DDI_PROP_SUCCESS) { 835 return (DDI_WALK_CONTINUE); 836 } 837 838 if (strcmp(buf, "cpu") != 0) { 839 return (DDI_WALK_CONTINUE); 840 } 841 842 if ((impl = ddi_getprop(DDI_DEV_T_ANY, dip, 843 DDI_PROP_DONTPASS, "implementation#", -1)) == -1) { 844 return (DDI_WALK_CONTINUE); 845 } 846 847 if ((cpuid = ddi_getprop(DDI_DEV_T_ANY, dip, 848 DDI_PROP_DONTPASS, "cpuid", -1)) == -1) { 849 return (DDI_WALK_CONTINUE); 850 } 851 852 portid = SG_CPUID_TO_PORTID(cpuid); 853 854 /* filter out nodes not on this board */ 855 if (SG_PORTID_TO_BOARD_NUM(portid) != args->board || 856 SG_PORTID_TO_NODEID(portid) != args->node) { 857 return (DDI_WALK_PRUNECHILD); 858 } 859 860 switch (impl) { 861 case CHEETAH_IMPL: 862 case CHEETAH_PLUS_IMPL: 863 case JAGUAR_IMPL: 864 args->non_panther_cpus++; 865 break; 866 case PANTHER_IMPL: 867 break; 868 default: 869 ASSERT(0); 870 args->non_panther_cpus++; 871 break; 872 } 873 874 SBDP_DBG_CPU("cpuid=0x%x, portid=0x%x, impl=0x%x, device_type=%s", 875 cpuid, portid, impl, buf); 876 877 return (DDI_WALK_CONTINUE); 878 } 879 880 int 881 sbdp_board_non_panther_cpus(int node, int board) 882 { 883 sbdp_node_walk_t arg = {0}; 884 885 arg.node = node; 886 arg.board = board; 887 888 /* 889 * Root node doesn't have to be held. 890 */ 891 ddi_walk_devs(ddi_root_node(), sbdp_find_non_panther_cpus, 892 (void *)&arg); 893 894 return (arg.non_panther_cpus); 895 } 896