Prex Home / Browse Source - Prex Version: 0.9.0

root/sys/kern/debug.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. printf
  2. assert
  3. panic
  4. getlog
  5. dbgctl

   1 /*-
   2  * Copyright (c) 2005-2009, Kohsuke Ohtani
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. Neither the name of the author nor the names of any co-contributors
  14  *    may be used to endorse or promote products derived from this software
  15  *    without specific prior written permission.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 
  30 /*
  31  * debug.c - kernel debug services
  32  */
  33 
  34 #include <kernel.h>
  35 #include <task.h>
  36 #include <thread.h>
  37 #include <sched.h>
  38 #include <hal.h>
  39 #include <sys/dbgctl.h>
  40 
  41 typedef void (*diagfn_t)(char *);
  42 typedef void (*abtfn_t)(void);
  43 
  44 static abtfn_t  db_abort = &machine_abort;      /* abort handler */
  45 static diagfn_t db_puts = &diag_puts;           /* function to print string */
  46 static char     db_msg[DBGMSGSZ];               /* debug message string */
  47 
  48 static char     log_buf[LOGBUFSZ];              /* log buffer */
  49 static u_long   log_head;                       /* index for log head */
  50 static u_long   log_tail;                       /* iundex for log tail */
  51 static u_long   log_len;                        /* length of log */
  52 
  53 #define LOGINDEX(x)     ((x) & (LOGBUFSZ - 1))
  54 
  55 /*
  56  * Scaled down version of C Library printf.
  57  * Only %s %u %d %c %x and zero pad flag are recognized.
  58  * Printf should not be used for chit-chat.
  59  */
  60 void
  61 printf(const char *fmt, ...)
  62 {
  63         va_list args;
  64         int i, s;
  65         char c;
  66 
  67         s = splhigh();
  68         va_start(args, fmt);
  69         vsprintf(db_msg, fmt, args);
  70 
  71         (*db_puts)(db_msg);
  72 
  73         /*
  74          * Record to log buffer.
  75          */
  76         for (i = 0; i < DBGMSGSZ; i++) {
  77                 c = db_msg[i];
  78                 if (c == '\0')
  79                         break;
  80                 log_buf[LOGINDEX(log_tail)] = c;
  81                 log_tail++;
  82                 if (log_len < LOGBUFSZ)
  83                         log_len++;
  84                 else
  85                         log_head = log_tail - LOGBUFSZ;
  86         }
  87         va_end(args);
  88         splx(s);
  89 }
  90 
  91 /*
  92  * Kernel assertion.
  93  */
  94 void
  95 assert(const char *file, int line, const char *exp)
  96 {
  97 
  98         printf("Assertion failed: %s line:%d '%s'\n", file, line, exp);
  99 
 100         (*db_abort)();
 101         /* NOTREACHED */
 102 }
 103 
 104 /*
 105  * Kernel panic.
 106  */
 107 void
 108 panic(const char *msg)
 109 {
 110 
 111         printf("Kernel panic: %s\n", msg);
 112 
 113         (*db_abort)();
 114         /* NOTREACHED */
 115 }
 116 
 117 /*
 118  * Copy log to the user's buffer.
 119  */
 120 static int
 121 getlog(char *buf)
 122 {
 123         u_long cnt, len, i;
 124         int s, error = 0;
 125         char c;
 126 
 127         s = splhigh();
 128         i = log_head;
 129         len = log_len;
 130         if (len >= LOGBUFSZ) {
 131                 /*
 132                  * Overrun found. Discard broken message.
 133                  */
 134                 while (len > 0 && log_buf[LOGINDEX(i)] != '\n') {
 135                         i++;
 136                         len--;
 137                 }
 138         }
 139         for (cnt = 0; cnt < LOGBUFSZ; cnt++) {
 140                 if (cnt < len)
 141                         c = log_buf[LOGINDEX(i)];
 142                 else
 143                         c = '\0';
 144                 if (copyout(&c, buf, 1)) {
 145                         error = EFAULT;
 146                         break;
 147                 }
 148                 i++;
 149                 buf++;
 150         }
 151         splx(s);
 152         return error;
 153 }
 154 
 155 /*
 156  * Debug control service.
 157  */
 158 int
 159 dbgctl(int cmd, void *data)
 160 {
 161         int error = 0;
 162         size_t size;
 163         task_t task;
 164         struct diag_ops *dops;
 165         struct abort_ops *aops;
 166 
 167         switch (cmd) {
 168         case DBGC_LOGSIZE:
 169                 size = LOGBUFSZ;
 170                 error = copyout(&size, data, sizeof(size));
 171                 break;
 172 
 173         case DBGC_GETLOG:
 174                 error = getlog(data);
 175                 break;
 176 
 177         case DBGC_TRACE:
 178                 task = (task_t)data;
 179                 if (task_valid(task)) {
 180                         task->flags ^= TF_TRACE;
 181                 }
 182                 break;
 183 
 184         case DBGC_DUMPTRAP:
 185                 context_dump(&curthread->ctx);
 186                 break;
 187 
 188         case DBGC_SETDIAG:
 189                 dops = data;
 190                 db_puts = dops->puts;
 191                 break;
 192 
 193         case DBGC_SETABORT:
 194                 aops = data;
 195                 db_abort = aops->abort;
 196                 break;
 197 
 198         default:
 199                 error = EINVAL;
 200                 break;
 201         }
 202         return error;
 203 }

/* [<][>][^][v][top][bottom][index][help] */