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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/param.h> 27 #include <sys/types.h> 28 #include <sys/sysmacros.h> 29 #include <sys/inline.h> 30 #include <sys/varargs.h> 31 #include <sys/systm.h> 32 #include <sys/conf.h> 33 #include <sys/cmn_err.h> 34 #include <sys/syslog.h> 35 #include <sys/log.h> 36 #include <sys/proc.h> 37 #include <sys/vnode.h> 38 #include <sys/session.h> 39 #include <sys/stream.h> 40 #include <sys/kmem.h> 41 #include <sys/kobj.h> 42 #include <sys/atomic.h> 43 #include <sys/console.h> 44 #include <sys/cpuvar.h> 45 #include <sys/modctl.h> 46 #include <sys/reboot.h> 47 #include <sys/debug.h> 48 #include <sys/panic.h> 49 #include <sys/spl.h> 50 #include <sys/zone.h> 51 52 /* 53 * In some debugging situations it's useful to log all messages to panicbuf, 54 * which is persistent across reboots (on most platforms). The range 55 * panicbuf[panicbuf_log..PANICBUFSIZE-1] may be used for this purpose. 56 * By default, panicbuf_log == PANICBUFSIZE and no messages are logged. 57 * To enable panicbuf logging, set panicbuf_log to a small value, say 1K; 58 * this will reserve 1K for panic information and 7K for message logging. 59 */ 60 uint32_t panicbuf_log = PANICBUFSIZE; 61 uint32_t panicbuf_index = PANICBUFSIZE; 62 63 static int aask, aok; 64 static int ce_to_sl[CE_IGNORE] = { SL_NOTE, SL_NOTE, SL_WARN, SL_FATAL }; 65 static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; 66 static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; 67 68 static void 69 cprintf(const char *fmt, va_list adx, int sl, const char *prefix, 70 const char *suffix, void *site, int mid, int sid, int level, 71 zoneid_t zoneid) 72 { 73 uint32_t msgid; 74 size_t bufsize = LOG_MSGSIZE; 75 char buf[LOG_MSGSIZE]; 76 char *bufp = buf; 77 char *body, *msgp, *bufend; 78 mblk_t *mp; 79 int s, on_intr; 80 size_t len; 81 82 s = splhi(); 83 on_intr = CPU_ON_INTR(CPU) || 84 (interrupts_unleashed && (spltoipl(s) > LOCK_LEVEL)); 85 splx(s); 86 87 ASSERT(zoneid == GLOBAL_ZONEID || !on_intr); 88 89 STRLOG_MAKE_MSGID(fmt, msgid); 90 91 if (strchr("^!?", fmt[0]) != NULL) { 92 if (fmt[0] == '^') 93 sl |= SL_CONSONLY; 94 else if (fmt[0] == '!' || 95 (prefix[0] == '\0' && !(boothowto & RB_VERBOSE))) 96 sl = (sl & ~(SL_USER | SL_NOTE)) | SL_LOGONLY; 97 fmt++; 98 } 99 100 if ((sl & SL_USER) && (MUTEX_HELD(&pidlock) || on_intr)) { 101 zoneid = getzoneid(); 102 sl = sl & ~(SL_USER | SL_LOGONLY) | SL_CONSOLE; 103 } 104 105 retry: 106 bufend = bufp + bufsize; 107 msgp = bufp; 108 body = msgp += snprintf(msgp, bufend - msgp, 109 "%s: [ID %u FACILITY_AND_PRIORITY] ", 110 mod_containing_pc(site), msgid); 111 msgp += snprintf(msgp, bufend - msgp, prefix); 112 msgp += vsnprintf(msgp, bufend - msgp, fmt, adx); 113 msgp += snprintf(msgp, bufend - msgp, suffix); 114 len = strlen(body); 115 116 if (((sl & SL_CONSONLY) && panicstr) || 117 (zoneid == GLOBAL_ZONEID && log_global.lz_active == 0)) { 118 console_printf("%s", body); 119 goto out; 120 } 121 122 if (msgp - bufp >= bufsize && !on_intr) { 123 ASSERT(bufp == buf); 124 bufsize = msgp - bufp + 1; 125 bufp = kmem_alloc(bufsize, KM_NOSLEEP); 126 if (bufp != NULL) 127 goto retry; 128 bufsize = LOG_MSGSIZE; 129 bufp = buf; 130 } 131 132 mp = log_makemsg(mid, sid, level, sl, LOG_KERN, bufp, 133 MIN(bufsize, msgp - bufp + 1), on_intr); 134 if (mp == NULL) { 135 if ((sl & (SL_CONSOLE | SL_LOGONLY)) == SL_CONSOLE && !on_intr) 136 console_printf("%s", body); 137 goto out; 138 } 139 140 if (sl & SL_USER) { 141 ssize_t resid; 142 sess_t *sp; 143 144 if ((sp = tty_hold()) != NULL) { 145 if (sp->s_vp != NULL) 146 (void) vn_rdwr(UIO_WRITE, sp->s_vp, body, 147 len, 0LL, UIO_SYSSPACE, FAPPEND, 148 (rlim64_t)LOG_HIWAT, kcred, &resid); 149 tty_rele(sp); 150 } 151 } 152 153 if (on_intr && !panicstr) { 154 (void) putq(log_intrq, mp); 155 softcall((void (*)(void *))log_flushq, log_intrq); 156 } else { 157 log_sendmsg(mp, zoneid); 158 } 159 out: 160 if (panicbuf_log + len < PANICBUFSIZE) { 161 uint32_t old, new; 162 do { 163 old = panicbuf_index; 164 new = old + len; 165 if (new >= PANICBUFSIZE) 166 new = panicbuf_log + len; 167 } while (cas32(&panicbuf_index, old, new) != old); 168 bcopy(body, &panicbuf[new - len], len); 169 } 170 if (bufp != buf) 171 kmem_free(bufp, bufsize); 172 } 173 174 void 175 vzprintf(zoneid_t zoneid, const char *fmt, va_list adx) 176 { 177 cprintf(fmt, adx, SL_CONSOLE | SL_NOTE, "", "", caller(), 0, 0, 0, 178 zoneid); 179 } 180 181 void 182 vprintf(const char *fmt, va_list adx) 183 { 184 vzprintf(GLOBAL_ZONEID, fmt, adx); 185 } 186 187 /*PRINTFLIKE1*/ 188 void 189 printf(const char *fmt, ...) 190 { 191 va_list adx; 192 193 va_start(adx, fmt); 194 cprintf(fmt, adx, SL_CONSOLE | SL_NOTE, "", "", caller(), 0, 0, 0, 195 GLOBAL_ZONEID); 196 va_end(adx); 197 } 198 199 /*PRINTFLIKE2*/ 200 void 201 zprintf(zoneid_t zoneid, const char *fmt, ...) 202 { 203 va_list adx; 204 205 va_start(adx, fmt); 206 cprintf(fmt, adx, SL_CONSOLE | SL_NOTE, "", "", caller(), 0, 0, 0, 207 zoneid); 208 va_end(adx); 209 } 210 211 void 212 vuprintf(const char *fmt, va_list adx) 213 { 214 va_list adxcp; 215 va_copy(adxcp, adx); 216 217 /* Message the user tty, if any, and the global zone syslog */ 218 cprintf(fmt, adx, SL_CONSOLE | SL_LOGONLY | SL_USER | SL_NOTE, 219 "", "", caller(), 0, 0, 0, GLOBAL_ZONEID); 220 221 /* Now message the local zone syslog */ 222 if (!INGLOBALZONE(curproc)) 223 cprintf(fmt, adxcp, SL_CONSOLE | SL_LOGONLY | SL_NOTE, 224 "", "", caller(), 0, 0, 0, getzoneid()); 225 226 va_end(adxcp); 227 } 228 229 /*PRINTFLIKE1*/ 230 void 231 uprintf(const char *fmt, ...) 232 { 233 va_list adx; 234 235 va_start(adx, fmt); 236 237 vuprintf(fmt, adx); 238 239 va_end(adx); 240 } 241 242 void 243 vzcmn_err(zoneid_t zoneid, int ce, const char *fmt, va_list adx) 244 { 245 if (ce == CE_PANIC) 246 vpanic(fmt, adx); 247 if ((uint_t)ce < CE_IGNORE) 248 cprintf(fmt, adx, ce_to_sl[ce] | SL_CONSOLE, 249 ce_prefix[ce], ce_suffix[ce], caller(), 0, 0, 0, 250 zoneid); 251 } 252 253 void 254 vcmn_err(int ce, const char *fmt, va_list adx) 255 { 256 vzcmn_err(GLOBAL_ZONEID, ce, fmt, adx); 257 } 258 259 /*PRINTFLIKE2*/ 260 void 261 cmn_err(int ce, const char *fmt, ...) 262 { 263 va_list adx; 264 265 va_start(adx, fmt); 266 if (ce == CE_PANIC) 267 vpanic(fmt, adx); 268 if ((uint_t)ce < CE_IGNORE) 269 cprintf(fmt, adx, ce_to_sl[ce] | SL_CONSOLE, 270 ce_prefix[ce], ce_suffix[ce], caller(), 0, 0, 0, 271 GLOBAL_ZONEID); 272 va_end(adx); 273 } 274 275 /*PRINTFLIKE3*/ 276 void 277 zcmn_err(zoneid_t zoneid, int ce, const char *fmt, ...) 278 { 279 va_list adx; 280 281 va_start(adx, fmt); 282 if (ce == CE_PANIC) 283 vpanic(fmt, adx); 284 if ((uint_t)ce < CE_IGNORE) 285 cprintf(fmt, adx, ce_to_sl[ce] | SL_CONSOLE, ce_prefix[ce], 286 ce_suffix[ce], caller(), 0, 0, 0, zoneid); 287 va_end(adx); 288 } 289 290 int 291 assfail(const char *a, const char *f, int l) 292 { 293 if (aask) { 294 printf("ASSERTION CAUGHT: %s, file: %s, line: %d", a, f, l); 295 debug_enter(NULL); 296 } 297 298 if (!aok && !panicstr) 299 panic("assertion failed: %s, file: %s, line: %d", a, f, l); 300 301 return (0); 302 } 303 304 void 305 assfail3(const char *a, uintmax_t lv, const char *op, uintmax_t rv, 306 const char *f, int l) 307 { 308 if (aask) { 309 printf("ASSERTION CAUGHT: %s (0x%llx %s 0x%llx), file: %s, " 310 "line: %d", a, (u_longlong_t)lv, op, (u_longlong_t)rv, 311 f, l); 312 debug_enter(NULL); 313 } 314 315 if (!aok && !panicstr) 316 panic("assertion failed: %s (0x%llx %s 0x%llx), file: %s, " 317 "line: %d", a, (u_longlong_t)lv, op, (u_longlong_t)rv, 318 f, l); 319 } 320 321 int 322 strlog(short mid, short sid, char level, ushort_t sl, char *fmt, ...) 323 { 324 if (sl & log_global.lz_active) { 325 va_list adx; 326 va_start(adx, fmt); 327 cprintf(fmt, adx, sl, "", "", caller(), mid, sid, level, 328 GLOBAL_ZONEID); 329 va_end(adx); 330 } 331 return (1); 332 } 333 334 int 335 vstrlog(short mid, short sid, char level, ushort_t sl, char *fmt, va_list adx) 336 { 337 if (sl & log_global.lz_active) 338 cprintf(fmt, adx, sl, "", "", caller(), mid, sid, level, 339 GLOBAL_ZONEID); 340 return (1); 341 } 342