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 2017 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright 2017 RackTop Systems.
  26  */
  27 
  28 #include <sys/param.h>
  29 #include <sys/types.h>
  30 #include <sys/varargs.h>
  31 #include <sys/systm.h>
  32 #include <sys/cmn_err.h>
  33 #include <sys/log.h>
  34 
  35 #include <fakekernel.h>
  36 
  37 void    abort(void) __NORETURN;
  38 void    debug_enter(char *);
  39 
  40 char *volatile panicstr;
  41 va_list  panicargs;
  42 char panicbuf[512];
  43 
  44 volatile int aok;
  45 
  46 static const int
  47 ce_flags[CE_IGNORE] = { SL_NOTE, SL_NOTE, SL_WARN, SL_FATAL };
  48 static const char
  49 ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
  50 static const char
  51 ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
  52 
  53 
  54 /*
  55  * This function is just a stub, exported NODIRECT so that
  56  * comsumers like fksmbd can provide their own.
  57  * (One that actually prints the messages.)
  58  *
  59  * It's used by fakekernel_cprintf() below.
  60  * The flags are SL_... from strlog.h
  61  */
  62 /* ARGSUSED */
  63 void
  64 fakekernel_putlog(char *msg, size_t len, int flags)
  65 {
  66 }
  67 
  68 /*
  69  * fakekernel_cprintf() corresponds to os/printf.c:cprintf()
  70  * This formats the message and calls fakekernel_putlog().
  71  * It's exported NODIRECT to allow replacment.
  72  * The flags are SL_... from strlog.h
  73  */
  74 void
  75 fakekernel_cprintf(const char *fmt, va_list adx, int flags,
  76     const char *prefix, const char *suffix)
  77 {
  78         size_t bufsize = LOG_MSGSIZE;
  79         char buf[LOG_MSGSIZE];
  80         char *bufp = buf;
  81         char *msgp, *bufend;
  82         size_t len;
  83 
  84         if (strchr("^!?", fmt[0]) != NULL) {
  85                 if (fmt[0] == '^')
  86                         flags |= SL_CONSONLY;
  87                 else if (fmt[0] == '!')
  88                         flags |= SL_LOGONLY;
  89                 fmt++;
  90         }
  91 
  92         bufend = bufp + bufsize;
  93         msgp = bufp;
  94         msgp += snprintf(msgp, bufend - msgp, "[fake_kernel] ");
  95         msgp += snprintf(msgp, bufend - msgp, prefix);
  96         msgp += vsnprintf(msgp, bufend - msgp, fmt, adx);
  97         msgp += snprintf(msgp, bufend - msgp, suffix);
  98         len = msgp - bufp;
  99 
 100         fakekernel_putlog(bufp, len, flags);
 101 }
 102 
 103 /* ARGSUSED */
 104 void
 105 vzprintf(zoneid_t zoneid, const char *fmt, va_list adx)
 106 {
 107         fakekernel_cprintf(fmt, adx, SL_CONSOLE | SL_NOTE, "", "");
 108 }
 109 
 110 /*PRINTFLIKE2*/
 111 void
 112 zprintf(zoneid_t zoneid, const char *fmt, ...)
 113 {
 114         va_list adx;
 115 
 116         va_start(adx, fmt);
 117         vzprintf(zoneid, fmt, adx);
 118         va_end(adx);
 119 }
 120 
 121 /*
 122  * "User-level crash dump", if you will.
 123  */
 124 void
 125 vpanic(const char *fmt, va_list adx)
 126 {
 127         va_list tmpargs;
 128 
 129         panicstr = (char *)fmt;
 130         va_copy(panicargs, adx);
 131 
 132         va_copy(tmpargs, adx);
 133         fakekernel_cprintf(fmt, tmpargs, SL_FATAL, "fatal: ", "\n");
 134 
 135         /* Call libc`assfail() so that mdb ::status works */
 136         (void) vsnprintf(panicbuf, sizeof (panicbuf), fmt, adx);
 137         debug_enter(panicbuf);
 138         (void) assfail(panicbuf, "(panic)", 0);
 139 
 140         abort();        /* avoid "noreturn" warnings */
 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 }