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 /* 22*12524SChris.Baumbauer@Oracle.COM * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 23*12524SChris.Baumbauer@Oracle.COM * 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #include <sys/types.h> 280Sstevel@tonic-gate #include <sys/t_lock.h> 290Sstevel@tonic-gate #include <sys/uadmin.h> 300Sstevel@tonic-gate #include <sys/panic.h> 310Sstevel@tonic-gate #include <sys/reboot.h> 320Sstevel@tonic-gate #include <sys/autoconf.h> 330Sstevel@tonic-gate #include <sys/machsystm.h> 340Sstevel@tonic-gate #include <sys/promif.h> 350Sstevel@tonic-gate #include <sys/membar.h> 360Sstevel@tonic-gate #include <vm/hat_sfmmu.h> 370Sstevel@tonic-gate #include <sys/cpu_module.h> 380Sstevel@tonic-gate #include <sys/cpu_sgnblk_defs.h> 390Sstevel@tonic-gate #include <sys/intreg.h> 400Sstevel@tonic-gate #include <sys/consdev.h> 410Sstevel@tonic-gate #include <sys/kdi_impl.h> 42136Sachartre #include <sys/callb.h> 4310843SDave.Plauger@Sun.COM #include <sys/dumphdr.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; 53*12524SChris.Baumbauer@Oracle.COM extern uint64_t cpc_level15_inum; 540Sstevel@tonic-gate 550Sstevel@tonic-gate /* 560Sstevel@tonic-gate * Machine dependent code to reboot. 570Sstevel@tonic-gate * "mdep" is interpreted as a character pointer; if non-null, it is a pointer 580Sstevel@tonic-gate * to a string to be used as the argument string when rebooting. 59136Sachartre * 60136Sachartre * "invoke_cb" is a boolean. It is set to true when mdboot() can safely 61136Sachartre * invoke CB_CL_MDBOOT callbacks before shutting the system down, i.e. when 62136Sachartre * we are in a normal shutdown sequence (interrupts are not blocked, the 63136Sachartre * system is not panic'ing or being suspended). 640Sstevel@tonic-gate */ 650Sstevel@tonic-gate /*ARGSUSED*/ 660Sstevel@tonic-gate void 67136Sachartre mdboot(int cmd, int fcn, char *bootstr, boolean_t invoke_cb) 680Sstevel@tonic-gate { 690Sstevel@tonic-gate extern void pm_cfb_check_and_powerup(void); 700Sstevel@tonic-gate 710Sstevel@tonic-gate /* 720Sstevel@tonic-gate * Disable the hw watchdog timer. 730Sstevel@tonic-gate */ 740Sstevel@tonic-gate if (disable_watchdog_on_exit && watchdog_activated) { 750Sstevel@tonic-gate mutex_enter(&tod_lock); 760Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 770Sstevel@tonic-gate mutex_exit(&tod_lock); 780Sstevel@tonic-gate } 790Sstevel@tonic-gate 800Sstevel@tonic-gate /* 815630Sjbeck * XXX - rconsvp is set to NULL to ensure that output messages 825630Sjbeck * are sent to the underlying "hardware" device using the 835630Sjbeck * monitor's printf routine since we are in the process of 845630Sjbeck * either rebooting or halting the machine. 855630Sjbeck */ 865630Sjbeck rconsvp = NULL; 875630Sjbeck 885630Sjbeck /* 890Sstevel@tonic-gate * At a high interrupt level we can't: 900Sstevel@tonic-gate * 1) bring up the console 910Sstevel@tonic-gate * or 920Sstevel@tonic-gate * 2) wait for pending interrupts prior to redistribution 930Sstevel@tonic-gate * to the current CPU 940Sstevel@tonic-gate * 950Sstevel@tonic-gate * so we do them now. 960Sstevel@tonic-gate */ 970Sstevel@tonic-gate pm_cfb_check_and_powerup(); 980Sstevel@tonic-gate 990Sstevel@tonic-gate /* make sure there are no more changes to the device tree */ 1000Sstevel@tonic-gate devtree_freeze(); 1010Sstevel@tonic-gate 102136Sachartre if (invoke_cb) 103136Sachartre (void) callb_execute_class(CB_CL_MDBOOT, NULL); 104136Sachartre 1050Sstevel@tonic-gate /* 106917Selowe * Clear any unresolved UEs from memory. 107917Selowe */ 1083253Smec page_retire_mdboot(); 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 13311897SChris.Kiick@Sun.COM case AD_FASTREBOOT: 1340Sstevel@tonic-gate case AD_BOOT: 1350Sstevel@tonic-gate bootstr = ""; 1360Sstevel@tonic-gate break; 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate case AD_IBOOT: 1390Sstevel@tonic-gate bootstr = "-a"; 1400Sstevel@tonic-gate break; 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate case AD_SBOOT: 1430Sstevel@tonic-gate bootstr = "-s"; 1440Sstevel@tonic-gate break; 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate case AD_SIBOOT: 1470Sstevel@tonic-gate bootstr = "-sa"; 1480Sstevel@tonic-gate break; 1490Sstevel@tonic-gate default: 1500Sstevel@tonic-gate cmn_err(CE_WARN, 1510Sstevel@tonic-gate "mdboot: invalid function %d", fcn); 1520Sstevel@tonic-gate bootstr = ""; 1530Sstevel@tonic-gate break; 1540Sstevel@tonic-gate } 1550Sstevel@tonic-gate } 15611897SChris.Kiick@Sun.COM if (fcn == AD_FASTREBOOT) { 15711897SChris.Kiick@Sun.COM pnode_t onode; 15811897SChris.Kiick@Sun.COM int dllen; 15911897SChris.Kiick@Sun.COM onode = prom_optionsnode(); 16011897SChris.Kiick@Sun.COM if ((onode == OBP_NONODE) || (onode == OBP_BADNODE)) { 16111897SChris.Kiick@Sun.COM cmn_err(CE_WARN, "Unable to set diag level for" 16211897SChris.Kiick@Sun.COM " quick reboot"); 16311897SChris.Kiick@Sun.COM } else { 16411897SChris.Kiick@Sun.COM dllen = prom_getproplen(onode, "diag-level"); 16511897SChris.Kiick@Sun.COM if (dllen != -1) { 16611897SChris.Kiick@Sun.COM int newstrlen; 16711897SChris.Kiick@Sun.COM char *newstr = kmem_alloc(strlen( 16811897SChris.Kiick@Sun.COM bootstr) + dllen + 5, KM_SLEEP); 16911897SChris.Kiick@Sun.COM (void) strcpy(newstr, bootstr); 17011897SChris.Kiick@Sun.COM (void) strcat(newstr, " -f "); 17111897SChris.Kiick@Sun.COM newstrlen = strlen(bootstr) + 4; 17211897SChris.Kiick@Sun.COM (void) prom_getprop(onode, "diag-level", 17311897SChris.Kiick@Sun.COM (caddr_t)&(newstr[newstrlen])); 17411897SChris.Kiick@Sun.COM newstr[newstrlen + dllen] = '\0'; 17511897SChris.Kiick@Sun.COM bootstr = newstr; 17611897SChris.Kiick@Sun.COM } 17711897SChris.Kiick@Sun.COM (void) prom_setprop(onode, "diag-level", 17811897SChris.Kiick@Sun.COM "off", 4); 17911897SChris.Kiick@Sun.COM } 18011897SChris.Kiick@Sun.COM } 1810Sstevel@tonic-gate reboot_machine(bootstr); 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate /* MAYBE REACHED */ 1840Sstevel@tonic-gate } 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate /* mdpreboot - may be called prior to mdboot while root fs still mounted */ 1870Sstevel@tonic-gate /*ARGSUSED*/ 1880Sstevel@tonic-gate void 1890Sstevel@tonic-gate mdpreboot(int cmd, int fcn, char *bootstr) 1900Sstevel@tonic-gate { 1910Sstevel@tonic-gate } 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate /* 1940Sstevel@tonic-gate * Halt the machine and then reboot with the device 1950Sstevel@tonic-gate * and arguments specified in bootstr. 1960Sstevel@tonic-gate */ 1970Sstevel@tonic-gate static void 1980Sstevel@tonic-gate reboot_machine(char *bootstr) 1990Sstevel@tonic-gate { 2000Sstevel@tonic-gate flush_windows(); 2010Sstevel@tonic-gate stop_other_cpus(); /* send stop signal to other CPUs */ 2020Sstevel@tonic-gate prom_printf("rebooting...\n"); 2030Sstevel@tonic-gate /* 2040Sstevel@tonic-gate * For platforms that use CPU signatures, we 2050Sstevel@tonic-gate * need to set the signature block to OS and 2060Sstevel@tonic-gate * the state to exiting for all the processors. 2070Sstevel@tonic-gate */ 2080Sstevel@tonic-gate CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_REBOOT, -1); 2090Sstevel@tonic-gate prom_reboot(bootstr); 2100Sstevel@tonic-gate /*NOTREACHED*/ 2110Sstevel@tonic-gate } 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate /* 2140Sstevel@tonic-gate * We use the x-trap mechanism and idle_stop_xcall() to stop the other CPUs. 2150Sstevel@tonic-gate * Once in panic_idle() they raise spl, record their location, and spin. 2160Sstevel@tonic-gate */ 2170Sstevel@tonic-gate static void 2180Sstevel@tonic-gate panic_idle(void) 2190Sstevel@tonic-gate { 2200Sstevel@tonic-gate cpu_async_panic_callb(); /* check for async errors */ 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate (void) spl7(); 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate debug_flush_windows(); 2250Sstevel@tonic-gate (void) setjmp(&curthread->t_pcb); 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate CPU->cpu_m.in_prom = 1; 2280Sstevel@tonic-gate membar_stld(); 2290Sstevel@tonic-gate 23010843SDave.Plauger@Sun.COM dumpsys_helper(); 23110843SDave.Plauger@Sun.COM 2325084Sjohnlev for (;;) 2335084Sjohnlev continue; 2340Sstevel@tonic-gate } 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate /* 2370Sstevel@tonic-gate * Force the other CPUs to trap into panic_idle(), and then remove them 2380Sstevel@tonic-gate * from the cpu_ready_set so they will no longer receive cross-calls. 2390Sstevel@tonic-gate */ 2400Sstevel@tonic-gate /*ARGSUSED*/ 2410Sstevel@tonic-gate void 2420Sstevel@tonic-gate panic_stopcpus(cpu_t *cp, kthread_t *t, int spl) 2430Sstevel@tonic-gate { 2440Sstevel@tonic-gate cpuset_t cps; 2450Sstevel@tonic-gate int i; 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate (void) splzs(); 2480Sstevel@tonic-gate CPUSET_ALL_BUT(cps, cp->cpu_id); 2490Sstevel@tonic-gate xt_some(cps, (xcfunc_t *)idle_stop_xcall, (uint64_t)&panic_idle, NULL); 2500Sstevel@tonic-gate 2510Sstevel@tonic-gate for (i = 0; i < NCPU; i++) { 2520Sstevel@tonic-gate if (i != cp->cpu_id && CPU_XCALL_READY(i)) { 2530Sstevel@tonic-gate int ntries = 0x10000; 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate while (!cpu[i]->cpu_m.in_prom && ntries) { 2560Sstevel@tonic-gate DELAY(50); 2570Sstevel@tonic-gate ntries--; 2580Sstevel@tonic-gate } 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate if (!cpu[i]->cpu_m.in_prom) 2610Sstevel@tonic-gate printf("panic: failed to stop cpu%d\n", i); 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate cpu[i]->cpu_flags &= ~CPU_READY; 2640Sstevel@tonic-gate cpu[i]->cpu_flags |= CPU_QUIESCED; 2650Sstevel@tonic-gate CPUSET_DEL(cpu_ready_set, cpu[i]->cpu_id); 2660Sstevel@tonic-gate } 2670Sstevel@tonic-gate } 2680Sstevel@tonic-gate } 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate /* 2710Sstevel@tonic-gate * Platform callback following each entry to panicsys(). If we've panicked at 2720Sstevel@tonic-gate * level 14, we examine t_panic_trap to see if a fatal trap occurred. If so, 2730Sstevel@tonic-gate * we disable further %tick_cmpr interrupts. If not, an explicit call to panic 2740Sstevel@tonic-gate * was made and so we re-enqueue an interrupt request structure to allow 2750Sstevel@tonic-gate * further level 14 interrupts to be processed once we lower PIL. This allows 2760Sstevel@tonic-gate * us to handle panics from the deadman() CY_HIGH_LEVEL cyclic. 277*12524SChris.Baumbauer@Oracle.COM * 278*12524SChris.Baumbauer@Oracle.COM * In case we panic at level 15, ensure that the cpc handler has been 279*12524SChris.Baumbauer@Oracle.COM * reinstalled otherwise we could run the risk of hitting a missing interrupt 280*12524SChris.Baumbauer@Oracle.COM * handler when this thread drops PIL and the cpc counter overflows. 2810Sstevel@tonic-gate */ 2820Sstevel@tonic-gate void 2830Sstevel@tonic-gate panic_enter_hw(int spl) 2840Sstevel@tonic-gate { 285*12524SChris.Baumbauer@Oracle.COM uint_t opstate; 286*12524SChris.Baumbauer@Oracle.COM 2870Sstevel@tonic-gate if (spl == ipltospl(PIL_14)) { 288*12524SChris.Baumbauer@Oracle.COM opstate = disable_vec_intr(); 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate if (curthread->t_panic_trap != NULL) { 2910Sstevel@tonic-gate tickcmpr_disable(); 2920Sstevel@tonic-gate intr_dequeue_req(PIL_14, cbe_level14_inum); 2930Sstevel@tonic-gate } else { 2940Sstevel@tonic-gate if (!tickcmpr_disabled()) 2950Sstevel@tonic-gate intr_enqueue_req(PIL_14, cbe_level14_inum); 2960Sstevel@tonic-gate /* 2970Sstevel@tonic-gate * Clear SOFTINT<14>, SOFTINT<0> (TICK_INT) 2980Sstevel@tonic-gate * and SOFTINT<16> (STICK_INT) to indicate 2990Sstevel@tonic-gate * that the current level 14 has been serviced. 3000Sstevel@tonic-gate */ 3010Sstevel@tonic-gate wr_clr_softint((1 << PIL_14) | 3025084Sjohnlev TICK_INT_MASK | STICK_INT_MASK); 3030Sstevel@tonic-gate } 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate enable_vec_intr(opstate); 306*12524SChris.Baumbauer@Oracle.COM } else if (spl == ipltospl(PIL_15)) { 307*12524SChris.Baumbauer@Oracle.COM opstate = disable_vec_intr(); 308*12524SChris.Baumbauer@Oracle.COM intr_enqueue_req(PIL_15, cpc_level15_inum); 309*12524SChris.Baumbauer@Oracle.COM wr_clr_softint(1 << PIL_15); 310*12524SChris.Baumbauer@Oracle.COM enable_vec_intr(opstate); 3110Sstevel@tonic-gate } 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate /* 3150Sstevel@tonic-gate * Miscellaneous hardware-specific code to execute after panicstr is set 3160Sstevel@tonic-gate * by the panic code: we also print and record PTL1 panic information here. 3170Sstevel@tonic-gate */ 3180Sstevel@tonic-gate /*ARGSUSED*/ 3190Sstevel@tonic-gate void 3200Sstevel@tonic-gate panic_quiesce_hw(panic_data_t *pdp) 3210Sstevel@tonic-gate { 3220Sstevel@tonic-gate extern uint_t getpstate(void); 3230Sstevel@tonic-gate extern void setpstate(uint_t); 3240Sstevel@tonic-gate 3250Sstevel@tonic-gate #ifdef TRAPTRACE 3260Sstevel@tonic-gate /* 3270Sstevel@tonic-gate * Turn off TRAPTRACE and save the current %tick value in panic_tick. 3280Sstevel@tonic-gate */ 3290Sstevel@tonic-gate if (!panic_tick) 3300Sstevel@tonic-gate panic_tick = gettick(); 3310Sstevel@tonic-gate TRAPTRACE_FREEZE; 3320Sstevel@tonic-gate #endif 3330Sstevel@tonic-gate /* 3340Sstevel@tonic-gate * For Platforms that use CPU signatures, we 3350Sstevel@tonic-gate * need to set the signature block to OS, the state to 3360Sstevel@tonic-gate * exiting, and the substate to panic for all the processors. 3370Sstevel@tonic-gate */ 3380Sstevel@tonic-gate CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_PANIC, -1); 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate /* 3410Sstevel@tonic-gate * De-activate ECC functions and disable the watchdog timer now that 3420Sstevel@tonic-gate * we've made it through the critical part of the panic code. 3430Sstevel@tonic-gate */ 3440Sstevel@tonic-gate if (watchdog_enable) 3450Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate /* 3480Sstevel@tonic-gate * Disable further ECC errors from the CPU module and the bus nexus. 3490Sstevel@tonic-gate */ 3500Sstevel@tonic-gate cpu_disable_errors(); 3510Sstevel@tonic-gate (void) bus_func_invoke(BF_TYPE_ERRDIS); 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate /* 3540Sstevel@tonic-gate * Redirect all interrupts to the current CPU. 3550Sstevel@tonic-gate */ 3560Sstevel@tonic-gate intr_redist_all_cpus_shutdown(); 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate /* 3590Sstevel@tonic-gate * This call exists solely to support dumps to network 3600Sstevel@tonic-gate * devices after sync from OBP. 3610Sstevel@tonic-gate * 3620Sstevel@tonic-gate * If we came here via the sync callback, then on some 3630Sstevel@tonic-gate * platforms, interrupts may have arrived while we were 3640Sstevel@tonic-gate * stopped in OBP. OBP will arrange for those interrupts to 3650Sstevel@tonic-gate * be redelivered if you say "go", but not if you invoke a 3660Sstevel@tonic-gate * client callback like 'sync'. For some dump devices 3670Sstevel@tonic-gate * (network swap devices), we need interrupts to be 3680Sstevel@tonic-gate * delivered in order to dump, so we have to call the bus 3690Sstevel@tonic-gate * nexus driver to reset the interrupt state machines. 3700Sstevel@tonic-gate */ 3710Sstevel@tonic-gate (void) bus_func_invoke(BF_TYPE_RESINTR); 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate setpstate(getpstate() | PSTATE_IE); 3740Sstevel@tonic-gate } 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate /* 3770Sstevel@tonic-gate * Platforms that use CPU signatures need to set the signature block to OS and 3780Sstevel@tonic-gate * the state to exiting for all CPUs. PANIC_CONT indicates that we're about to 3790Sstevel@tonic-gate * write the crash dump, which tells the SSP/SMS to begin a timeout routine to 3800Sstevel@tonic-gate * reboot the machine if the dump never completes. 3810Sstevel@tonic-gate */ 3820Sstevel@tonic-gate /*ARGSUSED*/ 3830Sstevel@tonic-gate void 3840Sstevel@tonic-gate panic_dump_hw(int spl) 3850Sstevel@tonic-gate { 3860Sstevel@tonic-gate CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_DUMP, -1); 3870Sstevel@tonic-gate } 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate /* 3900Sstevel@tonic-gate * for ptl1_panic 3910Sstevel@tonic-gate */ 3920Sstevel@tonic-gate void 3930Sstevel@tonic-gate ptl1_init_cpu(struct cpu *cpu) 3940Sstevel@tonic-gate { 3950Sstevel@tonic-gate ptl1_state_t *pstate = &cpu->cpu_m.ptl1_state; 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate /*CONSTCOND*/ 3980Sstevel@tonic-gate if (sizeof (struct cpu) + PTL1_SSIZE > CPU_ALLOC_SIZE) { 3990Sstevel@tonic-gate panic("ptl1_init_cpu: not enough space left for ptl1_panic " 4001009Smathue "stack, sizeof (struct cpu) = %lu", sizeof (struct cpu)); 4010Sstevel@tonic-gate } 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate pstate->ptl1_stktop = (uintptr_t)cpu + CPU_ALLOC_SIZE; 4040Sstevel@tonic-gate cpu_pa[cpu->cpu_id] = va_to_pa(cpu); 4050Sstevel@tonic-gate } 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate void 4080Sstevel@tonic-gate ptl1_panic_handler(ptl1_state_t *pstate) 4090Sstevel@tonic-gate { 4100Sstevel@tonic-gate static const char *ptl1_reasons[] = { 4110Sstevel@tonic-gate #ifdef PTL1_PANIC_DEBUG 4120Sstevel@tonic-gate "trap for debug purpose", /* PTL1_BAD_DEBUG */ 4130Sstevel@tonic-gate #else 4140Sstevel@tonic-gate "unknown trap", /* PTL1_BAD_DEBUG */ 4150Sstevel@tonic-gate #endif 4160Sstevel@tonic-gate "register window trap", /* PTL1_BAD_WTRAP */ 4170Sstevel@tonic-gate "kernel MMU miss", /* PTL1_BAD_KMISS */ 4180Sstevel@tonic-gate "kernel protection fault", /* PTL1_BAD_KPROT_FAULT */ 4190Sstevel@tonic-gate "ISM MMU miss", /* PTL1_BAD_ISM */ 4200Sstevel@tonic-gate "kernel MMU trap", /* PTL1_BAD_MMUTRAP */ 4210Sstevel@tonic-gate "kernel trap handler state", /* PTL1_BAD_TRAP */ 4220Sstevel@tonic-gate "floating point trap", /* PTL1_BAD_FPTRAP */ 4230Sstevel@tonic-gate #ifdef DEBUG 4242973Sgovinda "pointer to intr_vec", /* PTL1_BAD_INTR_VEC */ 4250Sstevel@tonic-gate #else 4262973Sgovinda "unknown trap", /* PTL1_BAD_INTR_VEC */ 4270Sstevel@tonic-gate #endif 4280Sstevel@tonic-gate #ifdef TRAPTRACE 4290Sstevel@tonic-gate "TRACE_PTR state", /* PTL1_BAD_TRACE_PTR */ 4300Sstevel@tonic-gate #else 4310Sstevel@tonic-gate "unknown trap", /* PTL1_BAD_TRACE_PTR */ 4320Sstevel@tonic-gate #endif 4330Sstevel@tonic-gate "stack overflow", /* PTL1_BAD_STACK */ 4340Sstevel@tonic-gate "DTrace flags", /* PTL1_BAD_DTRACE_FLAGS */ 4350Sstevel@tonic-gate "attempt to steal locked ctx", /* PTL1_BAD_CTX_STEAL */ 4360Sstevel@tonic-gate "CPU ECC error loop", /* PTL1_BAD_ECC */ 4371270Sbs21162 "non-kernel context in sys/priv_trap() below or", 4381270Sbs21162 /* PTL1_BAD_CTX */ 4396127Ssm142603 "error raising a TSB exception", /* PTL1_BAD_RAISE_TSBEXCP */ 4406127Ssm142603 "missing shared TSB" /* PTL1_NO_SCDTSB8K */ 4410Sstevel@tonic-gate }; 4420Sstevel@tonic-gate 4430Sstevel@tonic-gate uint_t reason = pstate->ptl1_regs.ptl1_g1; 4440Sstevel@tonic-gate uint_t tl = pstate->ptl1_regs.ptl1_trap_regs[0].ptl1_tl; 4455084Sjohnlev struct panic_trap_info ti = { 0 }; 4460Sstevel@tonic-gate 4470Sstevel@tonic-gate /* 4480Sstevel@tonic-gate * Use trap_info for a place holder to call panic_savetrap() and 4490Sstevel@tonic-gate * panic_showtrap() to save and print out ptl1_panic information. 4500Sstevel@tonic-gate */ 4510Sstevel@tonic-gate if (curthread->t_panic_trap == NULL) 4520Sstevel@tonic-gate curthread->t_panic_trap = &ti; 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate if (reason < sizeof (ptl1_reasons) / sizeof (ptl1_reasons[0])) 4550Sstevel@tonic-gate panic("bad %s at TL %u", ptl1_reasons[reason], tl); 4560Sstevel@tonic-gate else 4570Sstevel@tonic-gate panic("ptl1_panic reason 0x%x at TL %u", reason, tl); 4580Sstevel@tonic-gate } 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate void 4610Sstevel@tonic-gate clear_watchdog_on_exit() 4620Sstevel@tonic-gate { 4630Sstevel@tonic-gate /* 4640Sstevel@tonic-gate * Only shut down an active hardware watchdog timer if the platform 4650Sstevel@tonic-gate * has expressed an interest to. 4660Sstevel@tonic-gate */ 4670Sstevel@tonic-gate if (disable_watchdog_on_exit && watchdog_activated) { 4680Sstevel@tonic-gate prom_printf("Debugging requested; hardware watchdog " 4690Sstevel@tonic-gate "disabled; reboot to re-enable.\n"); 4700Sstevel@tonic-gate cmn_err(CE_WARN, "!Debugging requested; hardware watchdog " 4710Sstevel@tonic-gate "disabled; reboot to re-enable."); 4720Sstevel@tonic-gate mutex_enter(&tod_lock); 4730Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 4740Sstevel@tonic-gate mutex_exit(&tod_lock); 4750Sstevel@tonic-gate } 4760Sstevel@tonic-gate } 4770Sstevel@tonic-gate 4782036Swentaoy /* 4792036Swentaoy * This null routine is only used by sun4v watchdog timer support. 4802036Swentaoy */ 4812036Swentaoy void 4822036Swentaoy restore_watchdog_on_entry(void) 4832036Swentaoy { 4842036Swentaoy } 4852036Swentaoy 4860Sstevel@tonic-gate int 4870Sstevel@tonic-gate kdi_watchdog_disable(void) 4880Sstevel@tonic-gate { 4890Sstevel@tonic-gate if (watchdog_activated) { 4900Sstevel@tonic-gate mutex_enter(&tod_lock); 4910Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 4920Sstevel@tonic-gate mutex_exit(&tod_lock); 4930Sstevel@tonic-gate } 4940Sstevel@tonic-gate 4950Sstevel@tonic-gate return (watchdog_activated); 4960Sstevel@tonic-gate } 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate void 4990Sstevel@tonic-gate kdi_watchdog_restore(void) 5000Sstevel@tonic-gate { 5010Sstevel@tonic-gate if (watchdog_enable) { 5020Sstevel@tonic-gate mutex_enter(&tod_lock); 5030Sstevel@tonic-gate (void) tod_ops.tod_set_watchdog_timer(watchdog_timeout_seconds); 5040Sstevel@tonic-gate mutex_exit(&tod_lock); 5050Sstevel@tonic-gate } 5060Sstevel@tonic-gate } 5070Sstevel@tonic-gate 5080Sstevel@tonic-gate /*ARGSUSED*/ 5090Sstevel@tonic-gate void 5100Sstevel@tonic-gate mach_dump_buffer_init(void) 5110Sstevel@tonic-gate { 5120Sstevel@tonic-gate /* 5130Sstevel@tonic-gate * setup dump buffer to store extra crash information 5140Sstevel@tonic-gate * not applicable to sun4u 5150Sstevel@tonic-gate */ 5160Sstevel@tonic-gate } 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate /* 5190Sstevel@tonic-gate * xt_sync - wait for previous x-traps to finish 5200Sstevel@tonic-gate */ 5210Sstevel@tonic-gate void 5220Sstevel@tonic-gate xt_sync(cpuset_t cpuset) 5230Sstevel@tonic-gate { 5240Sstevel@tonic-gate kpreempt_disable(); 5250Sstevel@tonic-gate CPUSET_DEL(cpuset, CPU->cpu_id); 5260Sstevel@tonic-gate CPUSET_AND(cpuset, cpu_ready_set); 5270Sstevel@tonic-gate xt_some(cpuset, (xcfunc_t *)xt_sync_tl1, 0, 0); 5280Sstevel@tonic-gate kpreempt_enable(); 5290Sstevel@tonic-gate } 5303266Sjb145095 5313266Sjb145095 /* 5323266Sjb145095 * mach_soft_state_init() - dummy routine for sun4v soft state 5333266Sjb145095 */ 5343266Sjb145095 void 5353266Sjb145095 mach_soft_state_init(void) 5363266Sjb145095 {} 537