1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/t_lock.h> 31*0Sstevel@tonic-gate #include <sys/uadmin.h> 32*0Sstevel@tonic-gate #include <sys/panic.h> 33*0Sstevel@tonic-gate #include <sys/reboot.h> 34*0Sstevel@tonic-gate #include <sys/autoconf.h> 35*0Sstevel@tonic-gate #include <sys/machsystm.h> 36*0Sstevel@tonic-gate #include <sys/promif.h> 37*0Sstevel@tonic-gate #include <sys/membar.h> 38*0Sstevel@tonic-gate #include <vm/hat_sfmmu.h> 39*0Sstevel@tonic-gate #include <sys/cpu_module.h> 40*0Sstevel@tonic-gate #include <sys/cpu_sgnblk_defs.h> 41*0Sstevel@tonic-gate #include <sys/intreg.h> 42*0Sstevel@tonic-gate #include <sys/consdev.h> 43*0Sstevel@tonic-gate #include <sys/kdi_impl.h> 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate #ifdef TRAPTRACE 46*0Sstevel@tonic-gate #include <sys/traptrace.h> 47*0Sstevel@tonic-gate u_longlong_t panic_tick; 48*0Sstevel@tonic-gate #endif /* TRAPTRACE */ 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate extern u_longlong_t gettick(); 51*0Sstevel@tonic-gate static void reboot_machine(char *); 52*0Sstevel@tonic-gate extern int disable_watchdog_on_exit; 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate /* 55*0Sstevel@tonic-gate * Machine dependent code to reboot. 56*0Sstevel@tonic-gate * "mdep" is interpreted as a character pointer; if non-null, it is a pointer 57*0Sstevel@tonic-gate * to a string to be used as the argument string when rebooting. 58*0Sstevel@tonic-gate */ 59*0Sstevel@tonic-gate /*ARGSUSED*/ 60*0Sstevel@tonic-gate void 61*0Sstevel@tonic-gate mdboot(int cmd, int fcn, char *bootstr) 62*0Sstevel@tonic-gate { 63*0Sstevel@tonic-gate page_t *first, *pp; 64*0Sstevel@tonic-gate extern void pm_cfb_check_and_powerup(void); 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate /* 67*0Sstevel@tonic-gate * Disable the hw watchdog timer. 68*0Sstevel@tonic-gate */ 69*0Sstevel@tonic-gate if (disable_watchdog_on_exit && watchdog_activated) { 70*0Sstevel@tonic-gate mutex_enter(&tod_lock); 71*0Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 72*0Sstevel@tonic-gate mutex_exit(&tod_lock); 73*0Sstevel@tonic-gate } 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate /* 76*0Sstevel@tonic-gate * Clear any unresolved UEs from memory. We rely on the fact that on 77*0Sstevel@tonic-gate * sun4u, pagezero() will always clear UEs. Since we're rebooting, we 78*0Sstevel@tonic-gate * just force p_selock to appear locked so pagezero()'s assert works. 79*0Sstevel@tonic-gate * 80*0Sstevel@tonic-gate * Pages that were retired successfully due to multiple CEs will 81*0Sstevel@tonic-gate * also be cleared. 82*0Sstevel@tonic-gate */ 83*0Sstevel@tonic-gate if (memsegs != NULL) { 84*0Sstevel@tonic-gate pp = first = page_first(); 85*0Sstevel@tonic-gate do { 86*0Sstevel@tonic-gate if (page_isretired(pp) || page_istoxic(pp)) { 87*0Sstevel@tonic-gate /* pagezero asserts PAGE_LOCKED */ 88*0Sstevel@tonic-gate pp->p_selock = -1; 89*0Sstevel@tonic-gate pagezero(pp, 0, PAGESIZE); 90*0Sstevel@tonic-gate } 91*0Sstevel@tonic-gate } while ((pp = page_next(pp)) != first); 92*0Sstevel@tonic-gate } 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate /* 95*0Sstevel@tonic-gate * XXX - rconsvp is set to NULL to ensure that output messages 96*0Sstevel@tonic-gate * are sent to the underlying "hardware" device using the 97*0Sstevel@tonic-gate * monitor's printf routine since we are in the process of 98*0Sstevel@tonic-gate * either rebooting or halting the machine. 99*0Sstevel@tonic-gate */ 100*0Sstevel@tonic-gate rconsvp = NULL; 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate /* 103*0Sstevel@tonic-gate * At a high interrupt level we can't: 104*0Sstevel@tonic-gate * 1) bring up the console 105*0Sstevel@tonic-gate * or 106*0Sstevel@tonic-gate * 2) wait for pending interrupts prior to redistribution 107*0Sstevel@tonic-gate * to the current CPU 108*0Sstevel@tonic-gate * 109*0Sstevel@tonic-gate * so we do them now. 110*0Sstevel@tonic-gate */ 111*0Sstevel@tonic-gate pm_cfb_check_and_powerup(); 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate /* make sure there are no more changes to the device tree */ 114*0Sstevel@tonic-gate devtree_freeze(); 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate /* 117*0Sstevel@tonic-gate * stop other cpus which also raise our priority. since there is only 118*0Sstevel@tonic-gate * one active cpu after this, and our priority will be too high 119*0Sstevel@tonic-gate * for us to be preempted, we're essentially single threaded 120*0Sstevel@tonic-gate * from here on out. 121*0Sstevel@tonic-gate */ 122*0Sstevel@tonic-gate stop_other_cpus(); 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate /* 125*0Sstevel@tonic-gate * try and reset leaf devices. reset_leaves() should only 126*0Sstevel@tonic-gate * be called when there are no other threads that could be 127*0Sstevel@tonic-gate * accessing devices 128*0Sstevel@tonic-gate */ 129*0Sstevel@tonic-gate reset_leaves(); 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate if (fcn == AD_HALT) { 132*0Sstevel@tonic-gate halt((char *)NULL); 133*0Sstevel@tonic-gate } else if (fcn == AD_POWEROFF) { 134*0Sstevel@tonic-gate power_down(NULL); 135*0Sstevel@tonic-gate } else { 136*0Sstevel@tonic-gate if (bootstr == NULL) { 137*0Sstevel@tonic-gate switch (fcn) { 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate case AD_BOOT: 140*0Sstevel@tonic-gate bootstr = ""; 141*0Sstevel@tonic-gate break; 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate case AD_IBOOT: 144*0Sstevel@tonic-gate bootstr = "-a"; 145*0Sstevel@tonic-gate break; 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate case AD_SBOOT: 148*0Sstevel@tonic-gate bootstr = "-s"; 149*0Sstevel@tonic-gate break; 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate case AD_SIBOOT: 152*0Sstevel@tonic-gate bootstr = "-sa"; 153*0Sstevel@tonic-gate break; 154*0Sstevel@tonic-gate default: 155*0Sstevel@tonic-gate cmn_err(CE_WARN, 156*0Sstevel@tonic-gate "mdboot: invalid function %d", fcn); 157*0Sstevel@tonic-gate bootstr = ""; 158*0Sstevel@tonic-gate break; 159*0Sstevel@tonic-gate } 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate reboot_machine(bootstr); 162*0Sstevel@tonic-gate } 163*0Sstevel@tonic-gate /* MAYBE REACHED */ 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate /* mdpreboot - may be called prior to mdboot while root fs still mounted */ 167*0Sstevel@tonic-gate /*ARGSUSED*/ 168*0Sstevel@tonic-gate void 169*0Sstevel@tonic-gate mdpreboot(int cmd, int fcn, char *bootstr) 170*0Sstevel@tonic-gate { 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate /* 174*0Sstevel@tonic-gate * Halt the machine and then reboot with the device 175*0Sstevel@tonic-gate * and arguments specified in bootstr. 176*0Sstevel@tonic-gate */ 177*0Sstevel@tonic-gate static void 178*0Sstevel@tonic-gate reboot_machine(char *bootstr) 179*0Sstevel@tonic-gate { 180*0Sstevel@tonic-gate flush_windows(); 181*0Sstevel@tonic-gate stop_other_cpus(); /* send stop signal to other CPUs */ 182*0Sstevel@tonic-gate prom_printf("rebooting...\n"); 183*0Sstevel@tonic-gate /* 184*0Sstevel@tonic-gate * For platforms that use CPU signatures, we 185*0Sstevel@tonic-gate * need to set the signature block to OS and 186*0Sstevel@tonic-gate * the state to exiting for all the processors. 187*0Sstevel@tonic-gate */ 188*0Sstevel@tonic-gate CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_REBOOT, -1); 189*0Sstevel@tonic-gate prom_reboot(bootstr); 190*0Sstevel@tonic-gate /*NOTREACHED*/ 191*0Sstevel@tonic-gate } 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate /* 194*0Sstevel@tonic-gate * We use the x-trap mechanism and idle_stop_xcall() to stop the other CPUs. 195*0Sstevel@tonic-gate * Once in panic_idle() they raise spl, record their location, and spin. 196*0Sstevel@tonic-gate */ 197*0Sstevel@tonic-gate static void 198*0Sstevel@tonic-gate panic_idle(void) 199*0Sstevel@tonic-gate { 200*0Sstevel@tonic-gate cpu_async_panic_callb(); /* check for async errors */ 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate (void) spl7(); 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate debug_flush_windows(); 205*0Sstevel@tonic-gate (void) setjmp(&curthread->t_pcb); 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate CPU->cpu_m.in_prom = 1; 208*0Sstevel@tonic-gate membar_stld(); 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate for (;;); 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate /* 214*0Sstevel@tonic-gate * Force the other CPUs to trap into panic_idle(), and then remove them 215*0Sstevel@tonic-gate * from the cpu_ready_set so they will no longer receive cross-calls. 216*0Sstevel@tonic-gate */ 217*0Sstevel@tonic-gate /*ARGSUSED*/ 218*0Sstevel@tonic-gate void 219*0Sstevel@tonic-gate panic_stopcpus(cpu_t *cp, kthread_t *t, int spl) 220*0Sstevel@tonic-gate { 221*0Sstevel@tonic-gate cpuset_t cps; 222*0Sstevel@tonic-gate int i; 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate (void) splzs(); 225*0Sstevel@tonic-gate CPUSET_ALL_BUT(cps, cp->cpu_id); 226*0Sstevel@tonic-gate xt_some(cps, (xcfunc_t *)idle_stop_xcall, (uint64_t)&panic_idle, NULL); 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate for (i = 0; i < NCPU; i++) { 229*0Sstevel@tonic-gate if (i != cp->cpu_id && CPU_XCALL_READY(i)) { 230*0Sstevel@tonic-gate int ntries = 0x10000; 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate while (!cpu[i]->cpu_m.in_prom && ntries) { 233*0Sstevel@tonic-gate DELAY(50); 234*0Sstevel@tonic-gate ntries--; 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate if (!cpu[i]->cpu_m.in_prom) 238*0Sstevel@tonic-gate printf("panic: failed to stop cpu%d\n", i); 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate cpu[i]->cpu_flags &= ~CPU_READY; 241*0Sstevel@tonic-gate cpu[i]->cpu_flags |= CPU_QUIESCED; 242*0Sstevel@tonic-gate CPUSET_DEL(cpu_ready_set, cpu[i]->cpu_id); 243*0Sstevel@tonic-gate } 244*0Sstevel@tonic-gate } 245*0Sstevel@tonic-gate } 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate /* 248*0Sstevel@tonic-gate * Platform callback following each entry to panicsys(). If we've panicked at 249*0Sstevel@tonic-gate * level 14, we examine t_panic_trap to see if a fatal trap occurred. If so, 250*0Sstevel@tonic-gate * we disable further %tick_cmpr interrupts. If not, an explicit call to panic 251*0Sstevel@tonic-gate * was made and so we re-enqueue an interrupt request structure to allow 252*0Sstevel@tonic-gate * further level 14 interrupts to be processed once we lower PIL. This allows 253*0Sstevel@tonic-gate * us to handle panics from the deadman() CY_HIGH_LEVEL cyclic. 254*0Sstevel@tonic-gate */ 255*0Sstevel@tonic-gate void 256*0Sstevel@tonic-gate panic_enter_hw(int spl) 257*0Sstevel@tonic-gate { 258*0Sstevel@tonic-gate if (spl == ipltospl(PIL_14)) { 259*0Sstevel@tonic-gate uint_t opstate = disable_vec_intr(); 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate if (curthread->t_panic_trap != NULL) { 262*0Sstevel@tonic-gate tickcmpr_disable(); 263*0Sstevel@tonic-gate intr_dequeue_req(PIL_14, cbe_level14_inum); 264*0Sstevel@tonic-gate } else { 265*0Sstevel@tonic-gate if (!tickcmpr_disabled()) 266*0Sstevel@tonic-gate intr_enqueue_req(PIL_14, cbe_level14_inum); 267*0Sstevel@tonic-gate /* 268*0Sstevel@tonic-gate * Clear SOFTINT<14>, SOFTINT<0> (TICK_INT) 269*0Sstevel@tonic-gate * and SOFTINT<16> (STICK_INT) to indicate 270*0Sstevel@tonic-gate * that the current level 14 has been serviced. 271*0Sstevel@tonic-gate */ 272*0Sstevel@tonic-gate wr_clr_softint((1 << PIL_14) | 273*0Sstevel@tonic-gate TICK_INT_MASK | STICK_INT_MASK); 274*0Sstevel@tonic-gate } 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gate enable_vec_intr(opstate); 277*0Sstevel@tonic-gate } 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate /* 281*0Sstevel@tonic-gate * Miscellaneous hardware-specific code to execute after panicstr is set 282*0Sstevel@tonic-gate * by the panic code: we also print and record PTL1 panic information here. 283*0Sstevel@tonic-gate */ 284*0Sstevel@tonic-gate /*ARGSUSED*/ 285*0Sstevel@tonic-gate void 286*0Sstevel@tonic-gate panic_quiesce_hw(panic_data_t *pdp) 287*0Sstevel@tonic-gate { 288*0Sstevel@tonic-gate extern uint_t getpstate(void); 289*0Sstevel@tonic-gate extern void setpstate(uint_t); 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate #ifdef TRAPTRACE 292*0Sstevel@tonic-gate /* 293*0Sstevel@tonic-gate * Turn off TRAPTRACE and save the current %tick value in panic_tick. 294*0Sstevel@tonic-gate */ 295*0Sstevel@tonic-gate if (!panic_tick) 296*0Sstevel@tonic-gate panic_tick = gettick(); 297*0Sstevel@tonic-gate TRAPTRACE_FREEZE; 298*0Sstevel@tonic-gate #endif 299*0Sstevel@tonic-gate /* 300*0Sstevel@tonic-gate * For Platforms that use CPU signatures, we 301*0Sstevel@tonic-gate * need to set the signature block to OS, the state to 302*0Sstevel@tonic-gate * exiting, and the substate to panic for all the processors. 303*0Sstevel@tonic-gate */ 304*0Sstevel@tonic-gate CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_PANIC, -1); 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate /* 307*0Sstevel@tonic-gate * De-activate ECC functions and disable the watchdog timer now that 308*0Sstevel@tonic-gate * we've made it through the critical part of the panic code. 309*0Sstevel@tonic-gate */ 310*0Sstevel@tonic-gate if (watchdog_enable) 311*0Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate /* 314*0Sstevel@tonic-gate * Disable further ECC errors from the CPU module and the bus nexus. 315*0Sstevel@tonic-gate */ 316*0Sstevel@tonic-gate cpu_disable_errors(); 317*0Sstevel@tonic-gate (void) bus_func_invoke(BF_TYPE_ERRDIS); 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate /* 320*0Sstevel@tonic-gate * Redirect all interrupts to the current CPU. 321*0Sstevel@tonic-gate */ 322*0Sstevel@tonic-gate intr_redist_all_cpus_shutdown(); 323*0Sstevel@tonic-gate 324*0Sstevel@tonic-gate /* 325*0Sstevel@tonic-gate * This call exists solely to support dumps to network 326*0Sstevel@tonic-gate * devices after sync from OBP. 327*0Sstevel@tonic-gate * 328*0Sstevel@tonic-gate * If we came here via the sync callback, then on some 329*0Sstevel@tonic-gate * platforms, interrupts may have arrived while we were 330*0Sstevel@tonic-gate * stopped in OBP. OBP will arrange for those interrupts to 331*0Sstevel@tonic-gate * be redelivered if you say "go", but not if you invoke a 332*0Sstevel@tonic-gate * client callback like 'sync'. For some dump devices 333*0Sstevel@tonic-gate * (network swap devices), we need interrupts to be 334*0Sstevel@tonic-gate * delivered in order to dump, so we have to call the bus 335*0Sstevel@tonic-gate * nexus driver to reset the interrupt state machines. 336*0Sstevel@tonic-gate */ 337*0Sstevel@tonic-gate (void) bus_func_invoke(BF_TYPE_RESINTR); 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate setpstate(getpstate() | PSTATE_IE); 340*0Sstevel@tonic-gate } 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate /* 343*0Sstevel@tonic-gate * Platforms that use CPU signatures need to set the signature block to OS and 344*0Sstevel@tonic-gate * the state to exiting for all CPUs. PANIC_CONT indicates that we're about to 345*0Sstevel@tonic-gate * write the crash dump, which tells the SSP/SMS to begin a timeout routine to 346*0Sstevel@tonic-gate * reboot the machine if the dump never completes. 347*0Sstevel@tonic-gate */ 348*0Sstevel@tonic-gate /*ARGSUSED*/ 349*0Sstevel@tonic-gate void 350*0Sstevel@tonic-gate panic_dump_hw(int spl) 351*0Sstevel@tonic-gate { 352*0Sstevel@tonic-gate CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_DUMP, -1); 353*0Sstevel@tonic-gate } 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate /* 356*0Sstevel@tonic-gate * for ptl1_panic 357*0Sstevel@tonic-gate */ 358*0Sstevel@tonic-gate void 359*0Sstevel@tonic-gate ptl1_init_cpu(struct cpu *cpu) 360*0Sstevel@tonic-gate { 361*0Sstevel@tonic-gate ptl1_state_t *pstate = &cpu->cpu_m.ptl1_state; 362*0Sstevel@tonic-gate 363*0Sstevel@tonic-gate /*CONSTCOND*/ 364*0Sstevel@tonic-gate if (sizeof (struct cpu) + PTL1_SSIZE > CPU_ALLOC_SIZE) { 365*0Sstevel@tonic-gate panic("ptl1_init_cpu: not enough space left for ptl1_panic " 366*0Sstevel@tonic-gate "stack, sizeof (struct cpu) = %d", sizeof (struct cpu)); 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate pstate->ptl1_stktop = (uintptr_t)cpu + CPU_ALLOC_SIZE; 370*0Sstevel@tonic-gate cpu_pa[cpu->cpu_id] = va_to_pa(cpu); 371*0Sstevel@tonic-gate } 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate void 374*0Sstevel@tonic-gate ptl1_panic_handler(ptl1_state_t *pstate) 375*0Sstevel@tonic-gate { 376*0Sstevel@tonic-gate static const char *ptl1_reasons[] = { 377*0Sstevel@tonic-gate #ifdef PTL1_PANIC_DEBUG 378*0Sstevel@tonic-gate "trap for debug purpose", /* PTL1_BAD_DEBUG */ 379*0Sstevel@tonic-gate #else 380*0Sstevel@tonic-gate "unknown trap", /* PTL1_BAD_DEBUG */ 381*0Sstevel@tonic-gate #endif 382*0Sstevel@tonic-gate "register window trap", /* PTL1_BAD_WTRAP */ 383*0Sstevel@tonic-gate "kernel MMU miss", /* PTL1_BAD_KMISS */ 384*0Sstevel@tonic-gate "kernel protection fault", /* PTL1_BAD_KPROT_FAULT */ 385*0Sstevel@tonic-gate "ISM MMU miss", /* PTL1_BAD_ISM */ 386*0Sstevel@tonic-gate "kernel MMU trap", /* PTL1_BAD_MMUTRAP */ 387*0Sstevel@tonic-gate "kernel trap handler state", /* PTL1_BAD_TRAP */ 388*0Sstevel@tonic-gate "floating point trap", /* PTL1_BAD_FPTRAP */ 389*0Sstevel@tonic-gate #ifdef DEBUG 390*0Sstevel@tonic-gate "pointer to intr_req", /* PTL1_BAD_INTR_REQ */ 391*0Sstevel@tonic-gate #else 392*0Sstevel@tonic-gate "unknown trap", /* PTL1_BAD_INTR_REQ */ 393*0Sstevel@tonic-gate #endif 394*0Sstevel@tonic-gate #ifdef TRAPTRACE 395*0Sstevel@tonic-gate "TRACE_PTR state", /* PTL1_BAD_TRACE_PTR */ 396*0Sstevel@tonic-gate #else 397*0Sstevel@tonic-gate "unknown trap", /* PTL1_BAD_TRACE_PTR */ 398*0Sstevel@tonic-gate #endif 399*0Sstevel@tonic-gate "stack overflow", /* PTL1_BAD_STACK */ 400*0Sstevel@tonic-gate "DTrace flags", /* PTL1_BAD_DTRACE_FLAGS */ 401*0Sstevel@tonic-gate "attempt to steal locked ctx", /* PTL1_BAD_CTX_STEAL */ 402*0Sstevel@tonic-gate "CPU ECC error loop", /* PTL1_BAD_ECC */ 403*0Sstevel@tonic-gate "unknown trap", /* PTL1_BAD_HCALL */ 404*0Sstevel@tonic-gate }; 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gate uint_t reason = pstate->ptl1_regs.ptl1_g1; 407*0Sstevel@tonic-gate uint_t tl = pstate->ptl1_regs.ptl1_trap_regs[0].ptl1_tl; 408*0Sstevel@tonic-gate struct trap_info ti = { 0 }; 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate /* 411*0Sstevel@tonic-gate * Use trap_info for a place holder to call panic_savetrap() and 412*0Sstevel@tonic-gate * panic_showtrap() to save and print out ptl1_panic information. 413*0Sstevel@tonic-gate */ 414*0Sstevel@tonic-gate if (curthread->t_panic_trap == NULL) 415*0Sstevel@tonic-gate curthread->t_panic_trap = &ti; 416*0Sstevel@tonic-gate 417*0Sstevel@tonic-gate if (reason < sizeof (ptl1_reasons) / sizeof (ptl1_reasons[0])) 418*0Sstevel@tonic-gate panic("bad %s at TL %u", ptl1_reasons[reason], tl); 419*0Sstevel@tonic-gate else 420*0Sstevel@tonic-gate panic("ptl1_panic reason 0x%x at TL %u", reason, tl); 421*0Sstevel@tonic-gate } 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gate void 424*0Sstevel@tonic-gate clear_watchdog_on_exit() 425*0Sstevel@tonic-gate { 426*0Sstevel@tonic-gate /* 427*0Sstevel@tonic-gate * Only shut down an active hardware watchdog timer if the platform 428*0Sstevel@tonic-gate * has expressed an interest to. 429*0Sstevel@tonic-gate */ 430*0Sstevel@tonic-gate if (disable_watchdog_on_exit && watchdog_activated) { 431*0Sstevel@tonic-gate prom_printf("Debugging requested; hardware watchdog " 432*0Sstevel@tonic-gate "disabled; reboot to re-enable.\n"); 433*0Sstevel@tonic-gate cmn_err(CE_WARN, "!Debugging requested; hardware watchdog " 434*0Sstevel@tonic-gate "disabled; reboot to re-enable."); 435*0Sstevel@tonic-gate mutex_enter(&tod_lock); 436*0Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 437*0Sstevel@tonic-gate mutex_exit(&tod_lock); 438*0Sstevel@tonic-gate } 439*0Sstevel@tonic-gate } 440*0Sstevel@tonic-gate 441*0Sstevel@tonic-gate int 442*0Sstevel@tonic-gate kdi_watchdog_disable(void) 443*0Sstevel@tonic-gate { 444*0Sstevel@tonic-gate if (watchdog_activated) { 445*0Sstevel@tonic-gate mutex_enter(&tod_lock); 446*0Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 447*0Sstevel@tonic-gate mutex_exit(&tod_lock); 448*0Sstevel@tonic-gate } 449*0Sstevel@tonic-gate 450*0Sstevel@tonic-gate return (watchdog_activated); 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate void 454*0Sstevel@tonic-gate kdi_watchdog_restore(void) 455*0Sstevel@tonic-gate { 456*0Sstevel@tonic-gate if (watchdog_enable) { 457*0Sstevel@tonic-gate mutex_enter(&tod_lock); 458*0Sstevel@tonic-gate (void) tod_ops.tod_set_watchdog_timer(watchdog_timeout_seconds); 459*0Sstevel@tonic-gate mutex_exit(&tod_lock); 460*0Sstevel@tonic-gate } 461*0Sstevel@tonic-gate } 462*0Sstevel@tonic-gate 463*0Sstevel@tonic-gate /*ARGSUSED*/ 464*0Sstevel@tonic-gate void 465*0Sstevel@tonic-gate mach_dump_buffer_init(void) 466*0Sstevel@tonic-gate { 467*0Sstevel@tonic-gate /* 468*0Sstevel@tonic-gate * setup dump buffer to store extra crash information 469*0Sstevel@tonic-gate * not applicable to sun4u 470*0Sstevel@tonic-gate */ 471*0Sstevel@tonic-gate } 472*0Sstevel@tonic-gate 473*0Sstevel@tonic-gate /* 474*0Sstevel@tonic-gate * xt_sync - wait for previous x-traps to finish 475*0Sstevel@tonic-gate */ 476*0Sstevel@tonic-gate void 477*0Sstevel@tonic-gate xt_sync(cpuset_t cpuset) 478*0Sstevel@tonic-gate { 479*0Sstevel@tonic-gate kpreempt_disable(); 480*0Sstevel@tonic-gate CPUSET_DEL(cpuset, CPU->cpu_id); 481*0Sstevel@tonic-gate CPUSET_AND(cpuset, cpu_ready_set); 482*0Sstevel@tonic-gate xt_some(cpuset, (xcfunc_t *)xt_sync_tl1, 0, 0); 483*0Sstevel@tonic-gate kpreempt_enable(); 484*0Sstevel@tonic-gate } 485