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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright (c) 2012 by Delphix. All rights reserved. 24 * Copyright 2021 Tintri by DDN, Inc. All rights reserved. 25 * Copyright 2017 RackTop Systems. 26 * Copyright (c) 2018, Joyent, Inc. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/types.h> 31 #include <sys/varargs.h> 32 #include <sys/systm.h> 33 #include <sys/cmn_err.h> 34 #include <sys/log.h> 35 36 #include <fakekernel.h> 37 38 void abort(void) __NORETURN; 39 void debug_enter(char *); 40 41 char *volatile panicstr; 42 va_list panicargs; 43 char panicbuf[512]; 44 45 int aok; 46 47 static const int 48 ce_flags[CE_IGNORE] = { SL_NOTE, SL_NOTE, SL_WARN, SL_FATAL }; 49 static const char 50 ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" }; 51 static const char 52 ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" }; 53 54 55 /* 56 * This function is just a stub, exported NODIRECT so that 57 * comsumers like fksmbd can provide their own. 58 * (One that actually prints the messages.) 59 * 60 * It's used by fakekernel_cprintf() below. 61 * The flags are SL_... from strlog.h 62 */ 63 /* ARGSUSED */ 64 void 65 fakekernel_putlog(char *msg, size_t len, int flags) 66 { 67 } 68 69 /* 70 * fakekernel_cprintf() corresponds to os/printf.c:cprintf() 71 * This formats the message and calls fakekernel_putlog(). 72 * It's exported NODIRECT to allow replacment. 73 * The flags are SL_... from strlog.h 74 */ 75 void 76 fakekernel_cprintf(const char *fmt, va_list adx, int flags, 77 const char *prefix, const char *suffix) 78 { 79 size_t bufsize = LOG_MSGSIZE; 80 char buf[LOG_MSGSIZE]; 81 char *bufp = buf; 82 char *msgp, *bufend; 83 size_t len; 84 85 if (strchr("^!?", fmt[0]) != NULL) { 86 if (fmt[0] == '^') 87 flags |= SL_CONSONLY; 88 else if (fmt[0] == '!') 89 flags |= SL_LOGONLY; 90 fmt++; 91 } 92 93 bufend = bufp + bufsize; 94 msgp = bufp; 95 msgp += snprintf(msgp, bufend - msgp, "[fake_kernel] "); 96 msgp += snprintf(msgp, bufend - msgp, prefix); 97 msgp += vsnprintf(msgp, bufend - msgp, fmt, adx); 98 msgp += snprintf(msgp, bufend - msgp, suffix); 99 len = msgp - bufp; 100 101 fakekernel_putlog(bufp, len, flags); 102 } 103 104 /* ARGSUSED */ 105 void 106 vzprintf(zoneid_t zoneid, const char *fmt, va_list adx) 107 { 108 fakekernel_cprintf(fmt, adx, SL_CONSOLE | SL_NOTE, "", ""); 109 } 110 111 /*PRINTFLIKE2*/ 112 void 113 zprintf(zoneid_t zoneid, const char *fmt, ...) 114 { 115 va_list adx; 116 117 va_start(adx, fmt); 118 vzprintf(zoneid, fmt, adx); 119 va_end(adx); 120 } 121 122 /* 123 * "User-level crash dump", if you will. 124 */ 125 void 126 vpanic(const char *fmt, va_list adx) 127 { 128 va_list tmpargs; 129 130 panicstr = (char *)fmt; 131 va_copy(panicargs, adx); 132 133 va_copy(tmpargs, adx); 134 fakekernel_cprintf(fmt, tmpargs, SL_FATAL, "fatal: ", "\n"); 135 136 /* Call libc`assfail() so that mdb ::status works */ 137 (void) vsnprintf(panicbuf, sizeof (panicbuf), fmt, adx); 138 debug_enter(panicbuf); 139 (void) assfail(panicbuf, "(panic)", 0); 140 141 abort(); /* avoid "noreturn" warnings */ 142 } 143 144 void 145 panic(const char *fmt, ...) 146 { 147 va_list adx; 148 149 va_start(adx, fmt); 150 vpanic(fmt, adx); 151 va_end(adx); 152 } 153 154 void 155 fm_panic(const char *fmt, ...) 156 { 157 va_list adx; 158 159 va_start(adx, fmt); 160 vpanic(fmt, adx); 161 va_end(adx); 162 } 163 164 void 165 vcmn_err(int ce, const char *fmt, va_list adx) 166 { 167 168 if (ce == CE_PANIC) 169 vpanic(fmt, adx); 170 if (ce >= CE_IGNORE) 171 return; 172 173 fakekernel_cprintf(fmt, adx, ce_flags[ce] | SL_CONSOLE, 174 ce_prefix[ce], ce_suffix[ce]); 175 } 176 177 /*PRINTFLIKE2*/ 178 void 179 cmn_err(int ce, const char *fmt, ...) 180 { 181 va_list adx; 182 183 va_start(adx, fmt); 184 vcmn_err(ce, fmt, adx); 185 va_end(adx); 186 } 187 188 /* ARGSUSED */ 189 void 190 debug_enter(char *str) 191 { 192 /* Just a place for a break point. */ 193 } 194 195 int 196 assfail(const char *a, const char *f, int l) 197 { 198 if (!aok) 199 panic("assertion failed: %s, file: %s, line: %d", a, f, l); 200 201 fprintf(stderr, "ASSERTION CAUGHT: %s, file: %s, line: %d\n", a, f, l); 202 203 return (0); 204 } 205 206 void 207 assfail3(const char *a, uintmax_t lv, const char *op, uintmax_t rv, 208 const char *f, int l) 209 { 210 if (!aok) { 211 panic("assertion failed: %s (0x%llx %s 0x%llx), file: %s, " 212 "line: %d", a, (u_longlong_t)lv, op, (u_longlong_t)rv, 213 f, l); 214 } 215 216 fprintf(stderr, "ASSERTION CAUGHT: %s (0x%llx %s 0x%llx), file: %s, " 217 "line: %d\n", a, (u_longlong_t)lv, op, (u_longlong_t)rv, 218 f, l); 219 } 220