1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1991 heppo * Common Development and Distribution License (the "License"). 6 1991 heppo * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 8542 Haik * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel #include <sys/types.h> 27 0 stevel #include <sys/systm.h> 28 0 stevel #include <sys/archsystm.h> 29 0 stevel #include <sys/t_lock.h> 30 0 stevel #include <sys/uadmin.h> 31 0 stevel #include <sys/panic.h> 32 0 stevel #include <sys/reboot.h> 33 0 stevel #include <sys/autoconf.h> 34 0 stevel #include <sys/machsystm.h> 35 0 stevel #include <sys/promif.h> 36 0 stevel #include <sys/membar.h> 37 0 stevel #include <vm/hat_sfmmu.h> 38 0 stevel #include <sys/cpu_module.h> 39 0 stevel #include <sys/cpu_sgnblk_defs.h> 40 0 stevel #include <sys/intreg.h> 41 0 stevel #include <sys/consdev.h> 42 0 stevel #include <sys/kdi_impl.h> 43 1077 svemuri #include <sys/traptrace.h> 44 0 stevel #include <sys/hypervisor_api.h> 45 0 stevel #include <sys/vmsystm.h> 46 0 stevel #include <sys/dtrace.h> 47 0 stevel #include <sys/xc_impl.h> 48 136 achartre #include <sys/callb.h> 49 1991 heppo #include <sys/mdesc.h> 50 1991 heppo #include <sys/mach_descrip.h> 51 2036 wentaoy #include <sys/wdt.h> 52 3266 jb145095 #include <sys/soft_state.h> 53 3266 jb145095 #include <sys/promimpl.h> 54 3266 jb145095 #include <sys/hsvc.h> 55 4776 jm22469 #include <sys/ldoms.h> 56 8542 Haik #include <sys/kldc.h> 57 11066 rafael #include <sys/clock_impl.h> 58 11172 Haik #include <sys/suspend.h> 59 10843 Dave #include <sys/dumphdr.h> 60 0 stevel 61 0 stevel /* 62 0 stevel * hvdump_buf_va is a pointer to the currently-configured hvdump_buf. 63 0 stevel * A value of NULL indicates that this area is not configured. 64 0 stevel * hvdump_buf_sz is tunable but will be clamped to HVDUMP_SIZE_MAX. 65 0 stevel */ 66 0 stevel 67 0 stevel caddr_t hvdump_buf_va; 68 0 stevel uint64_t hvdump_buf_sz = HVDUMP_SIZE_DEFAULT; 69 0 stevel static uint64_t hvdump_buf_pa; 70 0 stevel 71 1077 svemuri u_longlong_t panic_tick; 72 0 stevel 73 1077 svemuri extern u_longlong_t gettick(); 74 0 stevel static void reboot_machine(char *); 75 0 stevel static void update_hvdump_buffer(void); 76 0 stevel 77 0 stevel /* 78 0 stevel * For xt_sync synchronization. 79 0 stevel */ 80 0 stevel extern uint64_t xc_tick_limit; 81 0 stevel extern uint64_t xc_tick_jump_limit; 82 6138 svemuri extern uint64_t xc_sync_tick_limit; 83 0 stevel 84 0 stevel /* 85 0 stevel * We keep our own copies, used for cache flushing, because we can be called 86 0 stevel * before cpu_fiximpl(). 87 0 stevel */ 88 0 stevel static int kdi_dcache_size; 89 0 stevel static int kdi_dcache_linesize; 90 0 stevel static int kdi_icache_size; 91 0 stevel static int kdi_icache_linesize; 92 0 stevel 93 0 stevel /* 94 0 stevel * Assembly support for generic modules in sun4v/ml/mach_xc.s 95 0 stevel */ 96 0 stevel extern void init_mondo_nocheck(xcfunc_t *func, uint64_t arg1, uint64_t arg2); 97 0 stevel extern void kdi_flush_idcache(int, int, int, int); 98 0 stevel extern uint64_t get_cpuaddr(uint64_t, uint64_t); 99 0 stevel 100 4776 jm22469 101 4776 jm22469 #define BOOT_CMD_MAX_LEN 256 102 4776 jm22469 #define BOOT_CMD_BASE "boot " 103 4776 jm22469 104 4776 jm22469 /* 105 4776 jm22469 * In an LDoms system we do not save the user's boot args in NVRAM 106 4776 jm22469 * as is done on legacy systems. Instead, we format and send a 107 4776 jm22469 * 'reboot-command' variable to the variable service. The contents 108 4776 jm22469 * of the variable are retrieved by OBP and used verbatim for 109 4776 jm22469 * the next boot. 110 4776 jm22469 */ 111 4776 jm22469 static void 112 5974 jm22469 store_boot_cmd(char *args, boolean_t add_boot_str) 113 4776 jm22469 { 114 4776 jm22469 static char cmd_buf[BOOT_CMD_MAX_LEN]; 115 5974 jm22469 size_t len = 1; 116 4776 jm22469 pnode_t node; 117 5974 jm22469 size_t base_len = 0; 118 4776 jm22469 size_t args_len; 119 4776 jm22469 size_t args_max; 120 4776 jm22469 121 5974 jm22469 if (add_boot_str) { 122 5974 jm22469 (void) strcpy(cmd_buf, BOOT_CMD_BASE); 123 4776 jm22469 124 5974 jm22469 base_len = strlen(BOOT_CMD_BASE); 125 5974 jm22469 len = base_len + 1; 126 5974 jm22469 } 127 4776 jm22469 128 4776 jm22469 if (args != NULL) { 129 4776 jm22469 args_len = strlen(args); 130 4776 jm22469 args_max = BOOT_CMD_MAX_LEN - len; 131 4776 jm22469 132 4776 jm22469 if (args_len > args_max) { 133 4776 jm22469 cmn_err(CE_WARN, "Reboot command too long (%ld), " 134 4776 jm22469 "truncating command arguments", len + args_len); 135 4776 jm22469 136 4776 jm22469 args_len = args_max; 137 4776 jm22469 } 138 4776 jm22469 139 4776 jm22469 len += args_len; 140 4776 jm22469 (void) strncpy(&cmd_buf[base_len], args, args_len); 141 4776 jm22469 } 142 4776 jm22469 143 4776 jm22469 node = prom_optionsnode(); 144 4776 jm22469 if ((node == OBP_NONODE) || (node == OBP_BADNODE) || 145 4776 jm22469 prom_setprop(node, "reboot-command", cmd_buf, len) == -1) 146 4776 jm22469 cmn_err(CE_WARN, "Unable to store boot command for " 147 4776 jm22469 "use on reboot"); 148 4776 jm22469 } 149 4776 jm22469 150 4776 jm22469 151 0 stevel /* 152 0 stevel * Machine dependent code to reboot. 153 4776 jm22469 * 154 4776 jm22469 * "bootstr", when non-null, points to a string to be used as the 155 4776 jm22469 * argument string when rebooting. 156 136 achartre * 157 136 achartre * "invoke_cb" is a boolean. It is set to true when mdboot() can safely 158 136 achartre * invoke CB_CL_MDBOOT callbacks before shutting the system down, i.e. when 159 136 achartre * we are in a normal shutdown sequence (interrupts are not blocked, the 160 136 achartre * system is not panic'ing or being suspended). 161 0 stevel */ 162 0 stevel /*ARGSUSED*/ 163 0 stevel void 164 136 achartre mdboot(int cmd, int fcn, char *bootstr, boolean_t invoke_cb) 165 0 stevel { 166 0 stevel extern void pm_cfb_check_and_powerup(void); 167 5630 jbeck 168 5630 jbeck /* 169 5630 jbeck * XXX - rconsvp is set to NULL to ensure that output messages 170 5630 jbeck * are sent to the underlying "hardware" device using the 171 5630 jbeck * monitor's printf routine since we are in the process of 172 5630 jbeck * either rebooting or halting the machine. 173 5630 jbeck */ 174 5630 jbeck rconsvp = NULL; 175 4776 jm22469 176 4776 jm22469 switch (fcn) { 177 4776 jm22469 case AD_HALT: 178 5974 jm22469 /* 179 5974 jm22469 * LDoms: By storing a no-op command 180 5974 jm22469 * in the 'reboot-command' variable we cause OBP 181 5974 jm22469 * to ignore the setting of 'auto-boot?' after 182 5974 jm22469 * it completes the reset. This causes the system 183 5974 jm22469 * to stop at the ok prompt. 184 5974 jm22469 */ 185 5974 jm22469 if (domaining_enabled() && invoke_cb) 186 5974 jm22469 store_boot_cmd("noop", B_FALSE); 187 5974 jm22469 break; 188 5974 jm22469 189 4776 jm22469 case AD_POWEROFF: 190 4776 jm22469 break; 191 5974 jm22469 192 4776 jm22469 default: 193 4776 jm22469 if (bootstr == NULL) { 194 4776 jm22469 switch (fcn) { 195 4776 jm22469 196 4776 jm22469 case AD_BOOT: 197 4776 jm22469 bootstr = ""; 198 4776 jm22469 break; 199 4776 jm22469 200 4776 jm22469 case AD_IBOOT: 201 4776 jm22469 bootstr = "-a"; 202 4776 jm22469 break; 203 4776 jm22469 204 4776 jm22469 case AD_SBOOT: 205 4776 jm22469 bootstr = "-s"; 206 4776 jm22469 break; 207 4776 jm22469 208 4776 jm22469 case AD_SIBOOT: 209 4776 jm22469 bootstr = "-sa"; 210 4776 jm22469 break; 211 4776 jm22469 default: 212 4776 jm22469 cmn_err(CE_WARN, 213 4776 jm22469 "mdboot: invalid function %d", fcn); 214 4776 jm22469 bootstr = ""; 215 4776 jm22469 break; 216 4776 jm22469 } 217 4776 jm22469 } 218 5177 jm22469 219 5177 jm22469 /* 220 5177 jm22469 * If LDoms is running, we must save the boot string 221 5177 jm22469 * before we enter restricted mode. This is possible 222 5177 jm22469 * only if we are not being called from panic. 223 5177 jm22469 */ 224 5177 jm22469 if (domaining_enabled() && invoke_cb) 225 5974 jm22469 store_boot_cmd(bootstr, B_TRUE); 226 4776 jm22469 } 227 0 stevel 228 0 stevel /* 229 0 stevel * At a high interrupt level we can't: 230 0 stevel * 1) bring up the console 231 0 stevel * or 232 0 stevel * 2) wait for pending interrupts prior to redistribution 233 0 stevel * to the current CPU 234 0 stevel * 235 0 stevel * so we do them now. 236 0 stevel */ 237 0 stevel pm_cfb_check_and_powerup(); 238 0 stevel 239 0 stevel /* make sure there are no more changes to the device tree */ 240 0 stevel devtree_freeze(); 241 136 achartre 242 136 achartre if (invoke_cb) 243 136 achartre (void) callb_execute_class(CB_CL_MDBOOT, NULL); 244 917 elowe 245 917 elowe /* 246 917 elowe * Clear any unresolved UEs from memory. 247 917 elowe */ 248 3253 mec page_retire_mdboot(); 249 0 stevel 250 0 stevel /* 251 0 stevel * stop other cpus which also raise our priority. since there is only 252 0 stevel * one active cpu after this, and our priority will be too high 253 0 stevel * for us to be preempted, we're essentially single threaded 254 0 stevel * from here on out. 255 0 stevel */ 256 0 stevel stop_other_cpus(); 257 0 stevel 258 0 stevel /* 259 0 stevel * try and reset leaf devices. reset_leaves() should only 260 0 stevel * be called when there are no other threads that could be 261 0 stevel * accessing devices 262 0 stevel */ 263 0 stevel reset_leaves(); 264 2036 wentaoy 265 2036 wentaoy watchdog_clear(); 266 0 stevel 267 0 stevel if (fcn == AD_HALT) { 268 3266 jb145095 mach_set_soft_state(SIS_TRANSITION, 269 4776 jm22469 &SOLARIS_SOFT_STATE_HALT_MSG); 270 0 stevel halt((char *)NULL); 271 0 stevel } else if (fcn == AD_POWEROFF) { 272 3266 jb145095 mach_set_soft_state(SIS_TRANSITION, 273 4776 jm22469 &SOLARIS_SOFT_STATE_POWER_MSG); 274 0 stevel power_down(NULL); 275 0 stevel } else { 276 4776 jm22469 mach_set_soft_state(SIS_TRANSITION, 277 4776 jm22469 &SOLARIS_SOFT_STATE_REBOOT_MSG); 278 0 stevel reboot_machine(bootstr); 279 0 stevel } 280 0 stevel /* MAYBE REACHED */ 281 0 stevel } 282 0 stevel 283 0 stevel /* mdpreboot - may be called prior to mdboot while root fs still mounted */ 284 0 stevel /*ARGSUSED*/ 285 0 stevel void 286 0 stevel mdpreboot(int cmd, int fcn, char *bootstr) 287 0 stevel { 288 0 stevel } 289 0 stevel 290 0 stevel /* 291 0 stevel * Halt the machine and then reboot with the device 292 0 stevel * and arguments specified in bootstr. 293 0 stevel */ 294 0 stevel static void 295 0 stevel reboot_machine(char *bootstr) 296 0 stevel { 297 0 stevel flush_windows(); 298 0 stevel stop_other_cpus(); /* send stop signal to other CPUs */ 299 0 stevel prom_printf("rebooting...\n"); 300 0 stevel /* 301 0 stevel * For platforms that use CPU signatures, we 302 0 stevel * need to set the signature block to OS and 303 0 stevel * the state to exiting for all the processors. 304 0 stevel */ 305 0 stevel CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_REBOOT, -1); 306 0 stevel prom_reboot(bootstr); 307 0 stevel /*NOTREACHED*/ 308 0 stevel } 309 0 stevel 310 0 stevel /* 311 0 stevel * We use the x-trap mechanism and idle_stop_xcall() to stop the other CPUs. 312 0 stevel * Once in panic_idle() they raise spl, record their location, and spin. 313 0 stevel */ 314 0 stevel static void 315 0 stevel panic_idle(void) 316 0 stevel { 317 0 stevel (void) spl7(); 318 0 stevel 319 0 stevel debug_flush_windows(); 320 0 stevel (void) setjmp(&curthread->t_pcb); 321 0 stevel 322 0 stevel CPU->cpu_m.in_prom = 1; 323 0 stevel membar_stld(); 324 10843 Dave 325 10843 Dave dumpsys_helper(); 326 0 stevel 327 4776 jm22469 for (;;) 328 5974 jm22469 ; 329 0 stevel } 330 0 stevel 331 0 stevel /* 332 0 stevel * Force the other CPUs to trap into panic_idle(), and then remove them 333 0 stevel * from the cpu_ready_set so they will no longer receive cross-calls. 334 0 stevel */ 335 0 stevel /*ARGSUSED*/ 336 0 stevel void 337 0 stevel panic_stopcpus(cpu_t *cp, kthread_t *t, int spl) 338 0 stevel { 339 0 stevel cpuset_t cps; 340 0 stevel int i; 341 0 stevel 342 0 stevel (void) splzs(); 343 0 stevel CPUSET_ALL_BUT(cps, cp->cpu_id); 344 0 stevel xt_some(cps, (xcfunc_t *)idle_stop_xcall, (uint64_t)&panic_idle, NULL); 345 0 stevel 346 0 stevel for (i = 0; i < NCPU; i++) { 347 0 stevel if (i != cp->cpu_id && CPU_XCALL_READY(i)) { 348 0 stevel int ntries = 0x10000; 349 0 stevel 350 0 stevel while (!cpu[i]->cpu_m.in_prom && ntries) { 351 0 stevel DELAY(50); 352 0 stevel ntries--; 353 0 stevel } 354 0 stevel 355 0 stevel if (!cpu[i]->cpu_m.in_prom) 356 0 stevel printf("panic: failed to stop cpu%d\n", i); 357 0 stevel 358 0 stevel cpu[i]->cpu_flags &= ~CPU_READY; 359 0 stevel cpu[i]->cpu_flags |= CPU_QUIESCED; 360 0 stevel CPUSET_DEL(cpu_ready_set, cpu[i]->cpu_id); 361 0 stevel } 362 0 stevel } 363 0 stevel } 364 0 stevel 365 0 stevel /* 366 0 stevel * Platform callback following each entry to panicsys(). If we've panicked at 367 0 stevel * level 14, we examine t_panic_trap to see if a fatal trap occurred. If so, 368 0 stevel * we disable further %tick_cmpr interrupts. If not, an explicit call to panic 369 0 stevel * was made and so we re-enqueue an interrupt request structure to allow 370 0 stevel * further level 14 interrupts to be processed once we lower PIL. This allows 371 0 stevel * us to handle panics from the deadman() CY_HIGH_LEVEL cyclic. 372 0 stevel */ 373 0 stevel void 374 0 stevel panic_enter_hw(int spl) 375 0 stevel { 376 1077 svemuri if (!panic_tick) { 377 1077 svemuri panic_tick = gettick(); 378 1077 svemuri if (mach_htraptrace_enable) { 379 1077 svemuri uint64_t prev_freeze; 380 1077 svemuri 381 1077 svemuri /* there are no possible error codes for this hcall */ 382 1077 svemuri (void) hv_ttrace_freeze((uint64_t)TRAP_TFREEZE_ALL, 383 1077 svemuri &prev_freeze); 384 1077 svemuri } 385 526 arao #ifdef TRAPTRACE 386 526 arao TRAPTRACE_FREEZE; 387 1077 svemuri #endif 388 526 arao } 389 3266 jb145095 390 3266 jb145095 mach_set_soft_state(SIS_TRANSITION, &SOLARIS_SOFT_STATE_PANIC_MSG); 391 3266 jb145095 392 0 stevel if (spl == ipltospl(PIL_14)) { 393 0 stevel uint_t opstate = disable_vec_intr(); 394 0 stevel 395 0 stevel if (curthread->t_panic_trap != NULL) { 396 0 stevel tickcmpr_disable(); 397 0 stevel intr_dequeue_req(PIL_14, cbe_level14_inum); 398 0 stevel } else { 399 0 stevel if (!tickcmpr_disabled()) 400 0 stevel intr_enqueue_req(PIL_14, cbe_level14_inum); 401 0 stevel /* 402 0 stevel * Clear SOFTINT<14>, SOFTINT<0> (TICK_INT) 403 0 stevel * and SOFTINT<16> (STICK_INT) to indicate 404 0 stevel * that the current level 14 has been serviced. 405 0 stevel */ 406 0 stevel wr_clr_softint((1 << PIL_14) | 407 4776 jm22469 TICK_INT_MASK | STICK_INT_MASK); 408 0 stevel } 409 0 stevel 410 0 stevel enable_vec_intr(opstate); 411 0 stevel } 412 0 stevel } 413 0 stevel 414 0 stevel /* 415 0 stevel * Miscellaneous hardware-specific code to execute after panicstr is set 416 0 stevel * by the panic code: we also print and record PTL1 panic information here. 417 0 stevel */ 418 0 stevel /*ARGSUSED*/ 419 0 stevel void 420 0 stevel panic_quiesce_hw(panic_data_t *pdp) 421 0 stevel { 422 0 stevel extern uint_t getpstate(void); 423 0 stevel extern void setpstate(uint_t); 424 0 stevel 425 0 stevel /* 426 0 stevel * Turn off TRAPTRACE and save the current %tick value in panic_tick. 427 0 stevel */ 428 1077 svemuri if (!panic_tick) { 429 0 stevel panic_tick = gettick(); 430 1077 svemuri if (mach_htraptrace_enable) { 431 1077 svemuri uint64_t prev_freeze; 432 1077 svemuri 433 1077 svemuri /* there are no possible error codes for this hcall */ 434 1077 svemuri (void) hv_ttrace_freeze((uint64_t)TRAP_TFREEZE_ALL, 435 1077 svemuri &prev_freeze); 436 1077 svemuri } 437 1077 svemuri #ifdef TRAPTRACE 438 1077 svemuri TRAPTRACE_FREEZE; 439 0 stevel #endif 440 1077 svemuri } 441 0 stevel /* 442 0 stevel * For Platforms that use CPU signatures, we 443 0 stevel * need to set the signature block to OS, the state to 444 0 stevel * exiting, and the substate to panic for all the processors. 445 0 stevel */ 446 0 stevel CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_PANIC, -1); 447 0 stevel 448 0 stevel update_hvdump_buffer(); 449 0 stevel 450 0 stevel /* 451 0 stevel * Disable further ECC errors from the bus nexus. 452 0 stevel */ 453 0 stevel (void) bus_func_invoke(BF_TYPE_ERRDIS); 454 0 stevel 455 0 stevel /* 456 0 stevel * Redirect all interrupts to the current CPU. 457 0 stevel */ 458 0 stevel intr_redist_all_cpus_shutdown(); 459 0 stevel 460 0 stevel /* 461 0 stevel * This call exists solely to support dumps to network 462 0 stevel * devices after sync from OBP. 463 0 stevel * 464 0 stevel * If we came here via the sync callback, then on some 465 0 stevel * platforms, interrupts may have arrived while we were 466 0 stevel * stopped in OBP. OBP will arrange for those interrupts to 467 0 stevel * be redelivered if you say "go", but not if you invoke a 468 0 stevel * client callback like 'sync'. For some dump devices 469 0 stevel * (network swap devices), we need interrupts to be 470 0 stevel * delivered in order to dump, so we have to call the bus 471 0 stevel * nexus driver to reset the interrupt state machines. 472 0 stevel */ 473 0 stevel (void) bus_func_invoke(BF_TYPE_RESINTR); 474 0 stevel 475 0 stevel setpstate(getpstate() | PSTATE_IE); 476 0 stevel } 477 0 stevel 478 0 stevel /* 479 0 stevel * Platforms that use CPU signatures need to set the signature block to OS and 480 0 stevel * the state to exiting for all CPUs. PANIC_CONT indicates that we're about to 481 0 stevel * write the crash dump, which tells the SSP/SMS to begin a timeout routine to 482 0 stevel * reboot the machine if the dump never completes. 483 0 stevel */ 484 0 stevel /*ARGSUSED*/ 485 0 stevel void 486 0 stevel panic_dump_hw(int spl) 487 0 stevel { 488 0 stevel CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_DUMP, -1); 489 0 stevel } 490 0 stevel 491 0 stevel /* 492 0 stevel * for ptl1_panic 493 0 stevel */ 494 0 stevel void 495 0 stevel ptl1_init_cpu(struct cpu *cpu) 496 0 stevel { 497 0 stevel ptl1_state_t *pstate = &cpu->cpu_m.ptl1_state; 498 0 stevel 499 0 stevel /*CONSTCOND*/ 500 0 stevel if (sizeof (struct cpu) + PTL1_SSIZE > CPU_ALLOC_SIZE) { 501 0 stevel panic("ptl1_init_cpu: not enough space left for ptl1_panic " 502 911 iskreen "stack, sizeof (struct cpu) = %lu", 503 911 iskreen (unsigned long)sizeof (struct cpu)); 504 0 stevel } 505 0 stevel 506 0 stevel pstate->ptl1_stktop = (uintptr_t)cpu + CPU_ALLOC_SIZE; 507 0 stevel cpu_pa[cpu->cpu_id] = va_to_pa(cpu); 508 0 stevel } 509 0 stevel 510 0 stevel void 511 0 stevel ptl1_panic_handler(ptl1_state_t *pstate) 512 0 stevel { 513 0 stevel static const char *ptl1_reasons[] = { 514 0 stevel #ifdef PTL1_PANIC_DEBUG 515 0 stevel "trap for debug purpose", /* PTL1_BAD_DEBUG */ 516 0 stevel #else 517 0 stevel "unknown trap", /* PTL1_BAD_DEBUG */ 518 0 stevel #endif 519 0 stevel "register window trap", /* PTL1_BAD_WTRAP */ 520 0 stevel "kernel MMU miss", /* PTL1_BAD_KMISS */ 521 0 stevel "kernel protection fault", /* PTL1_BAD_KPROT_FAULT */ 522 0 stevel "ISM MMU miss", /* PTL1_BAD_ISM */ 523 0 stevel "kernel MMU trap", /* PTL1_BAD_MMUTRAP */ 524 0 stevel "kernel trap handler state", /* PTL1_BAD_TRAP */ 525 0 stevel "floating point trap", /* PTL1_BAD_FPTRAP */ 526 0 stevel #ifdef DEBUG 527 2973 govinda "pointer to intr_vec", /* PTL1_BAD_INTR_VEC */ 528 0 stevel #else 529 2973 govinda "unknown trap", /* PTL1_BAD_INTR_VEC */ 530 0 stevel #endif 531 0 stevel #ifdef TRAPTRACE 532 0 stevel "TRACE_PTR state", /* PTL1_BAD_TRACE_PTR */ 533 0 stevel #else 534 0 stevel "unknown trap", /* PTL1_BAD_TRACE_PTR */ 535 0 stevel #endif 536 0 stevel "stack overflow", /* PTL1_BAD_STACK */ 537 0 stevel "DTrace flags", /* PTL1_BAD_DTRACE_FLAGS */ 538 0 stevel "attempt to steal locked ctx", /* PTL1_BAD_CTX_STEAL */ 539 0 stevel "CPU ECC error loop", /* PTL1_BAD_ECC */ 540 0 stevel "unexpected error from hypervisor call", /* PTL1_BAD_HCALL */ 541 526 arao "unexpected global level(%gl)", /* PTL1_BAD_GL */ 542 1991 heppo "Watchdog Reset", /* PTL1_BAD_WATCHDOG */ 543 1991 heppo "unexpected RED mode trap", /* PTL1_BAD_RED */ 544 1991 heppo "return value EINVAL from hcall: "\ 545 1991 heppo "UNMAP_PERM_ADDR", /* PTL1_BAD_HCALL_UNMAP_PERM_EINVAL */ 546 1991 heppo "return value ENOMAP from hcall: "\ 547 1991 heppo "UNMAP_PERM_ADDR", /* PTL1_BAD_HCALL_UNMAP_PERM_ENOMAP */ 548 6044 paulsan "error raising a TSB exception", /* PTL1_BAD_RAISE_TSBEXCP */ 549 6044 paulsan "missing shared TSB" /* PTL1_NO_SCDTSB8K */ 550 0 stevel }; 551 0 stevel 552 357 svemuri uint_t reason = pstate->ptl1_regs.ptl1_gregs[0].ptl1_g1; 553 0 stevel uint_t tl = pstate->ptl1_regs.ptl1_trap_regs[0].ptl1_tl; 554 5084 johnlev struct panic_trap_info ti = { 0 }; 555 0 stevel 556 0 stevel /* 557 0 stevel * Use trap_info for a place holder to call panic_savetrap() and 558 0 stevel * panic_showtrap() to save and print out ptl1_panic information. 559 0 stevel */ 560 0 stevel if (curthread->t_panic_trap == NULL) 561 0 stevel curthread->t_panic_trap = &ti; 562 0 stevel 563 0 stevel if (reason < sizeof (ptl1_reasons) / sizeof (ptl1_reasons[0])) 564 0 stevel panic("bad %s at TL %u", ptl1_reasons[reason], tl); 565 0 stevel else 566 0 stevel panic("ptl1_panic reason 0x%x at TL %u", reason, tl); 567 0 stevel } 568 0 stevel 569 0 stevel void 570 0 stevel clear_watchdog_on_exit(void) 571 0 stevel { 572 3349 wentaoy if (watchdog_enabled && watchdog_activated) { 573 3349 wentaoy prom_printf("Debugging requested; hardware watchdog " 574 4776 jm22469 "suspended.\n"); 575 3349 wentaoy (void) watchdog_suspend(); 576 3349 wentaoy } 577 0 stevel } 578 0 stevel 579 2036 wentaoy /* 580 2036 wentaoy * Restore the watchdog timer when returning from a debugger 581 2036 wentaoy * after a panic or L1-A and resume watchdog pat. 582 2036 wentaoy */ 583 0 stevel void 584 2036 wentaoy restore_watchdog_on_entry() 585 0 stevel { 586 2036 wentaoy watchdog_resume(); 587 0 stevel } 588 0 stevel 589 0 stevel int 590 0 stevel kdi_watchdog_disable(void) 591 0 stevel { 592 2036 wentaoy watchdog_suspend(); 593 2036 wentaoy 594 2036 wentaoy return (0); 595 0 stevel } 596 0 stevel 597 0 stevel void 598 0 stevel kdi_watchdog_restore(void) 599 0 stevel { 600 2036 wentaoy watchdog_resume(); 601 0 stevel } 602 0 stevel 603 0 stevel void 604 0 stevel mach_dump_buffer_init(void) 605 0 stevel { 606 0 stevel uint64_t ret, minsize = 0; 607 0 stevel 608 0 stevel if (hvdump_buf_sz > HVDUMP_SIZE_MAX) 609 0 stevel hvdump_buf_sz = HVDUMP_SIZE_MAX; 610 0 stevel 611 288 arao hvdump_buf_va = contig_mem_alloc_align(hvdump_buf_sz, PAGESIZE); 612 0 stevel if (hvdump_buf_va == NULL) 613 0 stevel return; 614 0 stevel 615 0 stevel hvdump_buf_pa = va_to_pa(hvdump_buf_va); 616 0 stevel 617 0 stevel ret = hv_dump_buf_update(hvdump_buf_pa, hvdump_buf_sz, 618 0 stevel &minsize); 619 0 stevel 620 0 stevel if (ret != H_EOK) { 621 0 stevel contig_mem_free(hvdump_buf_va, hvdump_buf_sz); 622 0 stevel hvdump_buf_va = NULL; 623 0 stevel cmn_err(CE_NOTE, "!Error in setting up hvstate" 624 0 stevel "dump buffer. Error = 0x%lx, size = 0x%lx," 625 0 stevel "buf_pa = 0x%lx", ret, hvdump_buf_sz, 626 0 stevel hvdump_buf_pa); 627 0 stevel 628 0 stevel if (ret == H_EINVAL) { 629 0 stevel cmn_err(CE_NOTE, "!Buffer size too small." 630 0 stevel "Available buffer size = 0x%lx," 631 0 stevel "Minimum buffer size required = 0x%lx", 632 0 stevel hvdump_buf_sz, minsize); 633 0 stevel } 634 0 stevel } 635 0 stevel } 636 0 stevel 637 0 stevel 638 0 stevel static void 639 0 stevel update_hvdump_buffer(void) 640 0 stevel { 641 0 stevel uint64_t ret, dummy_val; 642 0 stevel 643 0 stevel if (hvdump_buf_va == NULL) 644 0 stevel return; 645 0 stevel 646 0 stevel ret = hv_dump_buf_update(hvdump_buf_pa, hvdump_buf_sz, 647 0 stevel &dummy_val); 648 0 stevel if (ret != H_EOK) { 649 0 stevel cmn_err(CE_NOTE, "!Cannot update hvstate dump" 650 0 stevel "buffer. Error = 0x%lx", ret); 651 0 stevel } 652 0 stevel } 653 0 stevel 654 0 stevel 655 0 stevel static int 656 789 ahrens getintprop(pnode_t node, char *name, int deflt) 657 0 stevel { 658 0 stevel int value; 659 0 stevel 660 0 stevel switch (prom_getproplen(node, name)) { 661 0 stevel case 0: 662 0 stevel value = 1; /* boolean properties */ 663 0 stevel break; 664 0 stevel 665 0 stevel case sizeof (int): 666 0 stevel (void) prom_getprop(node, name, (caddr_t)&value); 667 0 stevel break; 668 0 stevel 669 0 stevel default: 670 0 stevel value = deflt; 671 0 stevel break; 672 0 stevel } 673 0 stevel 674 0 stevel return (value); 675 0 stevel } 676 0 stevel 677 0 stevel /* 678 0 stevel * Called by setcpudelay 679 0 stevel */ 680 0 stevel void 681 0 stevel cpu_init_tick_freq(void) 682 0 stevel { 683 1991 heppo md_t *mdp; 684 1991 heppo mde_cookie_t rootnode; 685 1991 heppo int listsz; 686 1991 heppo mde_cookie_t *listp = NULL; 687 1991 heppo int num_nodes; 688 1991 heppo uint64_t stick_prop; 689 1991 heppo 690 1991 heppo if (broken_md_flag) { 691 1991 heppo sys_tick_freq = cpunodes[CPU->cpu_id].clock_freq; 692 1991 heppo return; 693 1991 heppo } 694 1991 heppo 695 1991 heppo if ((mdp = md_get_handle()) == NULL) 696 1991 heppo panic("stick_frequency property not found in MD"); 697 1991 heppo 698 1991 heppo rootnode = md_root_node(mdp); 699 1991 heppo ASSERT(rootnode != MDE_INVAL_ELEM_COOKIE); 700 1991 heppo 701 1991 heppo num_nodes = md_node_count(mdp); 702 1991 heppo 703 1991 heppo ASSERT(num_nodes > 0); 704 1991 heppo listsz = num_nodes * sizeof (mde_cookie_t); 705 1991 heppo listp = (mde_cookie_t *)prom_alloc((caddr_t)0, listsz, 0); 706 1991 heppo 707 1991 heppo if (listp == NULL) 708 1991 heppo panic("cannot allocate list for MD properties"); 709 1991 heppo 710 1991 heppo num_nodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "platform"), 711 1991 heppo md_find_name(mdp, "fwd"), listp); 712 1991 heppo 713 1991 heppo ASSERT(num_nodes == 1); 714 1991 heppo 715 1991 heppo if (md_get_prop_val(mdp, *listp, "stick-frequency", &stick_prop) != 0) 716 1991 heppo panic("stick_frequency property not found in MD"); 717 1991 heppo 718 1991 heppo sys_tick_freq = stick_prop; 719 1991 heppo 720 1991 heppo prom_free((caddr_t)listp, listsz); 721 1991 heppo (void) md_fini_handle(mdp); 722 0 stevel } 723 0 stevel 724 0 stevel int shipit(int n, uint64_t cpu_list_ra); 725 0 stevel 726 0 stevel #ifdef DEBUG 727 0 stevel #define SEND_MONDO_STATS 1 728 0 stevel #endif 729 0 stevel 730 0 stevel #ifdef SEND_MONDO_STATS 731 0 stevel uint32_t x_one_stimes[64]; 732 0 stevel uint32_t x_one_ltimes[16]; 733 0 stevel uint32_t x_set_stimes[64]; 734 0 stevel uint32_t x_set_ltimes[16]; 735 0 stevel uint32_t x_set_cpus[NCPU]; 736 0 stevel #endif 737 0 stevel 738 0 stevel void 739 0 stevel send_one_mondo(int cpuid) 740 0 stevel { 741 0 stevel int retries, stat; 742 0 stevel uint64_t starttick, endtick, tick, lasttick; 743 0 stevel struct machcpu *mcpup = &(CPU->cpu_m); 744 0 stevel 745 0 stevel CPU_STATS_ADDQ(CPU, sys, xcalls, 1); 746 0 stevel starttick = lasttick = gettick(); 747 0 stevel mcpup->cpu_list[0] = (uint16_t)cpuid; 748 0 stevel stat = shipit(1, mcpup->cpu_list_ra); 749 0 stevel endtick = starttick + xc_tick_limit; 750 0 stevel retries = 0; 751 1310 ha137994 while (stat != H_EOK) { 752 1310 ha137994 if (stat != H_EWOULDBLOCK) { 753 1310 ha137994 if (panic_quiesce) 754 1310 ha137994 return; 755 1310 ha137994 if (stat == H_ECPUERROR) 756 1310 ha137994 cmn_err(CE_PANIC, "send_one_mondo: " 757 1310 ha137994 "cpuid: 0x%x has been marked in " 758 1310 ha137994 "error", cpuid); 759 1310 ha137994 else 760 1310 ha137994 cmn_err(CE_PANIC, "send_one_mondo: " 761 1310 ha137994 "unexpected hypervisor error 0x%x " 762 1310 ha137994 "while sending a mondo to cpuid: " 763 1310 ha137994 "0x%x", stat, cpuid); 764 1310 ha137994 } 765 0 stevel tick = gettick(); 766 0 stevel /* 767 0 stevel * If there is a big jump between the current tick 768 0 stevel * count and lasttick, we have probably hit a break 769 0 stevel * point. Adjust endtick accordingly to avoid panic. 770 0 stevel */ 771 0 stevel if (tick > (lasttick + xc_tick_jump_limit)) 772 0 stevel endtick += (tick - lasttick); 773 0 stevel lasttick = tick; 774 0 stevel if (tick > endtick) { 775 0 stevel if (panic_quiesce) 776 0 stevel return; 777 0 stevel cmn_err(CE_PANIC, "send mondo timeout " 778 0 stevel "(target 0x%x) [retries: 0x%x hvstat: 0x%x]", 779 0 stevel cpuid, retries, stat); 780 0 stevel } 781 0 stevel drv_usecwait(1); 782 0 stevel stat = shipit(1, mcpup->cpu_list_ra); 783 0 stevel retries++; 784 0 stevel } 785 0 stevel #ifdef SEND_MONDO_STATS 786 0 stevel { 787 1310 ha137994 uint64_t n = gettick() - starttick; 788 0 stevel if (n < 8192) 789 0 stevel x_one_stimes[n >> 7]++; 790 1310 ha137994 else if (n < 15*8192) 791 1310 ha137994 x_one_ltimes[n >> 13]++; 792 0 stevel else 793 0 stevel x_one_ltimes[0xf]++; 794 0 stevel } 795 0 stevel #endif 796 0 stevel } 797 0 stevel 798 0 stevel void 799 0 stevel send_mondo_set(cpuset_t set) 800 0 stevel { 801 0 stevel uint64_t starttick, endtick, tick, lasttick; 802 2492 ha137994 uint_t largestid, smallestid; 803 2492 ha137994 int i, j; 804 2492 ha137994 int ncpuids = 0; 805 0 stevel int shipped = 0; 806 1310 ha137994 int retries = 0; 807 0 stevel struct machcpu *mcpup = &(CPU->cpu_m); 808 0 stevel 809 0 stevel ASSERT(!CPUSET_ISNULL(set)); 810 2492 ha137994 CPUSET_BOUNDS(set, smallestid, largestid); 811 2492 ha137994 if (smallestid == CPUSET_NOTINSET) { 812 2492 ha137994 return; 813 2492 ha137994 } 814 2492 ha137994 815 0 stevel starttick = lasttick = gettick(); 816 0 stevel endtick = starttick + xc_tick_limit; 817 0 stevel 818 2492 ha137994 /* 819 2492 ha137994 * Assemble CPU list for HV argument. We already know 820 2492 ha137994 * smallestid and largestid are members of set. 821 2492 ha137994 */ 822 2492 ha137994 mcpup->cpu_list[ncpuids++] = (uint16_t)smallestid; 823 2492 ha137994 if (largestid != smallestid) { 824 2492 ha137994 for (i = smallestid+1; i <= largestid-1; i++) { 825 1310 ha137994 if (CPU_IN_SET(set, i)) { 826 2492 ha137994 mcpup->cpu_list[ncpuids++] = (uint16_t)i; 827 0 stevel } 828 0 stevel } 829 2492 ha137994 mcpup->cpu_list[ncpuids++] = (uint16_t)largestid; 830 2492 ha137994 } 831 2492 ha137994 832 2492 ha137994 do { 833 2492 ha137994 int stat; 834 0 stevel 835 1310 ha137994 stat = shipit(ncpuids, mcpup->cpu_list_ra); 836 1310 ha137994 if (stat == H_EOK) { 837 1310 ha137994 shipped += ncpuids; 838 1310 ha137994 break; 839 1310 ha137994 } 840 1310 ha137994 841 1310 ha137994 /* 842 1310 ha137994 * Either not all CPU mondos were sent, or an 843 1310 ha137994 * error occurred. CPUs that were sent mondos 844 1310 ha137994 * have their CPU IDs overwritten in cpu_list. 845 2492 ha137994 * Reset cpu_list so that it only holds those 846 2492 ha137994 * CPU IDs that still need to be sent. 847 1310 ha137994 */ 848 2492 ha137994 for (i = 0, j = 0; i < ncpuids; i++) { 849 1310 ha137994 if (mcpup->cpu_list[i] == HV_SEND_MONDO_ENTRYDONE) { 850 1310 ha137994 shipped++; 851 1310 ha137994 } else { 852 2492 ha137994 mcpup->cpu_list[j++] = mcpup->cpu_list[i]; 853 1310 ha137994 } 854 1310 ha137994 } 855 2492 ha137994 ncpuids = j; 856 1310 ha137994 857 1310 ha137994 /* 858 1310 ha137994 * Now handle possible errors returned 859 1310 ha137994 * from hypervisor. 860 1310 ha137994 */ 861 1310 ha137994 if (stat == H_ECPUERROR) { 862 2492 ha137994 int errorcpus; 863 2492 ha137994 864 2492 ha137994 if (!panic_quiesce) 865 2492 ha137994 cmn_err(CE_CONT, "send_mondo_set: cpuid(s) "); 866 1310 ha137994 867 1310 ha137994 /* 868 2492 ha137994 * Remove any CPUs in the error state from 869 2492 ha137994 * cpu_list. At this point cpu_list only 870 2492 ha137994 * contains the CPU IDs for mondos not 871 2492 ha137994 * succesfully sent. 872 1310 ha137994 */ 873 2492 ha137994 for (i = 0, errorcpus = 0; i < ncpuids; i++) { 874 2492 ha137994 uint64_t state = CPU_STATE_INVALID; 875 2492 ha137994 uint16_t id = mcpup->cpu_list[i]; 876 2492 ha137994 877 2492 ha137994 (void) hv_cpu_state(id, &state); 878 2492 ha137994 if (state == CPU_STATE_ERROR) { 879 2492 ha137994 if (!panic_quiesce) 880 2492 ha137994 cmn_err(CE_CONT, "0x%x ", id); 881 2492 ha137994 errorcpus++; 882 2492 ha137994 } else if (errorcpus > 0) { 883 2492 ha137994 mcpup->cpu_list[i - errorcpus] = 884 2492 ha137994 mcpup->cpu_list[i]; 885 1310 ha137994 } 886 1310 ha137994 } 887 2492 ha137994 ncpuids -= errorcpus; 888 1310 ha137994 889 1310 ha137994 if (!panic_quiesce) { 890 2492 ha137994 if (errorcpus == 0) { 891 2492 ha137994 cmn_err(CE_CONT, "<none> have been " 892 2492 ha137994 "marked in error\n"); 893 1310 ha137994 cmn_err(CE_PANIC, "send_mondo_set: " 894 1310 ha137994 "hypervisor returned " 895 1310 ha137994 "H_ECPUERROR but no CPU in " 896 1310 ha137994 "cpu_list in error state"); 897 2492 ha137994 } else { 898 2492 ha137994 cmn_err(CE_CONT, "have been marked in " 899 2492 ha137994 "error\n"); 900 2492 ha137994 cmn_err(CE_PANIC, "send_mondo_set: " 901 2492 ha137994 "CPU(s) in error state"); 902 1310 ha137994 } 903 1310 ha137994 } 904 1310 ha137994 } else if (stat != H_EWOULDBLOCK) { 905 1310 ha137994 if (panic_quiesce) 906 1310 ha137994 return; 907 1310 ha137994 /* 908 1310 ha137994 * For all other errors, panic. 909 1310 ha137994 */ 910 1310 ha137994 cmn_err(CE_CONT, "send_mondo_set: unexpected " 911 1310 ha137994 "hypervisor error 0x%x while sending a " 912 1310 ha137994 "mondo to cpuid(s):", stat); 913 2492 ha137994 for (i = 0; i < ncpuids; i++) { 914 2492 ha137994 cmn_err(CE_CONT, " 0x%x", mcpup->cpu_list[i]); 915 1310 ha137994 } 916 1310 ha137994 cmn_err(CE_CONT, "\n"); 917 1310 ha137994 cmn_err(CE_PANIC, "send_mondo_set: unexpected " 918 1310 ha137994 "hypervisor error"); 919 1310 ha137994 } 920 1310 ha137994 921 0 stevel tick = gettick(); 922 0 stevel /* 923 0 stevel * If there is a big jump between the current tick 924 0 stevel * count and lasttick, we have probably hit a break 925 0 stevel * point. Adjust endtick accordingly to avoid panic. 926 0 stevel */ 927 0 stevel if (tick > (lasttick + xc_tick_jump_limit)) 928 0 stevel endtick += (tick - lasttick); 929 0 stevel lasttick = tick; 930 0 stevel if (tick > endtick) { 931 0 stevel if (panic_quiesce) 932 0 stevel return; 933 0 stevel cmn_err(CE_CONT, "send mondo timeout " 934 0 stevel "[retries: 0x%x] cpuids: ", retries); 935 2492 ha137994 for (i = 0; i < ncpuids; i++) 936 2492 ha137994 cmn_err(CE_CONT, " 0x%x", mcpup->cpu_list[i]); 937 0 stevel cmn_err(CE_CONT, "\n"); 938 0 stevel cmn_err(CE_PANIC, "send_mondo_set: timeout"); 939 0 stevel } 940 0 stevel 941 0 stevel while (gettick() < (tick + sys_clock_mhz)) 942 0 stevel ; 943 0 stevel retries++; 944 2492 ha137994 } while (ncpuids > 0); 945 1310 ha137994 946 1310 ha137994 CPU_STATS_ADDQ(CPU, sys, xcalls, shipped); 947 0 stevel 948 0 stevel #ifdef SEND_MONDO_STATS 949 0 stevel { 950 1310 ha137994 uint64_t n = gettick() - starttick; 951 0 stevel if (n < 8192) 952 0 stevel x_set_stimes[n >> 7]++; 953 1310 ha137994 else if (n < 15*8192) 954 1310 ha137994 x_set_ltimes[n >> 13]++; 955 0 stevel else 956 0 stevel x_set_ltimes[0xf]++; 957 0 stevel } 958 0 stevel x_set_cpus[shipped]++; 959 0 stevel #endif 960 0 stevel } 961 0 stevel 962 0 stevel void 963 0 stevel syncfpu(void) 964 0 stevel { 965 0 stevel } 966 0 stevel 967 0 stevel void 968 0 stevel sticksync_slave(void) 969 11172 Haik { 970 11172 Haik suspend_sync_tick_stick_npt(); 971 11172 Haik } 972 0 stevel 973 0 stevel void 974 0 stevel sticksync_master(void) 975 0 stevel {} 976 0 stevel 977 0 stevel void 978 0 stevel cpu_init_cache_scrub(void) 979 3266 jb145095 { 980 3266 jb145095 mach_set_soft_state(SIS_NORMAL, &SOLARIS_SOFT_STATE_RUN_MSG); 981 3266 jb145095 } 982 0 stevel 983 0 stevel int 984 0 stevel dtrace_blksuword32_err(uintptr_t addr, uint32_t *data) 985 0 stevel { 986 0 stevel int ret, watched; 987 0 stevel 988 0 stevel watched = watch_disable_addr((void *)addr, 4, S_WRITE); 989 0 stevel ret = dtrace_blksuword32(addr, data, 0); 990 0 stevel if (watched) 991 0 stevel watch_enable_addr((void *)addr, 4, S_WRITE); 992 0 stevel 993 0 stevel return (ret); 994 0 stevel } 995 0 stevel 996 0 stevel int 997 0 stevel dtrace_blksuword32(uintptr_t addr, uint32_t *data, int tryagain) 998 0 stevel { 999 0 stevel if (suword32((void *)addr, *data) == -1) 1000 0 stevel return (tryagain ? dtrace_blksuword32_err(addr, data) : -1); 1001 0 stevel dtrace_flush_sec(addr); 1002 0 stevel 1003 0 stevel return (0); 1004 0 stevel } 1005 0 stevel 1006 0 stevel /*ARGSUSED*/ 1007 0 stevel void 1008 0 stevel cpu_faulted_enter(struct cpu *cp) 1009 0 stevel { 1010 0 stevel } 1011 0 stevel 1012 0 stevel /*ARGSUSED*/ 1013 0 stevel void 1014 0 stevel cpu_faulted_exit(struct cpu *cp) 1015 0 stevel { 1016 0 stevel } 1017 0 stevel 1018 0 stevel static int 1019 0 stevel kdi_cpu_ready_iter(int (*cb)(int, void *), void *arg) 1020 0 stevel { 1021 0 stevel int rc, i; 1022 0 stevel 1023 0 stevel for (rc = 0, i = 0; i < NCPU; i++) { 1024 0 stevel if (CPU_IN_SET(cpu_ready_set, i)) 1025 0 stevel rc += cb(i, arg); 1026 0 stevel } 1027 0 stevel 1028 0 stevel return (rc); 1029 0 stevel } 1030 0 stevel 1031 0 stevel /* 1032 0 stevel * Sends a cross-call to a specified processor. The caller assumes 1033 0 stevel * responsibility for repetition of cross-calls, as appropriate (MARSA for 1034 0 stevel * debugging). 1035 0 stevel */ 1036 0 stevel static int 1037 0 stevel kdi_xc_one(int cpuid, void (*func)(uintptr_t, uintptr_t), uintptr_t arg1, 1038 0 stevel uintptr_t arg2) 1039 0 stevel { 1040 0 stevel int stat; 1041 0 stevel struct machcpu *mcpup; 1042 0 stevel uint64_t cpuaddr_reg = 0, cpuaddr_scr = 0; 1043 0 stevel 1044 0 stevel mcpup = &(((cpu_t *)get_cpuaddr(cpuaddr_reg, cpuaddr_scr))->cpu_m); 1045 0 stevel 1046 0 stevel /* 1047 0 stevel * if (idsr_busy()) 1048 0 stevel * return (KDI_XC_RES_ERR); 1049 0 stevel */ 1050 0 stevel 1051 0 stevel init_mondo_nocheck((xcfunc_t *)func, arg1, arg2); 1052 0 stevel 1053 0 stevel mcpup->cpu_list[0] = (uint16_t)cpuid; 1054 0 stevel stat = shipit(1, mcpup->cpu_list_ra); 1055 0 stevel 1056 0 stevel if (stat == 0) 1057 0 stevel return (KDI_XC_RES_OK); 1058 0 stevel else 1059 0 stevel return (KDI_XC_RES_NACK); 1060 0 stevel } 1061 0 stevel 1062 0 stevel static void 1063 0 stevel kdi_tickwait(clock_t nticks) 1064 0 stevel { 1065 0 stevel clock_t endtick = gettick() + nticks; 1066 0 stevel 1067 4776 jm22469 while (gettick() < endtick) 1068 5974 jm22469 ; 1069 0 stevel } 1070 0 stevel 1071 0 stevel static void 1072 0 stevel kdi_cpu_init(int dcache_size, int dcache_linesize, int icache_size, 1073 0 stevel int icache_linesize) 1074 0 stevel { 1075 0 stevel kdi_dcache_size = dcache_size; 1076 0 stevel kdi_dcache_linesize = dcache_linesize; 1077 0 stevel kdi_icache_size = icache_size; 1078 0 stevel kdi_icache_linesize = icache_linesize; 1079 0 stevel } 1080 0 stevel 1081 0 stevel /* used directly by kdi_read/write_phys */ 1082 0 stevel void 1083 0 stevel kdi_flush_caches(void) 1084 0 stevel { 1085 10271 Jason /* Not required on sun4v architecture. */ 1086 0 stevel } 1087 0 stevel 1088 0 stevel /*ARGSUSED*/ 1089 0 stevel int 1090 0 stevel kdi_get_stick(uint64_t *stickp) 1091 0 stevel { 1092 0 stevel return (-1); 1093 0 stevel } 1094 0 stevel 1095 0 stevel void 1096 0 stevel cpu_kdi_init(kdi_t *kdi) 1097 0 stevel { 1098 0 stevel kdi->kdi_flush_caches = kdi_flush_caches; 1099 0 stevel kdi->mkdi_cpu_init = kdi_cpu_init; 1100 0 stevel kdi->mkdi_cpu_ready_iter = kdi_cpu_ready_iter; 1101 0 stevel kdi->mkdi_xc_one = kdi_xc_one; 1102 0 stevel kdi->mkdi_tickwait = kdi_tickwait; 1103 0 stevel kdi->mkdi_get_stick = kdi_get_stick; 1104 0 stevel } 1105 0 stevel 1106 3266 jb145095 uint64_t soft_state_message_ra[SOLARIS_SOFT_STATE_MSG_CNT]; 1107 3266 jb145095 static uint64_t soft_state_saved_state = (uint64_t)-1; 1108 3266 jb145095 static int soft_state_initialized = 0; 1109 3266 jb145095 static uint64_t soft_state_sup_minor; /* Supported minor number */ 1110 3266 jb145095 static hsvc_info_t soft_state_hsvc = { 1111 3266 jb145095 HSVC_REV_1, NULL, HSVC_GROUP_SOFT_STATE, 1, 0, NULL }; 1112 3266 jb145095 1113 3266 jb145095 1114 2036 wentaoy static void 1115 2036 wentaoy sun4v_system_claim(void) 1116 2036 wentaoy { 1117 11066 rafael lbolt_debug_entry(); 1118 11066 rafael 1119 2036 wentaoy watchdog_suspend(); 1120 8542 Haik kldc_debug_enter(); 1121 3266 jb145095 /* 1122 3266 jb145095 * For "mdb -K", set soft state to debugging 1123 3266 jb145095 */ 1124 3266 jb145095 if (soft_state_saved_state == -1) { 1125 3266 jb145095 mach_get_soft_state(&soft_state_saved_state, 1126 4776 jm22469 &SOLARIS_SOFT_STATE_SAVED_MSG); 1127 3266 jb145095 } 1128 3266 jb145095 /* 1129 3266 jb145095 * check again as the read above may or may not have worked and if 1130 3266 jb145095 * it didn't then soft state will still be -1 1131 3266 jb145095 */ 1132 3266 jb145095 if (soft_state_saved_state != -1) { 1133 3266 jb145095 mach_set_soft_state(SIS_TRANSITION, 1134 4776 jm22469 &SOLARIS_SOFT_STATE_DEBUG_MSG); 1135 3266 jb145095 } 1136 2036 wentaoy } 1137 2036 wentaoy 1138 2036 wentaoy static void 1139 2036 wentaoy sun4v_system_release(void) 1140 2036 wentaoy { 1141 2036 wentaoy watchdog_resume(); 1142 3266 jb145095 /* 1143 3266 jb145095 * For "mdb -K", set soft_state state back to original state on exit 1144 3266 jb145095 */ 1145 3266 jb145095 if (soft_state_saved_state != -1) { 1146 3266 jb145095 mach_set_soft_state(soft_state_saved_state, 1147 4776 jm22469 &SOLARIS_SOFT_STATE_SAVED_MSG); 1148 3266 jb145095 soft_state_saved_state = -1; 1149 3266 jb145095 } 1150 11066 rafael 1151 11066 rafael lbolt_debug_return(); 1152 2036 wentaoy } 1153 2036 wentaoy 1154 2036 wentaoy void 1155 2036 wentaoy plat_kdi_init(kdi_t *kdi) 1156 2036 wentaoy { 1157 2036 wentaoy kdi->pkdi_system_claim = sun4v_system_claim; 1158 2036 wentaoy kdi->pkdi_system_release = sun4v_system_release; 1159 2036 wentaoy } 1160 2036 wentaoy 1161 0 stevel /* 1162 0 stevel * Routine to return memory information associated 1163 0 stevel * with a physical address and syndrome. 1164 0 stevel */ 1165 0 stevel /* ARGSUSED */ 1166 0 stevel int 1167 0 stevel cpu_get_mem_info(uint64_t synd, uint64_t afar, 1168 0 stevel uint64_t *mem_sizep, uint64_t *seg_sizep, uint64_t *bank_sizep, 1169 0 stevel int *segsp, int *banksp, int *mcidp) 1170 0 stevel { 1171 0 stevel return (ENOTSUP); 1172 0 stevel } 1173 0 stevel 1174 0 stevel /* 1175 0 stevel * This routine returns the size of the kernel's FRU name buffer. 1176 0 stevel */ 1177 0 stevel size_t 1178 0 stevel cpu_get_name_bufsize() 1179 0 stevel { 1180 0 stevel return (UNUM_NAMLEN); 1181 0 stevel } 1182 0 stevel 1183 0 stevel /* 1184 0 stevel * This routine is a more generic interface to cpu_get_mem_unum(), 1185 0 stevel * that may be used by other modules (e.g. mm). 1186 0 stevel */ 1187 0 stevel /* ARGSUSED */ 1188 0 stevel int 1189 0 stevel cpu_get_mem_name(uint64_t synd, uint64_t *afsr, uint64_t afar, 1190 0 stevel char *buf, int buflen, int *lenp) 1191 0 stevel { 1192 0 stevel return (ENOTSUP); 1193 0 stevel } 1194 0 stevel 1195 1186 ayznaga /* ARGSUSED */ 1196 1186 ayznaga int 1197 1186 ayznaga cpu_get_mem_sid(char *unum, char *buf, int buflen, int *lenp) 1198 1186 ayznaga { 1199 1186 ayznaga return (ENOTSUP); 1200 1186 ayznaga } 1201 1186 ayznaga 1202 1186 ayznaga /* ARGSUSED */ 1203 1186 ayznaga int 1204 1186 ayznaga cpu_get_mem_addr(char *unum, char *sid, uint64_t offset, uint64_t *addrp) 1205 1186 ayznaga { 1206 1186 ayznaga return (ENOTSUP); 1207 1186 ayznaga } 1208 1186 ayznaga 1209 0 stevel /* 1210 0 stevel * xt_sync - wait for previous x-traps to finish 1211 0 stevel */ 1212 0 stevel void 1213 0 stevel xt_sync(cpuset_t cpuset) 1214 0 stevel { 1215 0 stevel union { 1216 0 stevel uint8_t volatile byte[NCPU]; 1217 0 stevel uint64_t volatile xword[NCPU / 8]; 1218 0 stevel } cpu_sync; 1219 5146 svemuri uint64_t starttick, endtick, tick, lasttick, traptrace_id; 1220 2492 ha137994 uint_t largestid, smallestid; 1221 3316 rf157361 int i, j; 1222 0 stevel 1223 0 stevel kpreempt_disable(); 1224 0 stevel CPUSET_DEL(cpuset, CPU->cpu_id); 1225 0 stevel CPUSET_AND(cpuset, cpu_ready_set); 1226 2492 ha137994 1227 2492 ha137994 CPUSET_BOUNDS(cpuset, smallestid, largestid); 1228 2492 ha137994 if (smallestid == CPUSET_NOTINSET) 1229 2492 ha137994 goto out; 1230 0 stevel 1231 0 stevel /* 1232 0 stevel * Sun4v uses a queue for receiving mondos. Successful 1233 0 stevel * transmission of a mondo only indicates that the mondo 1234 0 stevel * has been written into the queue. 1235 0 stevel * 1236 0 stevel * We use an array of bytes to let each cpu to signal back 1237 0 stevel * to the cross trap sender that the cross trap has been 1238 0 stevel * executed. Set the byte to 1 before sending the cross trap 1239 0 stevel * and wait until other cpus reset it to 0. 1240 0 stevel */ 1241 0 stevel bzero((void *)&cpu_sync, NCPU); 1242 2492 ha137994 cpu_sync.byte[smallestid] = 1; 1243 2492 ha137994 if (largestid != smallestid) { 1244 2492 ha137994 for (i = (smallestid + 1); i <= (largestid - 1); i++) 1245 2492 ha137994 if (CPU_IN_SET(cpuset, i)) 1246 2492 ha137994 cpu_sync.byte[i] = 1; 1247 2492 ha137994 cpu_sync.byte[largestid] = 1; 1248 2492 ha137994 } 1249 0 stevel 1250 5146 svemuri /* 1251 5146 svemuri * To help debug xt_sync panic, each mondo is uniquely identified 1252 5146 svemuri * by passing the tick value, traptrace_id as the second mondo 1253 5146 svemuri * argument to xt_some which is logged in CPU's mondo queue, 1254 5146 svemuri * traptrace buffer and the panic message. 1255 5146 svemuri */ 1256 5146 svemuri traptrace_id = gettick(); 1257 0 stevel xt_some(cpuset, (xcfunc_t *)xt_sync_tl1, 1258 5146 svemuri (uint64_t)cpu_sync.byte, traptrace_id); 1259 0 stevel 1260 0 stevel starttick = lasttick = gettick(); 1261 6138 svemuri endtick = starttick + xc_sync_tick_limit; 1262 0 stevel 1263 2492 ha137994 for (i = (smallestid / 8); i <= (largestid / 8); i++) { 1264 0 stevel while (cpu_sync.xword[i] != 0) { 1265 0 stevel tick = gettick(); 1266 0 stevel /* 1267 0 stevel * If there is a big jump between the current tick 1268 0 stevel * count and lasttick, we have probably hit a break 1269 0 stevel * point. Adjust endtick accordingly to avoid panic. 1270 0 stevel */ 1271 0 stevel if (tick > (lasttick + xc_tick_jump_limit)) { 1272 0 stevel endtick += (tick - lasttick); 1273 0 stevel } 1274 0 stevel lasttick = tick; 1275 0 stevel if (tick > endtick) { 1276 0 stevel if (panic_quiesce) 1277 0 stevel goto out; 1278 3316 rf157361 cmn_err(CE_CONT, "Cross trap sync timeout: " 1279 5146 svemuri "at cpu_sync.xword[%d]: 0x%lx " 1280 5146 svemuri "cpu_sync.byte: 0x%lx " 1281 5146 svemuri "starttick: 0x%lx endtick: 0x%lx " 1282 5146 svemuri "traptrace_id = 0x%lx\n", 1283 5146 svemuri i, cpu_sync.xword[i], 1284 5146 svemuri (uint64_t)cpu_sync.byte, 1285 5146 svemuri starttick, endtick, traptrace_id); 1286 5146 svemuri cmn_err(CE_CONT, "CPUIDs:"); 1287 3316 rf157361 for (j = (i * 8); j <= largestid; j++) { 1288 3316 rf157361 if (cpu_sync.byte[j] != 0) 1289 3316 rf157361 cmn_err(CE_CONT, " 0x%x", j); 1290 3316 rf157361 } 1291 0 stevel cmn_err(CE_PANIC, "xt_sync: timeout"); 1292 0 stevel } 1293 0 stevel } 1294 0 stevel } 1295 0 stevel 1296 0 stevel out: 1297 0 stevel kpreempt_enable(); 1298 0 stevel } 1299 2957 jm22469 1300 6138 svemuri #define QFACTOR 200 1301 2957 jm22469 /* 1302 2957 jm22469 * Recalculate the values of the cross-call timeout variables based 1303 2957 jm22469 * on the value of the 'inter-cpu-latency' property of the platform node. 1304 2957 jm22469 * The property sets the number of nanosec to wait for a cross-call 1305 2957 jm22469 * to be acknowledged. Other timeout variables are derived from it. 1306 2957 jm22469 * 1307 2957 jm22469 * N.B. This implementation is aware of the internals of xc_init() 1308 2957 jm22469 * and updates many of the same variables. 1309 2957 jm22469 */ 1310 2957 jm22469 void 1311 2957 jm22469 recalc_xc_timeouts(void) 1312 2957 jm22469 { 1313 2957 jm22469 typedef union { 1314 2957 jm22469 uint64_t whole; 1315 2957 jm22469 struct { 1316 2957 jm22469 uint_t high; 1317 2957 jm22469 uint_t low; 1318 2957 jm22469 } half; 1319 2957 jm22469 } u_number; 1320 2957 jm22469 1321 2957 jm22469 /* See x_call.c for descriptions of these extern variables. */ 1322 2957 jm22469 extern uint64_t xc_tick_limit_scale; 1323 2957 jm22469 extern uint64_t xc_mondo_time_limit; 1324 2957 jm22469 extern uint64_t xc_func_time_limit; 1325 2957 jm22469 extern uint64_t xc_scale; 1326 2957 jm22469 extern uint64_t xc_mondo_multiplier; 1327 2957 jm22469 extern uint_t nsec_shift; 1328 2957 jm22469 1329 2957 jm22469 /* Temp versions of the target variables */ 1330 2957 jm22469 uint64_t tick_limit; 1331 2957 jm22469 uint64_t tick_jump_limit; 1332 2957 jm22469 uint64_t mondo_time_limit; 1333 2957 jm22469 uint64_t func_time_limit; 1334 2957 jm22469 uint64_t scale; 1335 2957 jm22469 1336 2957 jm22469 uint64_t latency; /* nanoseconds */ 1337 2957 jm22469 uint64_t maxfreq; 1338 2957 jm22469 uint64_t tick_limit_save = xc_tick_limit; 1339 6138 svemuri uint64_t sync_tick_limit_save = xc_sync_tick_limit; 1340 2957 jm22469 uint_t tick_scale; 1341 2957 jm22469 uint64_t top; 1342 2957 jm22469 uint64_t bottom; 1343 2957 jm22469 u_number tk; 1344 2957 jm22469 1345 2957 jm22469 md_t *mdp; 1346 2957 jm22469 int nrnode; 1347 2957 jm22469 mde_cookie_t *platlist; 1348 2957 jm22469 1349 2957 jm22469 /* 1350 2957 jm22469 * Look up the 'inter-cpu-latency' (optional) property in the 1351 2957 jm22469 * platform node of the MD. The units are nanoseconds. 1352 2957 jm22469 */ 1353 2957 jm22469 if ((mdp = md_get_handle()) == NULL) { 1354 2957 jm22469 cmn_err(CE_WARN, "recalc_xc_timeouts: " 1355 2957 jm22469 "Unable to initialize machine description"); 1356 2957 jm22469 return; 1357 2957 jm22469 } 1358 2957 jm22469 1359 2957 jm22469 nrnode = md_alloc_scan_dag(mdp, 1360 2957 jm22469 md_root_node(mdp), "platform", "fwd", &platlist); 1361 2957 jm22469 1362 2957 jm22469 ASSERT(nrnode == 1); 1363 2957 jm22469 if (nrnode < 1) { 1364 2957 jm22469 cmn_err(CE_WARN, "recalc_xc_timeouts: platform node missing"); 1365 3069 jm22469 goto done; 1366 2957 jm22469 } 1367 2957 jm22469 if (md_get_prop_val(mdp, platlist[0], 1368 2957 jm22469 "inter-cpu-latency", &latency) == -1) 1369 3069 jm22469 goto done; 1370 2957 jm22469 1371 2957 jm22469 /* 1372 2957 jm22469 * clock.h defines an assembly-language macro 1373 2957 jm22469 * (NATIVE_TIME_TO_NSEC_SCALE) to convert from %stick 1374 2957 jm22469 * units to nanoseconds. Since the inter-cpu-latency 1375 2957 jm22469 * units are nanoseconds and the xc_* variables require 1376 2957 jm22469 * %stick units, we need the inverse of that function. 1377 2957 jm22469 * The trick is to perform the calculation without 1378 2957 jm22469 * floating point, but also without integer truncation 1379 2957 jm22469 * or overflow. To understand the calculation below, 1380 2957 jm22469 * please read the discussion of the macro in clock.h. 1381 2957 jm22469 * Since this new code will be invoked infrequently, 1382 2957 jm22469 * we can afford to implement it in C. 1383 2957 jm22469 * 1384 2957 jm22469 * tick_scale is the reciprocal of nsec_scale which is 1385 2957 jm22469 * calculated at startup in setcpudelay(). The calc 1386 2957 jm22469 * of tick_limit parallels that of NATIVE_TIME_TO_NSEC_SCALE 1387 2957 jm22469 * except we use tick_scale instead of nsec_scale and 1388 2957 jm22469 * C instead of assembler. 1389 2957 jm22469 */ 1390 2957 jm22469 tick_scale = (uint_t)(((u_longlong_t)sys_tick_freq 1391 2957 jm22469 << (32 - nsec_shift)) / NANOSEC); 1392 2957 jm22469 1393 2957 jm22469 tk.whole = latency; 1394 2957 jm22469 top = ((uint64_t)tk.half.high << 4) * tick_scale; 1395 2957 jm22469 bottom = (((uint64_t)tk.half.low << 4) * (uint64_t)tick_scale) >> 32; 1396 2957 jm22469 tick_limit = top + bottom; 1397 2957 jm22469 1398 2957 jm22469 /* 1399 2957 jm22469 * xc_init() calculated 'maxfreq' by looking at all the cpus, 1400 2957 jm22469 * and used it to derive some of the timeout variables that we 1401 2957 jm22469 * recalculate below. We can back into the original value by 1402 2957 jm22469 * using the inverse of one of those calculations. 1403 2957 jm22469 */ 1404 2957 jm22469 maxfreq = xc_mondo_time_limit / xc_scale; 1405 2957 jm22469 1406 2957 jm22469 /* 1407 2957 jm22469 * Don't allow the new timeout (xc_tick_limit) to fall below 1408 2957 jm22469 * the system tick frequency (stick). Allowing the timeout 1409 2957 jm22469 * to be set more tightly than this empirically determined 1410 2957 jm22469 * value may cause panics. 1411 2957 jm22469 */ 1412 2957 jm22469 tick_limit = tick_limit < sys_tick_freq ? sys_tick_freq : tick_limit; 1413 2957 jm22469 1414 2957 jm22469 tick_jump_limit = tick_limit / 32; 1415 2957 jm22469 tick_limit *= xc_tick_limit_scale; 1416 2957 jm22469 1417 2957 jm22469 /* 1418 2957 jm22469 * Recalculate xc_scale since it is used in a callback function 1419 2957 jm22469 * (xc_func_timeout_adj) to adjust two of the timeouts dynamically. 1420 2957 jm22469 * Make the change in xc_scale proportional to the change in 1421 2957 jm22469 * xc_tick_limit. 1422 2957 jm22469 */ 1423 2957 jm22469 scale = (xc_scale * tick_limit + sys_tick_freq / 2) / tick_limit_save; 1424 2957 jm22469 if (scale == 0) 1425 2957 jm22469 scale = 1; 1426 2957 jm22469 1427 2957 jm22469 mondo_time_limit = maxfreq * scale; 1428 2957 jm22469 func_time_limit = mondo_time_limit * xc_mondo_multiplier; 1429 2957 jm22469 1430 2957 jm22469 /* 1431 2957 jm22469 * Don't modify the timeouts if nothing has changed. Else, 1432 2957 jm22469 * stuff the variables with the freshly calculated (temp) 1433 2957 jm22469 * variables. This minimizes the window where the set of 1434 2957 jm22469 * values could be inconsistent. 1435 2957 jm22469 */ 1436 2957 jm22469 if (tick_limit != xc_tick_limit) { 1437 2957 jm22469 xc_tick_limit = tick_limit; 1438 2957 jm22469 xc_tick_jump_limit = tick_jump_limit; 1439 2957 jm22469 xc_scale = scale; 1440 2957 jm22469 xc_mondo_time_limit = mondo_time_limit; 1441 2957 jm22469 xc_func_time_limit = func_time_limit; 1442 2957 jm22469 } 1443 3069 jm22469 1444 3069 jm22469 done: 1445 6138 svemuri /* 1446 6138 svemuri * Increase the timeout limit for xt_sync() cross calls. 1447 6138 svemuri */ 1448 6138 svemuri xc_sync_tick_limit = xc_tick_limit * (cpu_q_entries / QFACTOR); 1449 6138 svemuri xc_sync_tick_limit = xc_sync_tick_limit < xc_tick_limit ? 1450 6138 svemuri xc_tick_limit : xc_sync_tick_limit; 1451 6138 svemuri 1452 6138 svemuri /* 1453 6138 svemuri * Force the new values to be used for future cross calls. 1454 6138 svemuri * This is necessary only when we increase the timeouts. 1455 6138 svemuri */ 1456 6138 svemuri if ((xc_tick_limit > tick_limit_save) || (xc_sync_tick_limit > 1457 6138 svemuri sync_tick_limit_save)) { 1458 6138 svemuri cpuset_t cpuset = cpu_ready_set; 1459 6138 svemuri xt_sync(cpuset); 1460 6138 svemuri } 1461 6138 svemuri 1462 3069 jm22469 if (nrnode > 0) 1463 3069 jm22469 md_free_scan_dag(mdp, &platlist); 1464 3069 jm22469 (void) md_fini_handle(mdp); 1465 2957 jm22469 } 1466 3266 jb145095 1467 3266 jb145095 void 1468 3266 jb145095 mach_soft_state_init(void) 1469 3266 jb145095 { 1470 3266 jb145095 int i; 1471 3266 jb145095 uint64_t ra; 1472 3266 jb145095 1473 3266 jb145095 /* 1474 3266 jb145095 * Try to register soft_state api. If it fails, soft_state api has not 1475 3266 jb145095 * been implemented in the firmware, so do not bother to setup 1476 3266 jb145095 * soft_state in the kernel. 1477 3266 jb145095 */ 1478 3266 jb145095 if ((i = hsvc_register(&soft_state_hsvc, &soft_state_sup_minor)) != 0) { 1479 3266 jb145095 return; 1480 3266 jb145095 } 1481 3266 jb145095 for (i = 0; i < SOLARIS_SOFT_STATE_MSG_CNT; i++) { 1482 3266 jb145095 ASSERT(strlen((const char *)(void *) 1483 4776 jm22469 soft_state_message_strings + i) < SSM_SIZE); 1484 4776 jm22469 if ((ra = va_to_pa( 1485 4776 jm22469 (void *)(soft_state_message_strings + i))) == -1ll) { 1486 3266 jb145095 return; 1487 3266 jb145095 } 1488 3266 jb145095 soft_state_message_ra[i] = ra; 1489 3266 jb145095 } 1490 3266 jb145095 /* 1491 3266 jb145095 * Tell OBP that we are supporting Guest State 1492 3266 jb145095 */ 1493 3266 jb145095 prom_sun4v_soft_state_supported(); 1494 3266 jb145095 soft_state_initialized = 1; 1495 3266 jb145095 } 1496 3266 jb145095 1497 3266 jb145095 void 1498 3266 jb145095 mach_set_soft_state(uint64_t state, uint64_t *string_ra) 1499 3266 jb145095 { 1500 3266 jb145095 uint64_t rc; 1501 3266 jb145095 1502 3266 jb145095 if (soft_state_initialized && *string_ra) { 1503 3266 jb145095 rc = hv_soft_state_set(state, *string_ra); 1504 3266 jb145095 if (rc != H_EOK) { 1505 5146 svemuri cmn_err(CE_WARN, 1506 5146 svemuri "hv_soft_state_set returned %ld\n", rc); 1507 3266 jb145095 } 1508 3266 jb145095 } 1509 3266 jb145095 } 1510 3266 jb145095 1511 3266 jb145095 void 1512 3266 jb145095 mach_get_soft_state(uint64_t *state, uint64_t *string_ra) 1513 3266 jb145095 { 1514 4776 jm22469 uint64_t rc; 1515 3266 jb145095 1516 3266 jb145095 if (soft_state_initialized && *string_ra) { 1517 3266 jb145095 rc = hv_soft_state_get(*string_ra, state); 1518 3266 jb145095 if (rc != H_EOK) { 1519 5146 svemuri cmn_err(CE_WARN, 1520 5146 svemuri "hv_soft_state_get returned %ld\n", rc); 1521 3266 jb145095 *state = -1; 1522 3266 jb145095 } 1523 3266 jb145095 } 1524 3266 jb145095 } 1525