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