10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*2036Swentaoy * Common Development and Distribution License (the "License"). 6*2036Swentaoy * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 221270Sbs21162 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <sys/types.h> 290Sstevel@tonic-gate #include <sys/t_lock.h> 300Sstevel@tonic-gate #include <sys/uadmin.h> 310Sstevel@tonic-gate #include <sys/panic.h> 320Sstevel@tonic-gate #include <sys/reboot.h> 330Sstevel@tonic-gate #include <sys/autoconf.h> 340Sstevel@tonic-gate #include <sys/machsystm.h> 350Sstevel@tonic-gate #include <sys/promif.h> 360Sstevel@tonic-gate #include <sys/membar.h> 370Sstevel@tonic-gate #include <vm/hat_sfmmu.h> 380Sstevel@tonic-gate #include <sys/cpu_module.h> 390Sstevel@tonic-gate #include <sys/cpu_sgnblk_defs.h> 400Sstevel@tonic-gate #include <sys/intreg.h> 410Sstevel@tonic-gate #include <sys/consdev.h> 420Sstevel@tonic-gate #include <sys/kdi_impl.h> 43136Sachartre #include <sys/callb.h> 440Sstevel@tonic-gate 450Sstevel@tonic-gate #ifdef TRAPTRACE 460Sstevel@tonic-gate #include <sys/traptrace.h> 470Sstevel@tonic-gate u_longlong_t panic_tick; 480Sstevel@tonic-gate #endif /* TRAPTRACE */ 490Sstevel@tonic-gate 500Sstevel@tonic-gate extern u_longlong_t gettick(); 510Sstevel@tonic-gate static void reboot_machine(char *); 52*2036Swentaoy int disable_watchdog_on_exit = 0; 530Sstevel@tonic-gate 540Sstevel@tonic-gate /* 550Sstevel@tonic-gate * Machine dependent code to reboot. 560Sstevel@tonic-gate * "mdep" is interpreted as a character pointer; if non-null, it is a pointer 570Sstevel@tonic-gate * to a string to be used as the argument string when rebooting. 58136Sachartre * 59136Sachartre * "invoke_cb" is a boolean. It is set to true when mdboot() can safely 60136Sachartre * invoke CB_CL_MDBOOT callbacks before shutting the system down, i.e. when 61136Sachartre * we are in a normal shutdown sequence (interrupts are not blocked, the 62136Sachartre * system is not panic'ing or being suspended). 630Sstevel@tonic-gate */ 640Sstevel@tonic-gate /*ARGSUSED*/ 650Sstevel@tonic-gate void 66136Sachartre mdboot(int cmd, int fcn, char *bootstr, boolean_t invoke_cb) 670Sstevel@tonic-gate { 680Sstevel@tonic-gate extern void pm_cfb_check_and_powerup(void); 690Sstevel@tonic-gate 700Sstevel@tonic-gate /* 710Sstevel@tonic-gate * Disable the hw watchdog timer. 720Sstevel@tonic-gate */ 730Sstevel@tonic-gate if (disable_watchdog_on_exit && watchdog_activated) { 740Sstevel@tonic-gate mutex_enter(&tod_lock); 750Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 760Sstevel@tonic-gate mutex_exit(&tod_lock); 770Sstevel@tonic-gate } 780Sstevel@tonic-gate 790Sstevel@tonic-gate /* 800Sstevel@tonic-gate * XXX - rconsvp is set to NULL to ensure that output messages 810Sstevel@tonic-gate * are sent to the underlying "hardware" device using the 820Sstevel@tonic-gate * monitor's printf routine since we are in the process of 830Sstevel@tonic-gate * either rebooting or halting the machine. 840Sstevel@tonic-gate */ 850Sstevel@tonic-gate rconsvp = NULL; 860Sstevel@tonic-gate 870Sstevel@tonic-gate /* 880Sstevel@tonic-gate * At a high interrupt level we can't: 890Sstevel@tonic-gate * 1) bring up the console 900Sstevel@tonic-gate * or 910Sstevel@tonic-gate * 2) wait for pending interrupts prior to redistribution 920Sstevel@tonic-gate * to the current CPU 930Sstevel@tonic-gate * 940Sstevel@tonic-gate * so we do them now. 950Sstevel@tonic-gate */ 960Sstevel@tonic-gate pm_cfb_check_and_powerup(); 970Sstevel@tonic-gate 980Sstevel@tonic-gate /* make sure there are no more changes to the device tree */ 990Sstevel@tonic-gate devtree_freeze(); 1000Sstevel@tonic-gate 101136Sachartre if (invoke_cb) 102136Sachartre (void) callb_execute_class(CB_CL_MDBOOT, NULL); 103136Sachartre 1040Sstevel@tonic-gate /* 105917Selowe * Clear any unresolved UEs from memory. 106917Selowe */ 107917Selowe if (memsegs != NULL) 108917Selowe page_retire_hunt(page_retire_mdboot_cb); 109917Selowe 110917Selowe /* 1110Sstevel@tonic-gate * stop other cpus which also raise our priority. since there is only 1120Sstevel@tonic-gate * one active cpu after this, and our priority will be too high 1130Sstevel@tonic-gate * for us to be preempted, we're essentially single threaded 1140Sstevel@tonic-gate * from here on out. 1150Sstevel@tonic-gate */ 1160Sstevel@tonic-gate stop_other_cpus(); 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate /* 1190Sstevel@tonic-gate * try and reset leaf devices. reset_leaves() should only 1200Sstevel@tonic-gate * be called when there are no other threads that could be 1210Sstevel@tonic-gate * accessing devices 1220Sstevel@tonic-gate */ 1230Sstevel@tonic-gate reset_leaves(); 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate if (fcn == AD_HALT) { 1260Sstevel@tonic-gate halt((char *)NULL); 1270Sstevel@tonic-gate } else if (fcn == AD_POWEROFF) { 1280Sstevel@tonic-gate power_down(NULL); 1290Sstevel@tonic-gate } else { 1300Sstevel@tonic-gate if (bootstr == NULL) { 1310Sstevel@tonic-gate switch (fcn) { 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate case AD_BOOT: 1340Sstevel@tonic-gate bootstr = ""; 1350Sstevel@tonic-gate break; 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate case AD_IBOOT: 1380Sstevel@tonic-gate bootstr = "-a"; 1390Sstevel@tonic-gate break; 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate case AD_SBOOT: 1420Sstevel@tonic-gate bootstr = "-s"; 1430Sstevel@tonic-gate break; 1440Sstevel@tonic-gate 1450Sstevel@tonic-gate case AD_SIBOOT: 1460Sstevel@tonic-gate bootstr = "-sa"; 1470Sstevel@tonic-gate break; 1480Sstevel@tonic-gate default: 1490Sstevel@tonic-gate cmn_err(CE_WARN, 1500Sstevel@tonic-gate "mdboot: invalid function %d", fcn); 1510Sstevel@tonic-gate bootstr = ""; 1520Sstevel@tonic-gate break; 1530Sstevel@tonic-gate } 1540Sstevel@tonic-gate } 1550Sstevel@tonic-gate reboot_machine(bootstr); 1560Sstevel@tonic-gate } 1570Sstevel@tonic-gate /* MAYBE REACHED */ 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate /* mdpreboot - may be called prior to mdboot while root fs still mounted */ 1610Sstevel@tonic-gate /*ARGSUSED*/ 1620Sstevel@tonic-gate void 1630Sstevel@tonic-gate mdpreboot(int cmd, int fcn, char *bootstr) 1640Sstevel@tonic-gate { 1650Sstevel@tonic-gate } 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate /* 1680Sstevel@tonic-gate * Halt the machine and then reboot with the device 1690Sstevel@tonic-gate * and arguments specified in bootstr. 1700Sstevel@tonic-gate */ 1710Sstevel@tonic-gate static void 1720Sstevel@tonic-gate reboot_machine(char *bootstr) 1730Sstevel@tonic-gate { 1740Sstevel@tonic-gate flush_windows(); 1750Sstevel@tonic-gate stop_other_cpus(); /* send stop signal to other CPUs */ 1760Sstevel@tonic-gate prom_printf("rebooting...\n"); 1770Sstevel@tonic-gate /* 1780Sstevel@tonic-gate * For platforms that use CPU signatures, we 1790Sstevel@tonic-gate * need to set the signature block to OS and 1800Sstevel@tonic-gate * the state to exiting for all the processors. 1810Sstevel@tonic-gate */ 1820Sstevel@tonic-gate CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_REBOOT, -1); 1830Sstevel@tonic-gate prom_reboot(bootstr); 1840Sstevel@tonic-gate /*NOTREACHED*/ 1850Sstevel@tonic-gate } 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate /* 1880Sstevel@tonic-gate * We use the x-trap mechanism and idle_stop_xcall() to stop the other CPUs. 1890Sstevel@tonic-gate * Once in panic_idle() they raise spl, record their location, and spin. 1900Sstevel@tonic-gate */ 1910Sstevel@tonic-gate static void 1920Sstevel@tonic-gate panic_idle(void) 1930Sstevel@tonic-gate { 1940Sstevel@tonic-gate cpu_async_panic_callb(); /* check for async errors */ 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate (void) spl7(); 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate debug_flush_windows(); 1990Sstevel@tonic-gate (void) setjmp(&curthread->t_pcb); 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate CPU->cpu_m.in_prom = 1; 2020Sstevel@tonic-gate membar_stld(); 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate for (;;); 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate /* 2080Sstevel@tonic-gate * Force the other CPUs to trap into panic_idle(), and then remove them 2090Sstevel@tonic-gate * from the cpu_ready_set so they will no longer receive cross-calls. 2100Sstevel@tonic-gate */ 2110Sstevel@tonic-gate /*ARGSUSED*/ 2120Sstevel@tonic-gate void 2130Sstevel@tonic-gate panic_stopcpus(cpu_t *cp, kthread_t *t, int spl) 2140Sstevel@tonic-gate { 2150Sstevel@tonic-gate cpuset_t cps; 2160Sstevel@tonic-gate int i; 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate (void) splzs(); 2190Sstevel@tonic-gate CPUSET_ALL_BUT(cps, cp->cpu_id); 2200Sstevel@tonic-gate xt_some(cps, (xcfunc_t *)idle_stop_xcall, (uint64_t)&panic_idle, NULL); 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate for (i = 0; i < NCPU; i++) { 2230Sstevel@tonic-gate if (i != cp->cpu_id && CPU_XCALL_READY(i)) { 2240Sstevel@tonic-gate int ntries = 0x10000; 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate while (!cpu[i]->cpu_m.in_prom && ntries) { 2270Sstevel@tonic-gate DELAY(50); 2280Sstevel@tonic-gate ntries--; 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate if (!cpu[i]->cpu_m.in_prom) 2320Sstevel@tonic-gate printf("panic: failed to stop cpu%d\n", i); 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate cpu[i]->cpu_flags &= ~CPU_READY; 2350Sstevel@tonic-gate cpu[i]->cpu_flags |= CPU_QUIESCED; 2360Sstevel@tonic-gate CPUSET_DEL(cpu_ready_set, cpu[i]->cpu_id); 2370Sstevel@tonic-gate } 2380Sstevel@tonic-gate } 2390Sstevel@tonic-gate } 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate /* 2420Sstevel@tonic-gate * Platform callback following each entry to panicsys(). If we've panicked at 2430Sstevel@tonic-gate * level 14, we examine t_panic_trap to see if a fatal trap occurred. If so, 2440Sstevel@tonic-gate * we disable further %tick_cmpr interrupts. If not, an explicit call to panic 2450Sstevel@tonic-gate * was made and so we re-enqueue an interrupt request structure to allow 2460Sstevel@tonic-gate * further level 14 interrupts to be processed once we lower PIL. This allows 2470Sstevel@tonic-gate * us to handle panics from the deadman() CY_HIGH_LEVEL cyclic. 2480Sstevel@tonic-gate */ 2490Sstevel@tonic-gate void 2500Sstevel@tonic-gate panic_enter_hw(int spl) 2510Sstevel@tonic-gate { 2520Sstevel@tonic-gate if (spl == ipltospl(PIL_14)) { 2530Sstevel@tonic-gate uint_t opstate = disable_vec_intr(); 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate if (curthread->t_panic_trap != NULL) { 2560Sstevel@tonic-gate tickcmpr_disable(); 2570Sstevel@tonic-gate intr_dequeue_req(PIL_14, cbe_level14_inum); 2580Sstevel@tonic-gate } else { 2590Sstevel@tonic-gate if (!tickcmpr_disabled()) 2600Sstevel@tonic-gate intr_enqueue_req(PIL_14, cbe_level14_inum); 2610Sstevel@tonic-gate /* 2620Sstevel@tonic-gate * Clear SOFTINT<14>, SOFTINT<0> (TICK_INT) 2630Sstevel@tonic-gate * and SOFTINT<16> (STICK_INT) to indicate 2640Sstevel@tonic-gate * that the current level 14 has been serviced. 2650Sstevel@tonic-gate */ 2660Sstevel@tonic-gate wr_clr_softint((1 << PIL_14) | 2670Sstevel@tonic-gate TICK_INT_MASK | STICK_INT_MASK); 2680Sstevel@tonic-gate } 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate enable_vec_intr(opstate); 2710Sstevel@tonic-gate } 2720Sstevel@tonic-gate } 2730Sstevel@tonic-gate 2740Sstevel@tonic-gate /* 2750Sstevel@tonic-gate * Miscellaneous hardware-specific code to execute after panicstr is set 2760Sstevel@tonic-gate * by the panic code: we also print and record PTL1 panic information here. 2770Sstevel@tonic-gate */ 2780Sstevel@tonic-gate /*ARGSUSED*/ 2790Sstevel@tonic-gate void 2800Sstevel@tonic-gate panic_quiesce_hw(panic_data_t *pdp) 2810Sstevel@tonic-gate { 2820Sstevel@tonic-gate extern uint_t getpstate(void); 2830Sstevel@tonic-gate extern void setpstate(uint_t); 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate #ifdef TRAPTRACE 2860Sstevel@tonic-gate /* 2870Sstevel@tonic-gate * Turn off TRAPTRACE and save the current %tick value in panic_tick. 2880Sstevel@tonic-gate */ 2890Sstevel@tonic-gate if (!panic_tick) 2900Sstevel@tonic-gate panic_tick = gettick(); 2910Sstevel@tonic-gate TRAPTRACE_FREEZE; 2920Sstevel@tonic-gate #endif 2930Sstevel@tonic-gate /* 2940Sstevel@tonic-gate * For Platforms that use CPU signatures, we 2950Sstevel@tonic-gate * need to set the signature block to OS, the state to 2960Sstevel@tonic-gate * exiting, and the substate to panic for all the processors. 2970Sstevel@tonic-gate */ 2980Sstevel@tonic-gate CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_PANIC, -1); 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate /* 3010Sstevel@tonic-gate * De-activate ECC functions and disable the watchdog timer now that 3020Sstevel@tonic-gate * we've made it through the critical part of the panic code. 3030Sstevel@tonic-gate */ 3040Sstevel@tonic-gate if (watchdog_enable) 3050Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate /* 3080Sstevel@tonic-gate * Disable further ECC errors from the CPU module and the bus nexus. 3090Sstevel@tonic-gate */ 3100Sstevel@tonic-gate cpu_disable_errors(); 3110Sstevel@tonic-gate (void) bus_func_invoke(BF_TYPE_ERRDIS); 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate /* 3140Sstevel@tonic-gate * Redirect all interrupts to the current CPU. 3150Sstevel@tonic-gate */ 3160Sstevel@tonic-gate intr_redist_all_cpus_shutdown(); 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate /* 3190Sstevel@tonic-gate * This call exists solely to support dumps to network 3200Sstevel@tonic-gate * devices after sync from OBP. 3210Sstevel@tonic-gate * 3220Sstevel@tonic-gate * If we came here via the sync callback, then on some 3230Sstevel@tonic-gate * platforms, interrupts may have arrived while we were 3240Sstevel@tonic-gate * stopped in OBP. OBP will arrange for those interrupts to 3250Sstevel@tonic-gate * be redelivered if you say "go", but not if you invoke a 3260Sstevel@tonic-gate * client callback like 'sync'. For some dump devices 3270Sstevel@tonic-gate * (network swap devices), we need interrupts to be 3280Sstevel@tonic-gate * delivered in order to dump, so we have to call the bus 3290Sstevel@tonic-gate * nexus driver to reset the interrupt state machines. 3300Sstevel@tonic-gate */ 3310Sstevel@tonic-gate (void) bus_func_invoke(BF_TYPE_RESINTR); 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate setpstate(getpstate() | PSTATE_IE); 3340Sstevel@tonic-gate } 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate /* 3370Sstevel@tonic-gate * Platforms that use CPU signatures need to set the signature block to OS and 3380Sstevel@tonic-gate * the state to exiting for all CPUs. PANIC_CONT indicates that we're about to 3390Sstevel@tonic-gate * write the crash dump, which tells the SSP/SMS to begin a timeout routine to 3400Sstevel@tonic-gate * reboot the machine if the dump never completes. 3410Sstevel@tonic-gate */ 3420Sstevel@tonic-gate /*ARGSUSED*/ 3430Sstevel@tonic-gate void 3440Sstevel@tonic-gate panic_dump_hw(int spl) 3450Sstevel@tonic-gate { 3460Sstevel@tonic-gate CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_DUMP, -1); 3470Sstevel@tonic-gate } 3480Sstevel@tonic-gate 3490Sstevel@tonic-gate /* 3500Sstevel@tonic-gate * for ptl1_panic 3510Sstevel@tonic-gate */ 3520Sstevel@tonic-gate void 3530Sstevel@tonic-gate ptl1_init_cpu(struct cpu *cpu) 3540Sstevel@tonic-gate { 3550Sstevel@tonic-gate ptl1_state_t *pstate = &cpu->cpu_m.ptl1_state; 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate /*CONSTCOND*/ 3580Sstevel@tonic-gate if (sizeof (struct cpu) + PTL1_SSIZE > CPU_ALLOC_SIZE) { 3590Sstevel@tonic-gate panic("ptl1_init_cpu: not enough space left for ptl1_panic " 3601009Smathue "stack, sizeof (struct cpu) = %lu", sizeof (struct cpu)); 3610Sstevel@tonic-gate } 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate pstate->ptl1_stktop = (uintptr_t)cpu + CPU_ALLOC_SIZE; 3640Sstevel@tonic-gate cpu_pa[cpu->cpu_id] = va_to_pa(cpu); 3650Sstevel@tonic-gate } 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate void 3680Sstevel@tonic-gate ptl1_panic_handler(ptl1_state_t *pstate) 3690Sstevel@tonic-gate { 3700Sstevel@tonic-gate static const char *ptl1_reasons[] = { 3710Sstevel@tonic-gate #ifdef PTL1_PANIC_DEBUG 3720Sstevel@tonic-gate "trap for debug purpose", /* PTL1_BAD_DEBUG */ 3730Sstevel@tonic-gate #else 3740Sstevel@tonic-gate "unknown trap", /* PTL1_BAD_DEBUG */ 3750Sstevel@tonic-gate #endif 3760Sstevel@tonic-gate "register window trap", /* PTL1_BAD_WTRAP */ 3770Sstevel@tonic-gate "kernel MMU miss", /* PTL1_BAD_KMISS */ 3780Sstevel@tonic-gate "kernel protection fault", /* PTL1_BAD_KPROT_FAULT */ 3790Sstevel@tonic-gate "ISM MMU miss", /* PTL1_BAD_ISM */ 3800Sstevel@tonic-gate "kernel MMU trap", /* PTL1_BAD_MMUTRAP */ 3810Sstevel@tonic-gate "kernel trap handler state", /* PTL1_BAD_TRAP */ 3820Sstevel@tonic-gate "floating point trap", /* PTL1_BAD_FPTRAP */ 3830Sstevel@tonic-gate #ifdef DEBUG 3840Sstevel@tonic-gate "pointer to intr_req", /* PTL1_BAD_INTR_REQ */ 3850Sstevel@tonic-gate #else 3860Sstevel@tonic-gate "unknown trap", /* PTL1_BAD_INTR_REQ */ 3870Sstevel@tonic-gate #endif 3880Sstevel@tonic-gate #ifdef TRAPTRACE 3890Sstevel@tonic-gate "TRACE_PTR state", /* PTL1_BAD_TRACE_PTR */ 3900Sstevel@tonic-gate #else 3910Sstevel@tonic-gate "unknown trap", /* PTL1_BAD_TRACE_PTR */ 3920Sstevel@tonic-gate #endif 3930Sstevel@tonic-gate "stack overflow", /* PTL1_BAD_STACK */ 3940Sstevel@tonic-gate "DTrace flags", /* PTL1_BAD_DTRACE_FLAGS */ 3950Sstevel@tonic-gate "attempt to steal locked ctx", /* PTL1_BAD_CTX_STEAL */ 3960Sstevel@tonic-gate "CPU ECC error loop", /* PTL1_BAD_ECC */ 3971270Sbs21162 "non-kernel context in sys/priv_trap() below or", 3981270Sbs21162 /* PTL1_BAD_CTX */ 3990Sstevel@tonic-gate }; 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate uint_t reason = pstate->ptl1_regs.ptl1_g1; 4020Sstevel@tonic-gate uint_t tl = pstate->ptl1_regs.ptl1_trap_regs[0].ptl1_tl; 4030Sstevel@tonic-gate struct trap_info ti = { 0 }; 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate /* 4060Sstevel@tonic-gate * Use trap_info for a place holder to call panic_savetrap() and 4070Sstevel@tonic-gate * panic_showtrap() to save and print out ptl1_panic information. 4080Sstevel@tonic-gate */ 4090Sstevel@tonic-gate if (curthread->t_panic_trap == NULL) 4100Sstevel@tonic-gate curthread->t_panic_trap = &ti; 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate if (reason < sizeof (ptl1_reasons) / sizeof (ptl1_reasons[0])) 4130Sstevel@tonic-gate panic("bad %s at TL %u", ptl1_reasons[reason], tl); 4140Sstevel@tonic-gate else 4150Sstevel@tonic-gate panic("ptl1_panic reason 0x%x at TL %u", reason, tl); 4160Sstevel@tonic-gate } 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate void 4190Sstevel@tonic-gate clear_watchdog_on_exit() 4200Sstevel@tonic-gate { 4210Sstevel@tonic-gate /* 4220Sstevel@tonic-gate * Only shut down an active hardware watchdog timer if the platform 4230Sstevel@tonic-gate * has expressed an interest to. 4240Sstevel@tonic-gate */ 4250Sstevel@tonic-gate if (disable_watchdog_on_exit && watchdog_activated) { 4260Sstevel@tonic-gate prom_printf("Debugging requested; hardware watchdog " 4270Sstevel@tonic-gate "disabled; reboot to re-enable.\n"); 4280Sstevel@tonic-gate cmn_err(CE_WARN, "!Debugging requested; hardware watchdog " 4290Sstevel@tonic-gate "disabled; reboot to re-enable."); 4300Sstevel@tonic-gate mutex_enter(&tod_lock); 4310Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 4320Sstevel@tonic-gate mutex_exit(&tod_lock); 4330Sstevel@tonic-gate } 4340Sstevel@tonic-gate } 4350Sstevel@tonic-gate 436*2036Swentaoy /* 437*2036Swentaoy * This null routine is only used by sun4v watchdog timer support. 438*2036Swentaoy */ 439*2036Swentaoy void 440*2036Swentaoy restore_watchdog_on_entry(void) 441*2036Swentaoy { 442*2036Swentaoy } 443*2036Swentaoy 4440Sstevel@tonic-gate int 4450Sstevel@tonic-gate kdi_watchdog_disable(void) 4460Sstevel@tonic-gate { 4470Sstevel@tonic-gate if (watchdog_activated) { 4480Sstevel@tonic-gate mutex_enter(&tod_lock); 4490Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 4500Sstevel@tonic-gate mutex_exit(&tod_lock); 4510Sstevel@tonic-gate } 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate return (watchdog_activated); 4540Sstevel@tonic-gate } 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate void 4570Sstevel@tonic-gate kdi_watchdog_restore(void) 4580Sstevel@tonic-gate { 4590Sstevel@tonic-gate if (watchdog_enable) { 4600Sstevel@tonic-gate mutex_enter(&tod_lock); 4610Sstevel@tonic-gate (void) tod_ops.tod_set_watchdog_timer(watchdog_timeout_seconds); 4620Sstevel@tonic-gate mutex_exit(&tod_lock); 4630Sstevel@tonic-gate } 4640Sstevel@tonic-gate } 4650Sstevel@tonic-gate 466*2036Swentaoy /* 467*2036Swentaoy * This null routine is only used by sun4v watchdog timer support. 468*2036Swentaoy */ 469*2036Swentaoy void 470*2036Swentaoy watchdog_init(void) 471*2036Swentaoy { 472*2036Swentaoy } 473*2036Swentaoy 474*2036Swentaoy /* 475*2036Swentaoy * This null routine is only used by sun4v watchdog timer support. 476*2036Swentaoy */ 477*2036Swentaoy void 478*2036Swentaoy watchdog_pat(void) 479*2036Swentaoy { 480*2036Swentaoy } 481*2036Swentaoy 482*2036Swentaoy /* 483*2036Swentaoy * This null routine is only used by sun4v watchdog timer support. 484*2036Swentaoy */ 485*2036Swentaoy void 486*2036Swentaoy watchdog_suspend(void) 487*2036Swentaoy { 488*2036Swentaoy } 489*2036Swentaoy 490*2036Swentaoy /* 491*2036Swentaoy * This null routine is only used by sun4v watchdog timer support. 492*2036Swentaoy */ 493*2036Swentaoy void 494*2036Swentaoy watchdog_resume(void) 495*2036Swentaoy { 496*2036Swentaoy } 497*2036Swentaoy 498*2036Swentaoy /* 499*2036Swentaoy * This null routine is only used by sun4v watchdog timer support. 500*2036Swentaoy */ 501*2036Swentaoy void 502*2036Swentaoy watchdog_clear(void) 503*2036Swentaoy { 504*2036Swentaoy } 505*2036Swentaoy 5060Sstevel@tonic-gate /*ARGSUSED*/ 5070Sstevel@tonic-gate void 5080Sstevel@tonic-gate mach_dump_buffer_init(void) 5090Sstevel@tonic-gate { 5100Sstevel@tonic-gate /* 5110Sstevel@tonic-gate * setup dump buffer to store extra crash information 5120Sstevel@tonic-gate * not applicable to sun4u 5130Sstevel@tonic-gate */ 5140Sstevel@tonic-gate } 5150Sstevel@tonic-gate 5160Sstevel@tonic-gate /* 5170Sstevel@tonic-gate * xt_sync - wait for previous x-traps to finish 5180Sstevel@tonic-gate */ 5190Sstevel@tonic-gate void 5200Sstevel@tonic-gate xt_sync(cpuset_t cpuset) 5210Sstevel@tonic-gate { 5220Sstevel@tonic-gate kpreempt_disable(); 5230Sstevel@tonic-gate CPUSET_DEL(cpuset, CPU->cpu_id); 5240Sstevel@tonic-gate CPUSET_AND(cpuset, cpu_ready_set); 5250Sstevel@tonic-gate xt_some(cpuset, (xcfunc_t *)xt_sync_tl1, 0, 0); 5260Sstevel@tonic-gate kpreempt_enable(); 5270Sstevel@tonic-gate } 528