1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
|
#pragma once
#include "globals.h"
#include "main/interrupt.h"
#include "mm/page.h"
#include "proc/spinlock.h"
#include "types.h"
#include <main/apic.h>
/* How to create new dbg modes:
*
* 1) Add a new '#define DBG_NAME DBG_MODE(number)' down below. Make sure the
* number you choose is not already being used and is less than 64.
* 2) Add a new entry into the DBG_TAB below. Make sure it is above the entry
* for "all". The first entry should be the name you want to use to
* disable/enable it in the makefile, the second should be the #define'd
* name you gave it in step 1 and the third should be a color from the list
* directly below this comment. Make sure you include the '\' at the end of
* the line with the new entry.
*
*/
/*
* These color definitions are from the ANSI specs.
* Do a web search for ANSI color codes to find out
* more funky shit like this
*/
#define _NORMAL_ "\x1b[0m"
#define _BLACK_ "\x1b[30;47m"
#define _RED_ "\x1b[31;40m"
#define _GREEN_ "\x1b[32;40m"
#define _YELLOW_ "\x1b[33;40m"
#define _BLUE_ "\x1b[34;40m"
#define _MAGENTA_ "\x1b[35;40m"
#define _CYAN_ "\x1b[36;40m"
#define _WHITE_ "\x1b[37;40m"
#define _BRED_ "\x1b[1;31;40m"
#define _BGREEN_ "\x1b[1;32;40m"
#define _BYELLOW_ "\x1b[1;33;40m"
#define _BBLUE_ "\x1b[1;34;40m"
#define _BMAGENTA_ "\x1b[1;35;40m"
#define _BCYAN_ "\x1b[1;36;40m"
#define _BWHITE_ "\x1b[1;37;40m"
#define DBG_MODE(x) (1ULL << (x))
/* These defines list all of the possible debugging
* types. They are flags, so make sure to use the
* DBG_MODE macro to declare new values. */
#define DBG_ALL (~0ULL) /* umm, "verbose" */
#define DBG_CORE DBG_MODE(0) /* core boot code */
#define DBG_MM DBG_MODE(1) /* memory management */
#define DBG_INIT DBG_MODE(2) /* boot/init code */
#define DBG_SCHED DBG_MODE(3) /* swtch, scheduling */
#define DBG_DISK DBG_MODE(4) /* disk driver */
#define DBG_TEMP DBG_MODE(5) /* for resolving temporary problems */
#define DBG_KMALLOC DBG_MODE(6) /* kmalloc, kmem_cache_alloc */
#define DBG_PAGEALLOC DBG_MODE(7) /* page_alloc, etc. */
#define DBG_INTR DBG_MODE(8) /* misc. trap/interrupt */
#define DBG_TERM DBG_MODE(9) /* the terminal device */
#define DBG_FORK DBG_MODE(10) /* fork(2) */
#define DBG_PROC DBG_MODE(11) /* process stuff */
#define DBG_VNREF DBG_MODE(12) /* vnode reference counts */
#define DBG_PFRAME DBG_MODE(13) /* pframe subsys */
#define DBG_ERROR DBG_MODE(14) /* error conditions */
#define DBG_SYSCALL DBG_MODE(15) /* system calls */
#define DBG_FREF DBG_MODE(16) /* file reference counts */
#define DBG_PGTBL DBG_MODE(17) /* page table manipulation */
#define DBG_BRK DBG_MODE(18) /* process break; user memory alloc */
#define DBG_EXEC DBG_MODE(19) /* new process exec */
#define DBG_VFS DBG_MODE(20) /* vfs */
#define DBG_S5FS DBG_MODE(21) /* system V file system */
#define DBG_KB DBG_MODE(22) /* keyboard */
#define DBG_THR DBG_MODE(23) /* thread stuff */
#define DBG_PRINT DBG_MODE(24) /* printdbg.c */
#define DBG_OSYSCALL DBG_MODE(25) /* other system calls */
#define DBG_VM DBG_MODE(28) /* VM */
#define DBG_TEST DBG_MODE(30) /* for testing code */
#define DBG_TESTPASS DBG_MODE(31) /* for testing code */
#define DBG_TESTFAIL DBG_MODE(32) /* for testing code */
#define DBG_MEMDEV DBG_MODE(33) /* For memory devices ("null" and "zero") */
#define DBG_ANON DBG_MODE(34) /* anonymous vm objects */
#define DBG_VMMAP DBG_MODE(35) /* vm area mappings */
#define DBG_ELF DBG_MODE(37) /* elf loader */
#define DBG_USER DBG_MODE(38) /* user land */
#define DBG_DEFAULT DBG_ERROR /* default modes, 0 for none */
/* This defines the name that is used in the
* environment variable to turn on the given
* debugging type, along with the color of the debug type */
/* NOTE that there is an order to these objects - the color chosen for a
* debug statement with multiple DBG specifiers will be the first matching
* result in the table */
/* Note that rearranging the table will affect results, and may be beneficial
* later */
#define DBG_TAB \
/* General */ \
{"error", DBG_ERROR, _BWHITE_}, {"temp", DBG_TEMP, _NORMAL_}, \
{"print", DBG_PRINT, _NORMAL_}, {"test", DBG_TEST, _RED_}, \
{"testpass", DBG_TESTPASS, _GREEN_}, \
{"testfail", DBG_TESTFAIL, _RED_}, /* Kern 1 */ \
{"proc", DBG_PROC, _BLUE_}, {"thr", DBG_THR, _CYAN_}, \
{"sched", DBG_SCHED, _GREEN_}, \
{"init", DBG_INIT, _NORMAL_}, /* Kern 2 */ \
{"term", DBG_TERM, _BMAGENTA_}, {"disk", DBG_DISK, _YELLOW_}, \
{"memdev", DBG_MEMDEV, _BBLUE_}, /* VFS */ \
{"vfs", DBG_VFS, _WHITE_}, {"fref", DBG_FREF, _MAGENTA_}, \
{"vnref", DBG_VNREF, _CYAN_}, /* S5FS */ \
{"s5fs", DBG_S5FS, _BRED_}, \
{"pframe", DBG_PFRAME, _BMAGENTA_}, /* VM */ \
{"anon", DBG_ANON, _WHITE_}, {"vmmap", DBG_VMMAP, _BGREEN_}, \
{"fork", DBG_FORK, _BYELLOW_}, {"brk", DBG_BRK, _YELLOW_}, \
{"exec", DBG_EXEC, _BRED_}, {"elf", DBG_ELF, _BGREEN_}, \
{"pgtbl", DBG_PGTBL, _BBLUE_}, {"osyscall", DBG_OSYSCALL, _BMAGENTA_}, \
{"vm", DBG_VM, _RED_}, /* Syscalls (VFS - VM) */ \
{"syscall", DBG_SYSCALL, _RED_}, /* support code */ \
{"intr", DBG_INTR, _BRED_}, {"kmalloc", DBG_KMALLOC, _MAGENTA_}, \
{"pagealloc", DBG_PAGEALLOC, _WHITE_}, {"kb", DBG_KB, _BLUE_}, \
{"core", DBG_CORE, _GREEN_}, {"mm", DBG_MM, _RED_}, \
{"user", DBG_USER, _BYELLOW_}, \
/* Note this MUST be last or the color code will break */ /* Also note \
that the \
color \
specified \
here is \
effectively \
the \
"default" \
*/ \
{"all", DBG_ALL, _NORMAL_}, \
{ \
NULL, 0, NULL \
}
extern uint64_t dbg_modes;
/* A common interface for functions which provide human-readable information
* about some data structure. Functions implementing this interface should fill
* buf with up to size characters to describe the data passed in as data, then
* return the number of characters writen. If there is not enough space in buf
* to write all information then only size characters will be writen and size
* will be returned. The returned string will be null terminated regardless of
* its length. */
typedef size_t (*dbg_infofunc_t)(const void *data, char *buf, size_t size);
#define DBG_BUFFER_SIZE (PAGE_SIZE)
void dbg_init(void);
void dbg_print(char *fmt, ...) __attribute__((format(printf, 1, 2)));
void dbg_printinfo(dbg_infofunc_t func, const void *data);
const char *dbg_color(uint64_t d_mode);
#if defined(__SMP__) || defined(__KPREEMPT__)
#define DEBUG_ENTER \
uint8_t __ipl = apic_initialized() ? intr_setipl(IPL_HIGH) : IPL_LOW; \
#define DEBUG_EXIT \
if (apic_initialized()) \
intr_setipl(__ipl);
#else
#define DEBUG_ENTER \
do \
{ \
} while (0);
#define DEBUG_EXIT \
do \
{ \
} while (0);
#endif
#ifndef NDEBUG
#define dbg(mode, ...) \
do \
{ \
if (dbg_active(mode)) \
{ \
DEBUG_ENTER \
dbg_print("%s", dbg_color(mode)); \
dbg_print("C%ld P%ld ", curcore.kc_id, \
curproc ? curproc->p_pid : -1L); \
dbg_print("%s:%d %s(): ", __FILE__, __LINE__, __func__); \
dbg_print(__VA_ARGS__); \
dbg_print("%s", _NORMAL_); \
DEBUG_EXIT \
} \
} while (0)
#define dbg_force(mode, ...) \
do \
{ \
DEBUG_ENTER \
dbg_print("%s", dbg_color(mode)); \
dbg_print("C%ld P%ld ", curcore.kc_id, \
curproc ? curproc->p_pid : -1L); \
dbg_print("%s:%d %s(): ", __FILE__, __LINE__, __func__); \
dbg_print(__VA_ARGS__); \
dbg_print("%s", _NORMAL_); \
DEBUG_EXIT \
} while (0)
#define dbgq(mode, ...) \
do \
{ \
if (dbg_active(mode)) \
{ \
DEBUG_ENTER \
dbg_print("%s", dbg_color(mode)); \
dbg_print("C%ld P%ld ", curcore.kc_id, \
curproc ? curproc->p_pid : -1L); \
dbg_print(__VA_ARGS__); \
dbg_print("%s", _NORMAL_); \
DEBUG_EXIT \
} \
} while (0)
#define dbginfo(mode, func, data) \
do \
{ \
if (dbg_active(mode)) \
{ \
DEBUG_ENTER \
dbg_print("%s", dbg_color(mode)); \
dbg_print("C%ld P%ld ", curcore.kc_id, \
curproc ? curproc->p_pid : -1L); \
dbg_printinfo(func, data); \
dbg_print("%s", _NORMAL_); \
DEBUG_EXIT \
} \
} while (0)
#define dbg_active(mode) (dbg_modes & (mode))
void dbg_add_mode(const char *mode);
void dbg_add_modes(const char *modes);
#else
#define dbg(mode, ...)
#define dbgq(mode, ...)
#define dbginfo(mode, func, data)
#define dbg_active(mode) 0
#define dbg_add_mode(mode)
#define dbg_add_modes(modes)
#endif
noreturn void dbg_panic(const char *file, int line, const char *func,
const char *fmt, ...)
__attribute__((format(printf, 4, 5)));
#define panic(...) dbg_panic(__FILE__, __LINE__, __func__, __VA_ARGS__)
#ifndef NDEBUG
#define KASSERT(x) \
do \
{ \
if (!(x)) \
panic("assertion failed: %s", #x); \
} while (0)
#define KASSERT_GENERIC(left, right, comparator, comp_str) \
do \
{ \
int __left = (int)(left); \
int __right = (int)(right); \
if (!comparator(__left, __right)) \
{ \
panic("assertion failed: %s %s %s. Left: %d, Right: %d\n", #left, \
comp_str, #right, __left, __right); \
} \
} while (0)
static long equals(long l, long r)
{
return l == r;
}
static long notequals(long l, long r) { return l != r; }
static long lessthan(long l, long r) { return l < r; }
static long greaterthan(long l, long r) { return l > r; }
static long lessthaneq(long l, long r) { return l <= r; }
static long greaterthaneq(long l, long r) { return l >= r; }
#define KASSERTEQ(l, r) KASSERT_GENERIC(l, r, equals, "==")
#define KASSERTNEQ(l, r) KASSERT_GENERIC(l, r, notequals, "!=")
#define KASSERT_GREATER(l, r) KASSERT_GENERIC(l, r, greaterthan, ">")
#define KASSERT_LESS(l, r) KASSERT_GENERIC(l, r, lessthan, "<")
#define KASSERT_GREQ(l, r) KASSERT_GENERIC(l, r, greaterthaneq, ">=")
#define KASSERT_LESSEQ(l, r) KASSERT_GENERIC(l, r, lessthaneq, "<=")
#else
#define KASSERT(x)
#define KASSERTEQ(l, r)
#define KASSERT_GREATER(l, r)
#define KASSERT_LESS(l, r)
#define KASSERT_GREQ(l, r)
#define KASSERT_LESSEQ(l, r)
#endif
|