1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/reboot.h> 29 #include <sys/systm.h> 30 #include <sys/archsystm.h> 31 #include <sys/machsystm.h> 32 #include <sys/promif.h> 33 #include <sys/promimpl.h> 34 #include <sys/prom_plat.h> 35 #include <sys/cpu_sgnblk_defs.h> 36 #include <sys/ivintr.h> 37 #include <sys/kdi.h> 38 #include <sys/kdi_machimpl.h> 39 #include <sys/callb.h> 40 #include <sys/wdt.h> 41 42 #ifdef TRAPTRACE 43 #include <sys/traptrace.h> 44 #endif /* TRAPTRACE */ 45 46 extern void audit_enterprom(); 47 extern void audit_exitprom(); 48 49 /* 50 * Platforms that use CPU signatures need to set cpu_sgn_func 51 * to point to a platform specific function. This needs to 52 * be done in set_platform_defaults() within the platmod. 53 */ 54 void (*cpu_sgn_func)(ushort_t, uchar_t, uchar_t, int) = NULL; 55 56 /* 57 * abort_seq_handler required by sysctrl. 58 */ 59 void debug_enter(char *); 60 void (*abort_seq_handler)(char *) = debug_enter; 61 62 /* 63 * Platform tunable to disable the h/w watchdog timer. 64 */ 65 extern void clear_watchdog_on_exit(void); 66 67 /* 68 * On sun4u platform, abort_sequence_enter() can be called at high PIL 69 * and we can't afford to acquire any adaptive mutex or use any 70 * condition variables as we are not allowed to sleep while running 71 * on interrupt stack. We work around this problem by posting a level 72 * 10 soft interrupt and then invoking the "abort_seq_handler" within 73 * that soft interrupt context. 74 * 75 * This has the side effect of not allowing us to drop into debugger 76 * when the kernel is stuck at high PIL (PIL > 10). It's better to 77 * be able to break into a hung system even if it means crashing the 78 * system. If a user presses L1-A more than once within a 15 seconds 79 * window, and the previous L1-A soft interrupt is still pending, then 80 * we directly invoke the abort_sequence_enter. 81 * 82 * Since the "msg" argument passed to abort_sequence_enter can refer 83 * to a message anywhere in memory, including stack, it's copied into 84 * abort_seq_msgbuf buffer for processing by the soft interrupt. 85 */ 86 87 #define ABORT_SEQ_MSGBUFSZ 256 88 #define FORCE_ABORT_SEQ_INTERVAL ((hrtime_t)15 * NANOSEC) 89 90 static kmutex_t abort_seq_lock; 91 static uint64_t abort_seq_inum; /* abort seq softintr # */ 92 static hrtime_t abort_seq_tstamp; /* hrtime of last abort seq */ 93 static size_t abort_seq_msglen; /* abort seq message length */ 94 static char abort_seq_msgbuf[ABORT_SEQ_MSGBUFSZ]; 95 96 /*ARGSUSED0*/ 97 static uint_t 98 abort_seq_softintr(caddr_t arg) 99 { 100 char *msg; 101 char msgbuf[ABORT_SEQ_MSGBUFSZ]; 102 103 mutex_enter(&abort_seq_lock); 104 if (abort_enable != 0 && abort_seq_tstamp != 0LL) { 105 if (abort_seq_msglen > 0) { 106 bcopy(abort_seq_msgbuf, msgbuf, abort_seq_msglen); 107 msg = msgbuf; 108 } else 109 msg = NULL; 110 abort_seq_tstamp = 0LL; 111 mutex_exit(&abort_seq_lock); 112 if (audit_active) 113 audit_enterprom(1); 114 (*abort_seq_handler)(msg); 115 if (audit_active) 116 audit_exitprom(1); 117 } else { 118 mutex_exit(&abort_seq_lock); 119 if (audit_active) 120 audit_enterprom(0); 121 } 122 return (1); 123 } 124 125 void 126 abort_sequence_init(void) 127 { 128 mutex_init(&abort_seq_lock, NULL, MUTEX_SPIN, (void *)PIL_12); 129 abort_seq_tstamp = 0LL; 130 if (abort_seq_inum == 0) 131 abort_seq_inum = add_softintr(LOCK_LEVEL, 132 (softintrfunc)abort_seq_softintr, NULL, SOFTINT_ST); 133 } 134 135 /* 136 * Machine dependent abort sequence handling 137 */ 138 void 139 abort_sequence_enter(char *msg) 140 { 141 int s, on_intr; 142 size_t msglen; 143 hrtime_t tstamp; 144 145 if (abort_enable != 0) { 146 s = splhi(); 147 on_intr = CPU_ON_INTR(CPU) || (spltoipl(s) > LOCK_LEVEL); 148 splx(s); 149 150 tstamp = gethrtime(); 151 mutex_enter(&abort_seq_lock); 152 153 /* 154 * If we are on an interrupt stack and/or running at 155 * PIL > LOCK_LEVEL, then we post a softint and invoke 156 * abort_seq_handler from there as we can't afford to 157 * acquire any adaptive mutex here. However, if we 158 * already have a pending softint, which was posted 159 * within FORCE_ABORT_SEQ_INTERVAL duration, then we 160 * bypass softint approach as our softint may be blocked 161 * and the user really wants to drop into the debugger. 162 */ 163 if (on_intr && abort_seq_inum != 0 && 164 (abort_seq_tstamp == 0LL || tstamp > 165 (abort_seq_tstamp + FORCE_ABORT_SEQ_INTERVAL))) { 166 abort_seq_tstamp = tstamp; 167 if (msg != NULL) { 168 msglen = strlen(msg); 169 if (msglen >= ABORT_SEQ_MSGBUFSZ) 170 msglen = ABORT_SEQ_MSGBUFSZ - 1; 171 bcopy(msg, abort_seq_msgbuf, msglen); 172 abort_seq_msgbuf[msglen] = '\0'; 173 abort_seq_msglen = msglen + 1; 174 } else 175 abort_seq_msglen = 0; 176 mutex_exit(&abort_seq_lock); 177 setsoftint(abort_seq_inum); 178 } else { 179 /* 180 * Ignore any pending abort sequence softint 181 * as we are invoking the abort_seq_handler 182 * here. 183 */ 184 abort_seq_tstamp = 0LL; 185 mutex_exit(&abort_seq_lock); 186 if (!on_intr && audit_active) 187 audit_enterprom(1); 188 (*abort_seq_handler)(msg); 189 if (!on_intr && audit_active) 190 audit_exitprom(1); 191 } 192 } else { 193 if (audit_active) 194 audit_enterprom(0); 195 } 196 } 197 198 /* 199 * Enter debugger. Called when the user types L1-A or break or whenever 200 * code wants to enter the debugger and possibly resume later. 201 * If the debugger isn't present, enter the PROM monitor. 202 * 203 * If console is a framebuffer which is powered off, it will be powered up 204 * before jumping to the debugger. If we are called above lock level, a 205 * softint is triggered to reenter this code and allow the fb to be powered 206 * up as in the less than lock level case. If this code is entered at greater 207 * than lock level and the fb is not already powered up, the msg argument 208 * will not be displayed. 209 */ 210 void 211 debug_enter(char *msg) 212 { 213 label_t old_pcb; 214 int s; 215 extern void pm_cfb_powerup(void); 216 extern void pm_cfb_rele(void); 217 extern void pm_cfb_trigger(void); 218 extern int pm_cfb_check_and_hold(void); 219 220 /* 221 * For platforms that use CPU signatures, update the signature 222 * to indicate that we are entering the debugger if we are in 223 * the middle of a panic flow. 224 */ 225 if (panicstr) 226 CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_DEBUG, -1); 227 228 if (!panicstr) 229 (void) callb_execute_class(CB_CL_ENTER_DEBUGGER, 0); 230 231 if (pm_cfb_check_and_hold()) 232 if (getpil() > LOCK_LEVEL) { 233 pm_cfb_trigger(); 234 return; 235 } else 236 pm_cfb_powerup(); 237 if (msg) 238 prom_printf("%s\n", msg); 239 240 clear_watchdog_on_exit(); 241 242 if ((s = getpil()) < ipltospl(12)) 243 s = splzs(); 244 245 old_pcb = curthread->t_pcb; 246 (void) setjmp(&curthread->t_pcb); 247 248 if (boothowto & RB_DEBUG) 249 kmdb_enter(); 250 else 251 prom_enter_mon(); 252 253 restore_watchdog_on_entry(); 254 255 curthread->t_pcb = old_pcb; 256 splx(s); 257 pm_cfb_rele(); 258 259 if (!panicstr) 260 (void) callb_execute_class(CB_CL_ENTER_DEBUGGER, 1); 261 262 if (panicstr) 263 CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_PANIC_CONT, -1); 264 } 265 266 /* 267 * Halt the machine and return to the monitor 268 */ 269 void 270 halt(char *s) 271 { 272 flush_windows(); 273 stop_other_cpus(); /* send stop signal to other CPUs */ 274 275 if (s) 276 prom_printf("(%s) ", s); 277 278 /* 279 * For Platforms that use CPU signatures, we 280 * need to set the signature block to OS and 281 * the state to exiting for all the processors. 282 */ 283 CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_HALT, -1); 284 prom_exit_to_mon(); 285 /*NOTREACHED*/ 286 } 287 288 /* 289 * Halt the machine and power off the system. 290 */ 291 void 292 power_down(const char *s) 293 { 294 flush_windows(); 295 stop_other_cpus(); /* send stop signal to other CPUs */ 296 297 if (s != NULL) 298 prom_printf("(%s) ", s); 299 300 /* 301 * For platforms that use CPU signatures, we need to set up the 302 * signature blocks to indicate that we have an environmental 303 * interrupt request to power down, and then exit to the prom monitor. 304 */ 305 CPU_SIGNATURE(OS_SIG, SIGST_EXIT, SIGSUBST_ENVIRON, -1); 306 prom_power_off(); 307 /* 308 * If here is reached, for some reason prom's power-off command failed. 309 * Prom should have already printed out error messages. Exit to 310 * firmware. 311 */ 312 prom_exit_to_mon(); 313 /*NOTREACHED*/ 314 } 315 316 void 317 do_shutdown(void) 318 { 319 proc_t *initpp; 320 321 /* 322 * If we're still booting and init(1) isn't set up yet, simply halt. 323 */ 324 mutex_enter(&pidlock); 325 initpp = prfind(P_INITPID); 326 mutex_exit(&pidlock); 327 if (initpp == NULL) { 328 extern void halt(char *); 329 prom_power_off(); 330 halt("Power off the System"); /* just in case */ 331 } 332 333 /* 334 * else, graceful shutdown with inittab and all getting involved 335 */ 336 psignal(initpp, SIGPWR); 337 } 338