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 2022 RackTop Systems, Inc. 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 #include <upanic.h> 36 37 #include <fakekernel.h> 38 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 (void) vsnprintf(panicbuf, sizeof (panicbuf), fmt, adx); 137 debug_enter(panicbuf); 138 139 /* Call libc`upanic() so that mdb ::status works */ 140 upanic(panicbuf, sizeof (panicbuf)); 141 } 142 143 void 144 panic(const char *fmt, ...) 145 { 146 va_list adx; 147 148 va_start(adx, fmt); 149 vpanic(fmt, adx); 150 va_end(adx); 151 } 152 153 void 154 fm_panic(const char *fmt, ...) 155 { 156 va_list adx; 157 158 va_start(adx, fmt); 159 vpanic(fmt, adx); 160 va_end(adx); 161 } 162 163 void 164 vcmn_err(int ce, const char *fmt, va_list adx) 165 { 166 167 if (ce == CE_PANIC) 168 vpanic(fmt, adx); 169 if (ce >= CE_IGNORE) 170 return; 171 172 fakekernel_cprintf(fmt, adx, ce_flags[ce] | SL_CONSOLE, 173 ce_prefix[ce], ce_suffix[ce]); 174 } 175 176 /*PRINTFLIKE2*/ 177 void 178 cmn_err(int ce, const char *fmt, ...) 179 { 180 va_list adx; 181 182 va_start(adx, fmt); 183 vcmn_err(ce, fmt, adx); 184 va_end(adx); 185 } 186 187 /* ARGSUSED */ 188 void 189 debug_enter(char *str) 190 { 191 /* Just a place for a break point. */ 192 } 193 194 int 195 assfail(const char *a, const char *f, int l) 196 { 197 if (!aok) 198 panic("assertion failed: %s, file: %s, line: %d", a, f, l); 199 200 fprintf(stderr, "ASSERTION CAUGHT: %s, file: %s, line: %d\n", a, f, l); 201 202 return (0); 203 } 204 205 void 206 assfail3(const char *a, uintmax_t lv, const char *op, uintmax_t rv, 207 const char *f, int l) 208 { 209 if (!aok) { 210 panic("assertion failed: %s (0x%llx %s 0x%llx), file: %s, " 211 "line: %d", a, (u_longlong_t)lv, op, (u_longlong_t)rv, 212 f, l); 213 } 214 215 fprintf(stderr, "ASSERTION CAUGHT: %s (0x%llx %s 0x%llx), file: %s, " 216 "line: %d\n", a, (u_longlong_t)lv, op, (u_longlong_t)rv, 217 f, l); 218 } 219