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 52036Swentaoy * Common Development and Distribution License (the "License"). 62036Swentaoy * 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 *); 522036Swentaoy 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 */ 107*3253Smec page_retire_mdboot(); 108917Selowe 109917Selowe /* 1100Sstevel@tonic-gate * stop other cpus which also raise our priority. since there is only 1110Sstevel@tonic-gate * one active cpu after this, and our priority will be too high 1120Sstevel@tonic-gate * for us to be preempted, we're essentially single threaded 1130Sstevel@tonic-gate * from here on out. 1140Sstevel@tonic-gate */ 1150Sstevel@tonic-gate stop_other_cpus(); 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate /* 1180Sstevel@tonic-gate * try and reset leaf devices. reset_leaves() should only 1190Sstevel@tonic-gate * be called when there are no other threads that could be 1200Sstevel@tonic-gate * accessing devices 1210Sstevel@tonic-gate */ 1220Sstevel@tonic-gate reset_leaves(); 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate if (fcn == AD_HALT) { 1250Sstevel@tonic-gate halt((char *)NULL); 1260Sstevel@tonic-gate } else if (fcn == AD_POWEROFF) { 1270Sstevel@tonic-gate power_down(NULL); 1280Sstevel@tonic-gate } else { 1290Sstevel@tonic-gate if (bootstr == NULL) { 1300Sstevel@tonic-gate switch (fcn) { 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate case AD_BOOT: 1330Sstevel@tonic-gate bootstr = ""; 1340Sstevel@tonic-gate break; 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate case AD_IBOOT: 1370Sstevel@tonic-gate bootstr = "-a"; 1380Sstevel@tonic-gate break; 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate case AD_SBOOT: 1410Sstevel@tonic-gate bootstr = "-s"; 1420Sstevel@tonic-gate break; 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate case AD_SIBOOT: 1450Sstevel@tonic-gate bootstr = "-sa"; 1460Sstevel@tonic-gate break; 1470Sstevel@tonic-gate default: 1480Sstevel@tonic-gate cmn_err(CE_WARN, 1490Sstevel@tonic-gate "mdboot: invalid function %d", fcn); 1500Sstevel@tonic-gate bootstr = ""; 1510Sstevel@tonic-gate break; 1520Sstevel@tonic-gate } 1530Sstevel@tonic-gate } 1540Sstevel@tonic-gate reboot_machine(bootstr); 1550Sstevel@tonic-gate } 1560Sstevel@tonic-gate /* MAYBE REACHED */ 1570Sstevel@tonic-gate } 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate /* mdpreboot - may be called prior to mdboot while root fs still mounted */ 1600Sstevel@tonic-gate /*ARGSUSED*/ 1610Sstevel@tonic-gate void 1620Sstevel@tonic-gate mdpreboot(int cmd, int fcn, char *bootstr) 1630Sstevel@tonic-gate { 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate /* 1670Sstevel@tonic-gate * Halt the machine and then reboot with the device 1680Sstevel@tonic-gate * and arguments specified in bootstr. 1690Sstevel@tonic-gate */ 1700Sstevel@tonic-gate static void 1710Sstevel@tonic-gate reboot_machine(char *bootstr) 1720Sstevel@tonic-gate { 1730Sstevel@tonic-gate flush_windows(); 1740Sstevel@tonic-gate stop_other_cpus(); /* send stop signal to other CPUs */ 1750Sstevel@tonic-gate prom_printf("rebooting...\n"); 1760Sstevel@tonic-gate /* 1770Sstevel@tonic-gate * For platforms that use CPU signatures, we 1780Sstevel@tonic-gate * need to set the signature block to OS and 1790Sstevel@tonic-gate * the state to exiting for all the processors. 1800Sstevel@tonic-gate */ 1810Sstevel@tonic-gate CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_REBOOT, -1); 1820Sstevel@tonic-gate prom_reboot(bootstr); 1830Sstevel@tonic-gate /*NOTREACHED*/ 1840Sstevel@tonic-gate } 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate /* 1870Sstevel@tonic-gate * We use the x-trap mechanism and idle_stop_xcall() to stop the other CPUs. 1880Sstevel@tonic-gate * Once in panic_idle() they raise spl, record their location, and spin. 1890Sstevel@tonic-gate */ 1900Sstevel@tonic-gate static void 1910Sstevel@tonic-gate panic_idle(void) 1920Sstevel@tonic-gate { 1930Sstevel@tonic-gate cpu_async_panic_callb(); /* check for async errors */ 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate (void) spl7(); 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate debug_flush_windows(); 1980Sstevel@tonic-gate (void) setjmp(&curthread->t_pcb); 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate CPU->cpu_m.in_prom = 1; 2010Sstevel@tonic-gate membar_stld(); 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate for (;;); 2040Sstevel@tonic-gate } 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate /* 2070Sstevel@tonic-gate * Force the other CPUs to trap into panic_idle(), and then remove them 2080Sstevel@tonic-gate * from the cpu_ready_set so they will no longer receive cross-calls. 2090Sstevel@tonic-gate */ 2100Sstevel@tonic-gate /*ARGSUSED*/ 2110Sstevel@tonic-gate void 2120Sstevel@tonic-gate panic_stopcpus(cpu_t *cp, kthread_t *t, int spl) 2130Sstevel@tonic-gate { 2140Sstevel@tonic-gate cpuset_t cps; 2150Sstevel@tonic-gate int i; 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate (void) splzs(); 2180Sstevel@tonic-gate CPUSET_ALL_BUT(cps, cp->cpu_id); 2190Sstevel@tonic-gate xt_some(cps, (xcfunc_t *)idle_stop_xcall, (uint64_t)&panic_idle, NULL); 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate for (i = 0; i < NCPU; i++) { 2220Sstevel@tonic-gate if (i != cp->cpu_id && CPU_XCALL_READY(i)) { 2230Sstevel@tonic-gate int ntries = 0x10000; 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate while (!cpu[i]->cpu_m.in_prom && ntries) { 2260Sstevel@tonic-gate DELAY(50); 2270Sstevel@tonic-gate ntries--; 2280Sstevel@tonic-gate } 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate if (!cpu[i]->cpu_m.in_prom) 2310Sstevel@tonic-gate printf("panic: failed to stop cpu%d\n", i); 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate cpu[i]->cpu_flags &= ~CPU_READY; 2340Sstevel@tonic-gate cpu[i]->cpu_flags |= CPU_QUIESCED; 2350Sstevel@tonic-gate CPUSET_DEL(cpu_ready_set, cpu[i]->cpu_id); 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate } 2380Sstevel@tonic-gate } 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate /* 2410Sstevel@tonic-gate * Platform callback following each entry to panicsys(). If we've panicked at 2420Sstevel@tonic-gate * level 14, we examine t_panic_trap to see if a fatal trap occurred. If so, 2430Sstevel@tonic-gate * we disable further %tick_cmpr interrupts. If not, an explicit call to panic 2440Sstevel@tonic-gate * was made and so we re-enqueue an interrupt request structure to allow 2450Sstevel@tonic-gate * further level 14 interrupts to be processed once we lower PIL. This allows 2460Sstevel@tonic-gate * us to handle panics from the deadman() CY_HIGH_LEVEL cyclic. 2470Sstevel@tonic-gate */ 2480Sstevel@tonic-gate void 2490Sstevel@tonic-gate panic_enter_hw(int spl) 2500Sstevel@tonic-gate { 2510Sstevel@tonic-gate if (spl == ipltospl(PIL_14)) { 2520Sstevel@tonic-gate uint_t opstate = disable_vec_intr(); 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate if (curthread->t_panic_trap != NULL) { 2550Sstevel@tonic-gate tickcmpr_disable(); 2560Sstevel@tonic-gate intr_dequeue_req(PIL_14, cbe_level14_inum); 2570Sstevel@tonic-gate } else { 2580Sstevel@tonic-gate if (!tickcmpr_disabled()) 2590Sstevel@tonic-gate intr_enqueue_req(PIL_14, cbe_level14_inum); 2600Sstevel@tonic-gate /* 2610Sstevel@tonic-gate * Clear SOFTINT<14>, SOFTINT<0> (TICK_INT) 2620Sstevel@tonic-gate * and SOFTINT<16> (STICK_INT) to indicate 2630Sstevel@tonic-gate * that the current level 14 has been serviced. 2640Sstevel@tonic-gate */ 2650Sstevel@tonic-gate wr_clr_softint((1 << PIL_14) | 2660Sstevel@tonic-gate TICK_INT_MASK | STICK_INT_MASK); 2670Sstevel@tonic-gate } 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate enable_vec_intr(opstate); 2700Sstevel@tonic-gate } 2710Sstevel@tonic-gate } 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate /* 2740Sstevel@tonic-gate * Miscellaneous hardware-specific code to execute after panicstr is set 2750Sstevel@tonic-gate * by the panic code: we also print and record PTL1 panic information here. 2760Sstevel@tonic-gate */ 2770Sstevel@tonic-gate /*ARGSUSED*/ 2780Sstevel@tonic-gate void 2790Sstevel@tonic-gate panic_quiesce_hw(panic_data_t *pdp) 2800Sstevel@tonic-gate { 2810Sstevel@tonic-gate extern uint_t getpstate(void); 2820Sstevel@tonic-gate extern void setpstate(uint_t); 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate #ifdef TRAPTRACE 2850Sstevel@tonic-gate /* 2860Sstevel@tonic-gate * Turn off TRAPTRACE and save the current %tick value in panic_tick. 2870Sstevel@tonic-gate */ 2880Sstevel@tonic-gate if (!panic_tick) 2890Sstevel@tonic-gate panic_tick = gettick(); 2900Sstevel@tonic-gate TRAPTRACE_FREEZE; 2910Sstevel@tonic-gate #endif 2920Sstevel@tonic-gate /* 2930Sstevel@tonic-gate * For Platforms that use CPU signatures, we 2940Sstevel@tonic-gate * need to set the signature block to OS, the state to 2950Sstevel@tonic-gate * exiting, and the substate to panic for all the processors. 2960Sstevel@tonic-gate */ 2970Sstevel@tonic-gate CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_PANIC, -1); 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate /* 3000Sstevel@tonic-gate * De-activate ECC functions and disable the watchdog timer now that 3010Sstevel@tonic-gate * we've made it through the critical part of the panic code. 3020Sstevel@tonic-gate */ 3030Sstevel@tonic-gate if (watchdog_enable) 3040Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 3050Sstevel@tonic-gate 3060Sstevel@tonic-gate /* 3070Sstevel@tonic-gate * Disable further ECC errors from the CPU module and the bus nexus. 3080Sstevel@tonic-gate */ 3090Sstevel@tonic-gate cpu_disable_errors(); 3100Sstevel@tonic-gate (void) bus_func_invoke(BF_TYPE_ERRDIS); 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate /* 3130Sstevel@tonic-gate * Redirect all interrupts to the current CPU. 3140Sstevel@tonic-gate */ 3150Sstevel@tonic-gate intr_redist_all_cpus_shutdown(); 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate /* 3180Sstevel@tonic-gate * This call exists solely to support dumps to network 3190Sstevel@tonic-gate * devices after sync from OBP. 3200Sstevel@tonic-gate * 3210Sstevel@tonic-gate * If we came here via the sync callback, then on some 3220Sstevel@tonic-gate * platforms, interrupts may have arrived while we were 3230Sstevel@tonic-gate * stopped in OBP. OBP will arrange for those interrupts to 3240Sstevel@tonic-gate * be redelivered if you say "go", but not if you invoke a 3250Sstevel@tonic-gate * client callback like 'sync'. For some dump devices 3260Sstevel@tonic-gate * (network swap devices), we need interrupts to be 3270Sstevel@tonic-gate * delivered in order to dump, so we have to call the bus 3280Sstevel@tonic-gate * nexus driver to reset the interrupt state machines. 3290Sstevel@tonic-gate */ 3300Sstevel@tonic-gate (void) bus_func_invoke(BF_TYPE_RESINTR); 3310Sstevel@tonic-gate 3320Sstevel@tonic-gate setpstate(getpstate() | PSTATE_IE); 3330Sstevel@tonic-gate } 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate /* 3360Sstevel@tonic-gate * Platforms that use CPU signatures need to set the signature block to OS and 3370Sstevel@tonic-gate * the state to exiting for all CPUs. PANIC_CONT indicates that we're about to 3380Sstevel@tonic-gate * write the crash dump, which tells the SSP/SMS to begin a timeout routine to 3390Sstevel@tonic-gate * reboot the machine if the dump never completes. 3400Sstevel@tonic-gate */ 3410Sstevel@tonic-gate /*ARGSUSED*/ 3420Sstevel@tonic-gate void 3430Sstevel@tonic-gate panic_dump_hw(int spl) 3440Sstevel@tonic-gate { 3450Sstevel@tonic-gate CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_DUMP, -1); 3460Sstevel@tonic-gate } 3470Sstevel@tonic-gate 3480Sstevel@tonic-gate /* 3490Sstevel@tonic-gate * for ptl1_panic 3500Sstevel@tonic-gate */ 3510Sstevel@tonic-gate void 3520Sstevel@tonic-gate ptl1_init_cpu(struct cpu *cpu) 3530Sstevel@tonic-gate { 3540Sstevel@tonic-gate ptl1_state_t *pstate = &cpu->cpu_m.ptl1_state; 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate /*CONSTCOND*/ 3570Sstevel@tonic-gate if (sizeof (struct cpu) + PTL1_SSIZE > CPU_ALLOC_SIZE) { 3580Sstevel@tonic-gate panic("ptl1_init_cpu: not enough space left for ptl1_panic " 3591009Smathue "stack, sizeof (struct cpu) = %lu", sizeof (struct cpu)); 3600Sstevel@tonic-gate } 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate pstate->ptl1_stktop = (uintptr_t)cpu + CPU_ALLOC_SIZE; 3630Sstevel@tonic-gate cpu_pa[cpu->cpu_id] = va_to_pa(cpu); 3640Sstevel@tonic-gate } 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate void 3670Sstevel@tonic-gate ptl1_panic_handler(ptl1_state_t *pstate) 3680Sstevel@tonic-gate { 3690Sstevel@tonic-gate static const char *ptl1_reasons[] = { 3700Sstevel@tonic-gate #ifdef PTL1_PANIC_DEBUG 3710Sstevel@tonic-gate "trap for debug purpose", /* PTL1_BAD_DEBUG */ 3720Sstevel@tonic-gate #else 3730Sstevel@tonic-gate "unknown trap", /* PTL1_BAD_DEBUG */ 3740Sstevel@tonic-gate #endif 3750Sstevel@tonic-gate "register window trap", /* PTL1_BAD_WTRAP */ 3760Sstevel@tonic-gate "kernel MMU miss", /* PTL1_BAD_KMISS */ 3770Sstevel@tonic-gate "kernel protection fault", /* PTL1_BAD_KPROT_FAULT */ 3780Sstevel@tonic-gate "ISM MMU miss", /* PTL1_BAD_ISM */ 3790Sstevel@tonic-gate "kernel MMU trap", /* PTL1_BAD_MMUTRAP */ 3800Sstevel@tonic-gate "kernel trap handler state", /* PTL1_BAD_TRAP */ 3810Sstevel@tonic-gate "floating point trap", /* PTL1_BAD_FPTRAP */ 3820Sstevel@tonic-gate #ifdef DEBUG 3832973Sgovinda "pointer to intr_vec", /* PTL1_BAD_INTR_VEC */ 3840Sstevel@tonic-gate #else 3852973Sgovinda "unknown trap", /* PTL1_BAD_INTR_VEC */ 3860Sstevel@tonic-gate #endif 3870Sstevel@tonic-gate #ifdef TRAPTRACE 3880Sstevel@tonic-gate "TRACE_PTR state", /* PTL1_BAD_TRACE_PTR */ 3890Sstevel@tonic-gate #else 3900Sstevel@tonic-gate "unknown trap", /* PTL1_BAD_TRACE_PTR */ 3910Sstevel@tonic-gate #endif 3920Sstevel@tonic-gate "stack overflow", /* PTL1_BAD_STACK */ 3930Sstevel@tonic-gate "DTrace flags", /* PTL1_BAD_DTRACE_FLAGS */ 3940Sstevel@tonic-gate "attempt to steal locked ctx", /* PTL1_BAD_CTX_STEAL */ 3950Sstevel@tonic-gate "CPU ECC error loop", /* PTL1_BAD_ECC */ 3961270Sbs21162 "non-kernel context in sys/priv_trap() below or", 3971270Sbs21162 /* PTL1_BAD_CTX */ 3980Sstevel@tonic-gate }; 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate uint_t reason = pstate->ptl1_regs.ptl1_g1; 4010Sstevel@tonic-gate uint_t tl = pstate->ptl1_regs.ptl1_trap_regs[0].ptl1_tl; 4020Sstevel@tonic-gate struct trap_info ti = { 0 }; 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate /* 4050Sstevel@tonic-gate * Use trap_info for a place holder to call panic_savetrap() and 4060Sstevel@tonic-gate * panic_showtrap() to save and print out ptl1_panic information. 4070Sstevel@tonic-gate */ 4080Sstevel@tonic-gate if (curthread->t_panic_trap == NULL) 4090Sstevel@tonic-gate curthread->t_panic_trap = &ti; 4100Sstevel@tonic-gate 4110Sstevel@tonic-gate if (reason < sizeof (ptl1_reasons) / sizeof (ptl1_reasons[0])) 4120Sstevel@tonic-gate panic("bad %s at TL %u", ptl1_reasons[reason], tl); 4130Sstevel@tonic-gate else 4140Sstevel@tonic-gate panic("ptl1_panic reason 0x%x at TL %u", reason, tl); 4150Sstevel@tonic-gate } 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate void 4180Sstevel@tonic-gate clear_watchdog_on_exit() 4190Sstevel@tonic-gate { 4200Sstevel@tonic-gate /* 4210Sstevel@tonic-gate * Only shut down an active hardware watchdog timer if the platform 4220Sstevel@tonic-gate * has expressed an interest to. 4230Sstevel@tonic-gate */ 4240Sstevel@tonic-gate if (disable_watchdog_on_exit && watchdog_activated) { 4250Sstevel@tonic-gate prom_printf("Debugging requested; hardware watchdog " 4260Sstevel@tonic-gate "disabled; reboot to re-enable.\n"); 4270Sstevel@tonic-gate cmn_err(CE_WARN, "!Debugging requested; hardware watchdog " 4280Sstevel@tonic-gate "disabled; reboot to re-enable."); 4290Sstevel@tonic-gate mutex_enter(&tod_lock); 4300Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 4310Sstevel@tonic-gate mutex_exit(&tod_lock); 4320Sstevel@tonic-gate } 4330Sstevel@tonic-gate } 4340Sstevel@tonic-gate 4352036Swentaoy /* 4362036Swentaoy * This null routine is only used by sun4v watchdog timer support. 4372036Swentaoy */ 4382036Swentaoy void 4392036Swentaoy restore_watchdog_on_entry(void) 4402036Swentaoy { 4412036Swentaoy } 4422036Swentaoy 4430Sstevel@tonic-gate int 4440Sstevel@tonic-gate kdi_watchdog_disable(void) 4450Sstevel@tonic-gate { 4460Sstevel@tonic-gate if (watchdog_activated) { 4470Sstevel@tonic-gate mutex_enter(&tod_lock); 4480Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 4490Sstevel@tonic-gate mutex_exit(&tod_lock); 4500Sstevel@tonic-gate } 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate return (watchdog_activated); 4530Sstevel@tonic-gate } 4540Sstevel@tonic-gate 4550Sstevel@tonic-gate void 4560Sstevel@tonic-gate kdi_watchdog_restore(void) 4570Sstevel@tonic-gate { 4580Sstevel@tonic-gate if (watchdog_enable) { 4590Sstevel@tonic-gate mutex_enter(&tod_lock); 4600Sstevel@tonic-gate (void) tod_ops.tod_set_watchdog_timer(watchdog_timeout_seconds); 4610Sstevel@tonic-gate mutex_exit(&tod_lock); 4620Sstevel@tonic-gate } 4630Sstevel@tonic-gate } 4640Sstevel@tonic-gate 4652036Swentaoy /* 4662036Swentaoy * This null routine is only used by sun4v watchdog timer support. 4672036Swentaoy */ 4682036Swentaoy void 4692036Swentaoy watchdog_init(void) 4702036Swentaoy { 4712036Swentaoy } 4722036Swentaoy 4732036Swentaoy /* 4742036Swentaoy * This null routine is only used by sun4v watchdog timer support. 4752036Swentaoy */ 4762036Swentaoy void 4772036Swentaoy watchdog_pat(void) 4782036Swentaoy { 4792036Swentaoy } 4802036Swentaoy 4812036Swentaoy /* 4822036Swentaoy * This null routine is only used by sun4v watchdog timer support. 4832036Swentaoy */ 4842036Swentaoy void 4852036Swentaoy watchdog_suspend(void) 4862036Swentaoy { 4872036Swentaoy } 4882036Swentaoy 4892036Swentaoy /* 4902036Swentaoy * This null routine is only used by sun4v watchdog timer support. 4912036Swentaoy */ 4922036Swentaoy void 4932036Swentaoy watchdog_resume(void) 4942036Swentaoy { 4952036Swentaoy } 4962036Swentaoy 4972036Swentaoy /* 4982036Swentaoy * This null routine is only used by sun4v watchdog timer support. 4992036Swentaoy */ 5002036Swentaoy void 5012036Swentaoy watchdog_clear(void) 5022036Swentaoy { 5032036Swentaoy } 5042036Swentaoy 5050Sstevel@tonic-gate /*ARGSUSED*/ 5060Sstevel@tonic-gate void 5070Sstevel@tonic-gate mach_dump_buffer_init(void) 5080Sstevel@tonic-gate { 5090Sstevel@tonic-gate /* 5100Sstevel@tonic-gate * setup dump buffer to store extra crash information 5110Sstevel@tonic-gate * not applicable to sun4u 5120Sstevel@tonic-gate */ 5130Sstevel@tonic-gate } 5140Sstevel@tonic-gate 5150Sstevel@tonic-gate /* 5160Sstevel@tonic-gate * xt_sync - wait for previous x-traps to finish 5170Sstevel@tonic-gate */ 5180Sstevel@tonic-gate void 5190Sstevel@tonic-gate xt_sync(cpuset_t cpuset) 5200Sstevel@tonic-gate { 5210Sstevel@tonic-gate kpreempt_disable(); 5220Sstevel@tonic-gate CPUSET_DEL(cpuset, CPU->cpu_id); 5230Sstevel@tonic-gate CPUSET_AND(cpuset, cpu_ready_set); 5240Sstevel@tonic-gate xt_some(cpuset, (xcfunc_t *)xt_sync_tl1, 0, 0); 5250Sstevel@tonic-gate kpreempt_enable(); 5260Sstevel@tonic-gate } 527