root / 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 |
} |