Statistics
| Branch: | Revision:

scoutos / prex-0.9.0 / sys / kern / debug.c @ 03e9c04a

History | View | Annotate | Download (4.27 KB)

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
}