17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 53c431bb5Swentaoy * Common Development and Distribution License (the "License"). 63c431bb5Swentaoy * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22a1bf6e2eSChristopher Baumbauer - Oracle America - San Diego United States * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 23a1bf6e2eSChristopher Baumbauer - Oracle America - San Diego United States * 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <sys/types.h> 287c478bd9Sstevel@tonic-gate #include <sys/t_lock.h> 297c478bd9Sstevel@tonic-gate #include <sys/uadmin.h> 307c478bd9Sstevel@tonic-gate #include <sys/panic.h> 317c478bd9Sstevel@tonic-gate #include <sys/reboot.h> 327c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 337c478bd9Sstevel@tonic-gate #include <sys/machsystm.h> 347c478bd9Sstevel@tonic-gate #include <sys/promif.h> 357c478bd9Sstevel@tonic-gate #include <sys/membar.h> 367c478bd9Sstevel@tonic-gate #include <vm/hat_sfmmu.h> 377c478bd9Sstevel@tonic-gate #include <sys/cpu_module.h> 387c478bd9Sstevel@tonic-gate #include <sys/cpu_sgnblk_defs.h> 397c478bd9Sstevel@tonic-gate #include <sys/intreg.h> 407c478bd9Sstevel@tonic-gate #include <sys/consdev.h> 417c478bd9Sstevel@tonic-gate #include <sys/kdi_impl.h> 42edc40228Sachartre #include <sys/callb.h> 43ca3e8d88SDave Plauger #include <sys/dumphdr.h> 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate #ifdef TRAPTRACE 467c478bd9Sstevel@tonic-gate #include <sys/traptrace.h> 477c478bd9Sstevel@tonic-gate u_longlong_t panic_tick; 487c478bd9Sstevel@tonic-gate #endif /* TRAPTRACE */ 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate extern u_longlong_t gettick(); 517c478bd9Sstevel@tonic-gate static void reboot_machine(char *); 523c431bb5Swentaoy int disable_watchdog_on_exit = 0; 53a1bf6e2eSChristopher Baumbauer - Oracle America - San Diego United States extern uint64_t cpc_level15_inum; 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate /* 567c478bd9Sstevel@tonic-gate * Machine dependent code to reboot. 577c478bd9Sstevel@tonic-gate * "mdep" is interpreted as a character pointer; if non-null, it is a pointer 587c478bd9Sstevel@tonic-gate * to a string to be used as the argument string when rebooting. 59edc40228Sachartre * 60edc40228Sachartre * "invoke_cb" is a boolean. It is set to true when mdboot() can safely 61edc40228Sachartre * invoke CB_CL_MDBOOT callbacks before shutting the system down, i.e. when 62edc40228Sachartre * we are in a normal shutdown sequence (interrupts are not blocked, the 63edc40228Sachartre * system is not panic'ing or being suspended). 647c478bd9Sstevel@tonic-gate */ 657c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 667c478bd9Sstevel@tonic-gate void 67edc40228Sachartre mdboot(int cmd, int fcn, char *bootstr, boolean_t invoke_cb) 687c478bd9Sstevel@tonic-gate { 697c478bd9Sstevel@tonic-gate extern void pm_cfb_check_and_powerup(void); 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate /* 727c478bd9Sstevel@tonic-gate * Disable the hw watchdog timer. 737c478bd9Sstevel@tonic-gate */ 747c478bd9Sstevel@tonic-gate if (disable_watchdog_on_exit && watchdog_activated) { 757c478bd9Sstevel@tonic-gate mutex_enter(&tod_lock); 767c478bd9Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 777c478bd9Sstevel@tonic-gate mutex_exit(&tod_lock); 787c478bd9Sstevel@tonic-gate } 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /* 81281888b3Sjbeck * XXX - rconsvp is set to NULL to ensure that output messages 82281888b3Sjbeck * are sent to the underlying "hardware" device using the 83281888b3Sjbeck * monitor's printf routine since we are in the process of 84281888b3Sjbeck * either rebooting or halting the machine. 85281888b3Sjbeck */ 86281888b3Sjbeck rconsvp = NULL; 87281888b3Sjbeck 88281888b3Sjbeck /* 897c478bd9Sstevel@tonic-gate * At a high interrupt level we can't: 907c478bd9Sstevel@tonic-gate * 1) bring up the console 917c478bd9Sstevel@tonic-gate * or 927c478bd9Sstevel@tonic-gate * 2) wait for pending interrupts prior to redistribution 937c478bd9Sstevel@tonic-gate * to the current CPU 947c478bd9Sstevel@tonic-gate * 957c478bd9Sstevel@tonic-gate * so we do them now. 967c478bd9Sstevel@tonic-gate */ 977c478bd9Sstevel@tonic-gate pm_cfb_check_and_powerup(); 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate /* make sure there are no more changes to the device tree */ 1007c478bd9Sstevel@tonic-gate devtree_freeze(); 1017c478bd9Sstevel@tonic-gate 102edc40228Sachartre if (invoke_cb) 103edc40228Sachartre (void) callb_execute_class(CB_CL_MDBOOT, NULL); 104edc40228Sachartre 1057c478bd9Sstevel@tonic-gate /* 106db874c57Selowe * Clear any unresolved UEs from memory. 107db874c57Selowe */ 1088b464eb8Smec page_retire_mdboot(); 109db874c57Selowe 110db874c57Selowe /* 1117c478bd9Sstevel@tonic-gate * stop other cpus which also raise our priority. since there is only 1127c478bd9Sstevel@tonic-gate * one active cpu after this, and our priority will be too high 1137c478bd9Sstevel@tonic-gate * for us to be preempted, we're essentially single threaded 1147c478bd9Sstevel@tonic-gate * from here on out. 1157c478bd9Sstevel@tonic-gate */ 1167c478bd9Sstevel@tonic-gate stop_other_cpus(); 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * try and reset leaf devices. reset_leaves() should only 1207c478bd9Sstevel@tonic-gate * be called when there are no other threads that could be 1217c478bd9Sstevel@tonic-gate * accessing devices 1227c478bd9Sstevel@tonic-gate */ 1237c478bd9Sstevel@tonic-gate reset_leaves(); 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate if (fcn == AD_HALT) { 1267c478bd9Sstevel@tonic-gate halt((char *)NULL); 1277c478bd9Sstevel@tonic-gate } else if (fcn == AD_POWEROFF) { 1287c478bd9Sstevel@tonic-gate power_down(NULL); 1297c478bd9Sstevel@tonic-gate } else { 1307c478bd9Sstevel@tonic-gate if (bootstr == NULL) { 1317c478bd9Sstevel@tonic-gate switch (fcn) { 1327c478bd9Sstevel@tonic-gate 133e557d412SChristopher Kiick case AD_FASTREBOOT: 1347c478bd9Sstevel@tonic-gate case AD_BOOT: 1357c478bd9Sstevel@tonic-gate bootstr = ""; 1367c478bd9Sstevel@tonic-gate break; 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate case AD_IBOOT: 1397c478bd9Sstevel@tonic-gate bootstr = "-a"; 1407c478bd9Sstevel@tonic-gate break; 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate case AD_SBOOT: 1437c478bd9Sstevel@tonic-gate bootstr = "-s"; 1447c478bd9Sstevel@tonic-gate break; 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate case AD_SIBOOT: 1477c478bd9Sstevel@tonic-gate bootstr = "-sa"; 1487c478bd9Sstevel@tonic-gate break; 1497c478bd9Sstevel@tonic-gate default: 1507c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 1517c478bd9Sstevel@tonic-gate "mdboot: invalid function %d", fcn); 1527c478bd9Sstevel@tonic-gate bootstr = ""; 1537c478bd9Sstevel@tonic-gate break; 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate } 156e557d412SChristopher Kiick if (fcn == AD_FASTREBOOT) { 157e557d412SChristopher Kiick pnode_t onode; 158e557d412SChristopher Kiick int dllen; 159e557d412SChristopher Kiick onode = prom_optionsnode(); 160e557d412SChristopher Kiick if ((onode == OBP_NONODE) || (onode == OBP_BADNODE)) { 161e557d412SChristopher Kiick cmn_err(CE_WARN, "Unable to set diag level for" 162e557d412SChristopher Kiick " quick reboot"); 163e557d412SChristopher Kiick } else { 164e557d412SChristopher Kiick dllen = prom_getproplen(onode, "diag-level"); 165e557d412SChristopher Kiick if (dllen != -1) { 166e557d412SChristopher Kiick char *newstr = kmem_alloc(strlen( 167*79b62d18SJustin Frank bootstr) + dllen + 5, KM_NOSLEEP); 168*79b62d18SJustin Frank if (newstr != NULL) { 169*79b62d18SJustin Frank int newstrlen; 170e557d412SChristopher Kiick (void) strcpy(newstr, bootstr); 171e557d412SChristopher Kiick (void) strcat(newstr, " -f "); 172e557d412SChristopher Kiick newstrlen = strlen(bootstr) + 4; 173*79b62d18SJustin Frank (void) prom_getprop(onode, 174*79b62d18SJustin Frank "diag-level", 175*79b62d18SJustin Frank (caddr_t) 176*79b62d18SJustin Frank &(newstr[newstrlen])); 177*79b62d18SJustin Frank newstr[newstrlen + dllen] = 178*79b62d18SJustin Frank '\0'; 179e557d412SChristopher Kiick bootstr = newstr; 180*79b62d18SJustin Frank (void) prom_setprop(onode, 181*79b62d18SJustin Frank "diag-level", 182e557d412SChristopher Kiick "off", 4); 183e557d412SChristopher Kiick } 184e557d412SChristopher Kiick } 185*79b62d18SJustin Frank } 186*79b62d18SJustin Frank } 1877c478bd9Sstevel@tonic-gate reboot_machine(bootstr); 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate /* MAYBE REACHED */ 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate /* mdpreboot - may be called prior to mdboot while root fs still mounted */ 1937c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1947c478bd9Sstevel@tonic-gate void 1957c478bd9Sstevel@tonic-gate mdpreboot(int cmd, int fcn, char *bootstr) 1967c478bd9Sstevel@tonic-gate { 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate /* 2007c478bd9Sstevel@tonic-gate * Halt the machine and then reboot with the device 2017c478bd9Sstevel@tonic-gate * and arguments specified in bootstr. 2027c478bd9Sstevel@tonic-gate */ 2037c478bd9Sstevel@tonic-gate static void 2047c478bd9Sstevel@tonic-gate reboot_machine(char *bootstr) 2057c478bd9Sstevel@tonic-gate { 2067c478bd9Sstevel@tonic-gate flush_windows(); 2077c478bd9Sstevel@tonic-gate stop_other_cpus(); /* send stop signal to other CPUs */ 2087c478bd9Sstevel@tonic-gate prom_printf("rebooting...\n"); 2097c478bd9Sstevel@tonic-gate /* 2107c478bd9Sstevel@tonic-gate * For platforms that use CPU signatures, we 2117c478bd9Sstevel@tonic-gate * need to set the signature block to OS and 2127c478bd9Sstevel@tonic-gate * the state to exiting for all the processors. 2137c478bd9Sstevel@tonic-gate */ 2147c478bd9Sstevel@tonic-gate CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_REBOOT, -1); 2157c478bd9Sstevel@tonic-gate prom_reboot(bootstr); 2167c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate /* 2207c478bd9Sstevel@tonic-gate * We use the x-trap mechanism and idle_stop_xcall() to stop the other CPUs. 2217c478bd9Sstevel@tonic-gate * Once in panic_idle() they raise spl, record their location, and spin. 2227c478bd9Sstevel@tonic-gate */ 2237c478bd9Sstevel@tonic-gate static void 2247c478bd9Sstevel@tonic-gate panic_idle(void) 2257c478bd9Sstevel@tonic-gate { 2267c478bd9Sstevel@tonic-gate cpu_async_panic_callb(); /* check for async errors */ 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate (void) spl7(); 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate debug_flush_windows(); 2317c478bd9Sstevel@tonic-gate (void) setjmp(&curthread->t_pcb); 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate CPU->cpu_m.in_prom = 1; 2347c478bd9Sstevel@tonic-gate membar_stld(); 2357c478bd9Sstevel@tonic-gate 236ca3e8d88SDave Plauger dumpsys_helper(); 237ca3e8d88SDave Plauger 238843e1988Sjohnlev for (;;) 239843e1988Sjohnlev continue; 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* 2437c478bd9Sstevel@tonic-gate * Force the other CPUs to trap into panic_idle(), and then remove them 2447c478bd9Sstevel@tonic-gate * from the cpu_ready_set so they will no longer receive cross-calls. 2457c478bd9Sstevel@tonic-gate */ 2467c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 2477c478bd9Sstevel@tonic-gate void 2487c478bd9Sstevel@tonic-gate panic_stopcpus(cpu_t *cp, kthread_t *t, int spl) 2497c478bd9Sstevel@tonic-gate { 2507c478bd9Sstevel@tonic-gate cpuset_t cps; 2517c478bd9Sstevel@tonic-gate int i; 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate (void) splzs(); 2547c478bd9Sstevel@tonic-gate CPUSET_ALL_BUT(cps, cp->cpu_id); 2557c478bd9Sstevel@tonic-gate xt_some(cps, (xcfunc_t *)idle_stop_xcall, (uint64_t)&panic_idle, NULL); 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate for (i = 0; i < NCPU; i++) { 2587c478bd9Sstevel@tonic-gate if (i != cp->cpu_id && CPU_XCALL_READY(i)) { 2597c478bd9Sstevel@tonic-gate int ntries = 0x10000; 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate while (!cpu[i]->cpu_m.in_prom && ntries) { 2627c478bd9Sstevel@tonic-gate DELAY(50); 2637c478bd9Sstevel@tonic-gate ntries--; 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate if (!cpu[i]->cpu_m.in_prom) 2677c478bd9Sstevel@tonic-gate printf("panic: failed to stop cpu%d\n", i); 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate cpu[i]->cpu_flags &= ~CPU_READY; 2707c478bd9Sstevel@tonic-gate cpu[i]->cpu_flags |= CPU_QUIESCED; 2717c478bd9Sstevel@tonic-gate CPUSET_DEL(cpu_ready_set, cpu[i]->cpu_id); 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate /* 2777c478bd9Sstevel@tonic-gate * Platform callback following each entry to panicsys(). If we've panicked at 2787c478bd9Sstevel@tonic-gate * level 14, we examine t_panic_trap to see if a fatal trap occurred. If so, 2797c478bd9Sstevel@tonic-gate * we disable further %tick_cmpr interrupts. If not, an explicit call to panic 2807c478bd9Sstevel@tonic-gate * was made and so we re-enqueue an interrupt request structure to allow 2817c478bd9Sstevel@tonic-gate * further level 14 interrupts to be processed once we lower PIL. This allows 2827c478bd9Sstevel@tonic-gate * us to handle panics from the deadman() CY_HIGH_LEVEL cyclic. 283a1bf6e2eSChristopher Baumbauer - Oracle America - San Diego United States * 284a1bf6e2eSChristopher Baumbauer - Oracle America - San Diego United States * In case we panic at level 15, ensure that the cpc handler has been 285a1bf6e2eSChristopher Baumbauer - Oracle America - San Diego United States * reinstalled otherwise we could run the risk of hitting a missing interrupt 286a1bf6e2eSChristopher Baumbauer - Oracle America - San Diego United States * handler when this thread drops PIL and the cpc counter overflows. 2877c478bd9Sstevel@tonic-gate */ 2887c478bd9Sstevel@tonic-gate void 2897c478bd9Sstevel@tonic-gate panic_enter_hw(int spl) 2907c478bd9Sstevel@tonic-gate { 291a1bf6e2eSChristopher Baumbauer - Oracle America - San Diego United States uint_t opstate; 292a1bf6e2eSChristopher Baumbauer - Oracle America - San Diego United States 2937c478bd9Sstevel@tonic-gate if (spl == ipltospl(PIL_14)) { 294a1bf6e2eSChristopher Baumbauer - Oracle America - San Diego United States opstate = disable_vec_intr(); 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate if (curthread->t_panic_trap != NULL) { 2977c478bd9Sstevel@tonic-gate tickcmpr_disable(); 2987c478bd9Sstevel@tonic-gate intr_dequeue_req(PIL_14, cbe_level14_inum); 2997c478bd9Sstevel@tonic-gate } else { 3007c478bd9Sstevel@tonic-gate if (!tickcmpr_disabled()) 3017c478bd9Sstevel@tonic-gate intr_enqueue_req(PIL_14, cbe_level14_inum); 3027c478bd9Sstevel@tonic-gate /* 3037c478bd9Sstevel@tonic-gate * Clear SOFTINT<14>, SOFTINT<0> (TICK_INT) 3047c478bd9Sstevel@tonic-gate * and SOFTINT<16> (STICK_INT) to indicate 3057c478bd9Sstevel@tonic-gate * that the current level 14 has been serviced. 3067c478bd9Sstevel@tonic-gate */ 3077c478bd9Sstevel@tonic-gate wr_clr_softint((1 << PIL_14) | 3087c478bd9Sstevel@tonic-gate TICK_INT_MASK | STICK_INT_MASK); 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate enable_vec_intr(opstate); 312a1bf6e2eSChristopher Baumbauer - Oracle America - San Diego United States } else if (spl == ipltospl(PIL_15)) { 313a1bf6e2eSChristopher Baumbauer - Oracle America - San Diego United States opstate = disable_vec_intr(); 314a1bf6e2eSChristopher Baumbauer - Oracle America - San Diego United States intr_enqueue_req(PIL_15, cpc_level15_inum); 315a1bf6e2eSChristopher Baumbauer - Oracle America - San Diego United States wr_clr_softint(1 << PIL_15); 316a1bf6e2eSChristopher Baumbauer - Oracle America - San Diego United States enable_vec_intr(opstate); 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* 3217c478bd9Sstevel@tonic-gate * Miscellaneous hardware-specific code to execute after panicstr is set 3227c478bd9Sstevel@tonic-gate * by the panic code: we also print and record PTL1 panic information here. 3237c478bd9Sstevel@tonic-gate */ 3247c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3257c478bd9Sstevel@tonic-gate void 3267c478bd9Sstevel@tonic-gate panic_quiesce_hw(panic_data_t *pdp) 3277c478bd9Sstevel@tonic-gate { 3287c478bd9Sstevel@tonic-gate extern uint_t getpstate(void); 3297c478bd9Sstevel@tonic-gate extern void setpstate(uint_t); 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate #ifdef TRAPTRACE 3327c478bd9Sstevel@tonic-gate /* 3337c478bd9Sstevel@tonic-gate * Turn off TRAPTRACE and save the current %tick value in panic_tick. 3347c478bd9Sstevel@tonic-gate */ 3357c478bd9Sstevel@tonic-gate if (!panic_tick) 3367c478bd9Sstevel@tonic-gate panic_tick = gettick(); 3377c478bd9Sstevel@tonic-gate TRAPTRACE_FREEZE; 3387c478bd9Sstevel@tonic-gate #endif 3397c478bd9Sstevel@tonic-gate /* 3407c478bd9Sstevel@tonic-gate * For Platforms that use CPU signatures, we 3417c478bd9Sstevel@tonic-gate * need to set the signature block to OS, the state to 3427c478bd9Sstevel@tonic-gate * exiting, and the substate to panic for all the processors. 3437c478bd9Sstevel@tonic-gate */ 3447c478bd9Sstevel@tonic-gate CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_PANIC, -1); 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate /* 3477c478bd9Sstevel@tonic-gate * De-activate ECC functions and disable the watchdog timer now that 3487c478bd9Sstevel@tonic-gate * we've made it through the critical part of the panic code. 3497c478bd9Sstevel@tonic-gate */ 3507c478bd9Sstevel@tonic-gate if (watchdog_enable) 3517c478bd9Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate /* 3547c478bd9Sstevel@tonic-gate * Disable further ECC errors from the CPU module and the bus nexus. 3557c478bd9Sstevel@tonic-gate */ 3567c478bd9Sstevel@tonic-gate cpu_disable_errors(); 3577c478bd9Sstevel@tonic-gate (void) bus_func_invoke(BF_TYPE_ERRDIS); 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate /* 3607c478bd9Sstevel@tonic-gate * Redirect all interrupts to the current CPU. 3617c478bd9Sstevel@tonic-gate */ 3627c478bd9Sstevel@tonic-gate intr_redist_all_cpus_shutdown(); 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate /* 3657c478bd9Sstevel@tonic-gate * This call exists solely to support dumps to network 3667c478bd9Sstevel@tonic-gate * devices after sync from OBP. 3677c478bd9Sstevel@tonic-gate * 3687c478bd9Sstevel@tonic-gate * If we came here via the sync callback, then on some 3697c478bd9Sstevel@tonic-gate * platforms, interrupts may have arrived while we were 3707c478bd9Sstevel@tonic-gate * stopped in OBP. OBP will arrange for those interrupts to 3717c478bd9Sstevel@tonic-gate * be redelivered if you say "go", but not if you invoke a 3727c478bd9Sstevel@tonic-gate * client callback like 'sync'. For some dump devices 3737c478bd9Sstevel@tonic-gate * (network swap devices), we need interrupts to be 3747c478bd9Sstevel@tonic-gate * delivered in order to dump, so we have to call the bus 3757c478bd9Sstevel@tonic-gate * nexus driver to reset the interrupt state machines. 3767c478bd9Sstevel@tonic-gate */ 3777c478bd9Sstevel@tonic-gate (void) bus_func_invoke(BF_TYPE_RESINTR); 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate setpstate(getpstate() | PSTATE_IE); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate /* 3837c478bd9Sstevel@tonic-gate * Platforms that use CPU signatures need to set the signature block to OS and 3847c478bd9Sstevel@tonic-gate * the state to exiting for all CPUs. PANIC_CONT indicates that we're about to 3857c478bd9Sstevel@tonic-gate * write the crash dump, which tells the SSP/SMS to begin a timeout routine to 3867c478bd9Sstevel@tonic-gate * reboot the machine if the dump never completes. 3877c478bd9Sstevel@tonic-gate */ 3887c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3897c478bd9Sstevel@tonic-gate void 3907c478bd9Sstevel@tonic-gate panic_dump_hw(int spl) 3917c478bd9Sstevel@tonic-gate { 3927c478bd9Sstevel@tonic-gate CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_DUMP, -1); 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate /* 3967c478bd9Sstevel@tonic-gate * for ptl1_panic 3977c478bd9Sstevel@tonic-gate */ 3987c478bd9Sstevel@tonic-gate void 3997c478bd9Sstevel@tonic-gate ptl1_init_cpu(struct cpu *cpu) 4007c478bd9Sstevel@tonic-gate { 4017c478bd9Sstevel@tonic-gate ptl1_state_t *pstate = &cpu->cpu_m.ptl1_state; 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate /*CONSTCOND*/ 4047c478bd9Sstevel@tonic-gate if (sizeof (struct cpu) + PTL1_SSIZE > CPU_ALLOC_SIZE) { 4057c478bd9Sstevel@tonic-gate panic("ptl1_init_cpu: not enough space left for ptl1_panic " 4061a70ae91Smathue "stack, sizeof (struct cpu) = %lu", sizeof (struct cpu)); 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate pstate->ptl1_stktop = (uintptr_t)cpu + CPU_ALLOC_SIZE; 4107c478bd9Sstevel@tonic-gate cpu_pa[cpu->cpu_id] = va_to_pa(cpu); 4117c478bd9Sstevel@tonic-gate } 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate void 4147c478bd9Sstevel@tonic-gate ptl1_panic_handler(ptl1_state_t *pstate) 4157c478bd9Sstevel@tonic-gate { 4167c478bd9Sstevel@tonic-gate static const char *ptl1_reasons[] = { 4177c478bd9Sstevel@tonic-gate #ifdef PTL1_PANIC_DEBUG 4187c478bd9Sstevel@tonic-gate "trap for debug purpose", /* PTL1_BAD_DEBUG */ 4197c478bd9Sstevel@tonic-gate #else 4207c478bd9Sstevel@tonic-gate "unknown trap", /* PTL1_BAD_DEBUG */ 4217c478bd9Sstevel@tonic-gate #endif 4227c478bd9Sstevel@tonic-gate "register window trap", /* PTL1_BAD_WTRAP */ 4237c478bd9Sstevel@tonic-gate "kernel MMU miss", /* PTL1_BAD_KMISS */ 4247c478bd9Sstevel@tonic-gate "kernel protection fault", /* PTL1_BAD_KPROT_FAULT */ 4257c478bd9Sstevel@tonic-gate "ISM MMU miss", /* PTL1_BAD_ISM */ 4267c478bd9Sstevel@tonic-gate "kernel MMU trap", /* PTL1_BAD_MMUTRAP */ 4277c478bd9Sstevel@tonic-gate "kernel trap handler state", /* PTL1_BAD_TRAP */ 4287c478bd9Sstevel@tonic-gate "floating point trap", /* PTL1_BAD_FPTRAP */ 4297c478bd9Sstevel@tonic-gate #ifdef DEBUG 430b0fc0e77Sgovinda "pointer to intr_vec", /* PTL1_BAD_INTR_VEC */ 4317c478bd9Sstevel@tonic-gate #else 432b0fc0e77Sgovinda "unknown trap", /* PTL1_BAD_INTR_VEC */ 4337c478bd9Sstevel@tonic-gate #endif 4347c478bd9Sstevel@tonic-gate #ifdef TRAPTRACE 4357c478bd9Sstevel@tonic-gate "TRACE_PTR state", /* PTL1_BAD_TRACE_PTR */ 4367c478bd9Sstevel@tonic-gate #else 4377c478bd9Sstevel@tonic-gate "unknown trap", /* PTL1_BAD_TRACE_PTR */ 4387c478bd9Sstevel@tonic-gate #endif 4397c478bd9Sstevel@tonic-gate "stack overflow", /* PTL1_BAD_STACK */ 4407c478bd9Sstevel@tonic-gate "DTrace flags", /* PTL1_BAD_DTRACE_FLAGS */ 4417c478bd9Sstevel@tonic-gate "attempt to steal locked ctx", /* PTL1_BAD_CTX_STEAL */ 4427c478bd9Sstevel@tonic-gate "CPU ECC error loop", /* PTL1_BAD_ECC */ 4438f230a59Sbs21162 "non-kernel context in sys/priv_trap() below or", 4448f230a59Sbs21162 /* PTL1_BAD_CTX */ 4451426d65aSsm142603 "error raising a TSB exception", /* PTL1_BAD_RAISE_TSBEXCP */ 4461426d65aSsm142603 "missing shared TSB" /* PTL1_NO_SCDTSB8K */ 4477c478bd9Sstevel@tonic-gate }; 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate uint_t reason = pstate->ptl1_regs.ptl1_g1; 4507c478bd9Sstevel@tonic-gate uint_t tl = pstate->ptl1_regs.ptl1_trap_regs[0].ptl1_tl; 451843e1988Sjohnlev struct panic_trap_info ti = { 0 }; 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate /* 4547c478bd9Sstevel@tonic-gate * Use trap_info for a place holder to call panic_savetrap() and 4557c478bd9Sstevel@tonic-gate * panic_showtrap() to save and print out ptl1_panic information. 4567c478bd9Sstevel@tonic-gate */ 4577c478bd9Sstevel@tonic-gate if (curthread->t_panic_trap == NULL) 4587c478bd9Sstevel@tonic-gate curthread->t_panic_trap = &ti; 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate if (reason < sizeof (ptl1_reasons) / sizeof (ptl1_reasons[0])) 4617c478bd9Sstevel@tonic-gate panic("bad %s at TL %u", ptl1_reasons[reason], tl); 4627c478bd9Sstevel@tonic-gate else 4637c478bd9Sstevel@tonic-gate panic("ptl1_panic reason 0x%x at TL %u", reason, tl); 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate void 4677c478bd9Sstevel@tonic-gate clear_watchdog_on_exit() 4687c478bd9Sstevel@tonic-gate { 4697c478bd9Sstevel@tonic-gate /* 4707c478bd9Sstevel@tonic-gate * Only shut down an active hardware watchdog timer if the platform 4717c478bd9Sstevel@tonic-gate * has expressed an interest to. 4727c478bd9Sstevel@tonic-gate */ 4737c478bd9Sstevel@tonic-gate if (disable_watchdog_on_exit && watchdog_activated) { 4747c478bd9Sstevel@tonic-gate prom_printf("Debugging requested; hardware watchdog " 4757c478bd9Sstevel@tonic-gate "disabled; reboot to re-enable.\n"); 4767c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "!Debugging requested; hardware watchdog " 4777c478bd9Sstevel@tonic-gate "disabled; reboot to re-enable."); 4787c478bd9Sstevel@tonic-gate mutex_enter(&tod_lock); 4797c478bd9Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 4807c478bd9Sstevel@tonic-gate mutex_exit(&tod_lock); 4817c478bd9Sstevel@tonic-gate } 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate 4843c431bb5Swentaoy /* 4853c431bb5Swentaoy * This null routine is only used by sun4v watchdog timer support. 4863c431bb5Swentaoy */ 4873c431bb5Swentaoy void 4883c431bb5Swentaoy restore_watchdog_on_entry(void) 4893c431bb5Swentaoy { 4903c431bb5Swentaoy } 4913c431bb5Swentaoy 4927c478bd9Sstevel@tonic-gate int 4937c478bd9Sstevel@tonic-gate kdi_watchdog_disable(void) 4947c478bd9Sstevel@tonic-gate { 4957c478bd9Sstevel@tonic-gate if (watchdog_activated) { 4967c478bd9Sstevel@tonic-gate mutex_enter(&tod_lock); 4977c478bd9Sstevel@tonic-gate (void) tod_ops.tod_clear_watchdog_timer(); 4987c478bd9Sstevel@tonic-gate mutex_exit(&tod_lock); 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate return (watchdog_activated); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate void 5057c478bd9Sstevel@tonic-gate kdi_watchdog_restore(void) 5067c478bd9Sstevel@tonic-gate { 5077c478bd9Sstevel@tonic-gate if (watchdog_enable) { 5087c478bd9Sstevel@tonic-gate mutex_enter(&tod_lock); 5097c478bd9Sstevel@tonic-gate (void) tod_ops.tod_set_watchdog_timer(watchdog_timeout_seconds); 5107c478bd9Sstevel@tonic-gate mutex_exit(&tod_lock); 5117c478bd9Sstevel@tonic-gate } 5127c478bd9Sstevel@tonic-gate } 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 5157c478bd9Sstevel@tonic-gate void 5167c478bd9Sstevel@tonic-gate mach_dump_buffer_init(void) 5177c478bd9Sstevel@tonic-gate { 5187c478bd9Sstevel@tonic-gate /* 5197c478bd9Sstevel@tonic-gate * setup dump buffer to store extra crash information 5207c478bd9Sstevel@tonic-gate * not applicable to sun4u 5217c478bd9Sstevel@tonic-gate */ 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate /* 5257c478bd9Sstevel@tonic-gate * xt_sync - wait for previous x-traps to finish 5267c478bd9Sstevel@tonic-gate */ 5277c478bd9Sstevel@tonic-gate void 5287c478bd9Sstevel@tonic-gate xt_sync(cpuset_t cpuset) 5297c478bd9Sstevel@tonic-gate { 5307c478bd9Sstevel@tonic-gate kpreempt_disable(); 5317c478bd9Sstevel@tonic-gate CPUSET_DEL(cpuset, CPU->cpu_id); 5327c478bd9Sstevel@tonic-gate CPUSET_AND(cpuset, cpu_ready_set); 5337c478bd9Sstevel@tonic-gate xt_some(cpuset, (xcfunc_t *)xt_sync_tl1, 0, 0); 5347c478bd9Sstevel@tonic-gate kpreempt_enable(); 5357c478bd9Sstevel@tonic-gate } 5363b890a5bSjb145095 5373b890a5bSjb145095 /* 5383b890a5bSjb145095 * mach_soft_state_init() - dummy routine for sun4v soft state 5393b890a5bSjb145095 */ 5403b890a5bSjb145095 void 5413b890a5bSjb145095 mach_soft_state_init(void) 5423b890a5bSjb145095 {} 543