Kernel - Switch to VT7 on kernel panic
[tpg/acess2.git] / KernelLand / Kernel / debug.c
1 /*
2  * AcessOS Microkernel Version
3  * debug.c
4  */
5 #include <acess.h>
6 #include <stdarg.h>
7
8 #define DEBUG_MAX_LINE_LEN      256
9 #define LOCK_DEBUG_OUTPUT       1       // Avoid interleaving of output lines?
10 #define TRACE_TO_KTERM  0       // Send ENTER/DEBUG/LEAVE to debug?
11
12 // === IMPORTS ===
13 extern void     Threads_Dump(void);
14 extern void     Heap_Dump(void);
15 extern void     KernelPanic_SetMode(void);
16 extern void     KernelPanic_PutChar(char Ch);
17 extern void     IPStack_SendDebugText(const char *Text);
18
19 // === PROTOTYPES ===
20 static void     Debug_Putchar(char ch);
21 static void     Debug_Puts(int bUseKTerm, const char *Str);
22 void    Debug_DbgOnlyFmt(const char *format, va_list args);
23 void    Debug_FmtS(int bUseKTerm, const char *format, ...);
24 void    Debug_Fmt(int bUseKTerm, const char *format, va_list args);
25 void    Debug_SetKTerminal(const char *File);
26
27 // === GLOBALS ===
28  int    gDebug_Level = 0;
29  int    giDebug_KTerm = -1;
30  int    gbDebug_IsKPanic = 0;
31 volatile int    gbInPutChar = 0;
32 #if LOCK_DEBUG_OUTPUT
33 tShortSpinlock  glDebug_Lock;
34 #endif
35 // - Disabled because it breaks shit
36  int    gbSendNetworkDebug = 0;
37
38 // === CODE ===
39 static void Debug_Putchar(char ch)
40 {
41         Debug_PutCharDebug(ch);
42         
43         if( gbDebug_IsKPanic )
44                 KernelPanic_PutChar(ch);
45
46         if( gbDebug_IsKPanic < 2 )
47         {
48                 if(gbInPutChar) return ;
49                 gbInPutChar = 1;
50                 if(giDebug_KTerm != -1)
51                         VFS_Write(giDebug_KTerm, 1, &ch);
52                 gbInPutChar = 0;
53         }
54         
55         if( gbSendNetworkDebug )
56         {
57                 char str[2] = {ch, 0};
58                 IPStack_SendDebugText(str);
59         }
60 }
61
62 static void Debug_Puts(int UseKTerm, const char *Str)
63 {
64          int    len = 0;
65         
66         Debug_PutStringDebug(Str);
67         
68         if( gbDebug_IsKPanic )
69         {               
70                 for( len = 0; Str[len]; len ++ )
71                         KernelPanic_PutChar( Str[len] );
72         }
73         else
74                 for( len = 0; Str[len]; len ++ );
75
76         if( gbSendNetworkDebug )
77                 IPStack_SendDebugText(Str);
78
79         // Output to the kernel terminal
80         if( UseKTerm && gbDebug_IsKPanic < 2 && giDebug_KTerm != -1)
81         {
82                 if(gbInPutChar) return ;
83                 gbInPutChar = 1;
84                 VFS_Write(giDebug_KTerm, len, Str);
85                 gbInPutChar = 0;
86         }
87 }
88
89 void Debug_DbgOnlyFmt(const char *format, va_list args)
90 {
91         Debug_Fmt(0, format, args);
92 }
93
94 void Debug_Fmt(int bUseKTerm, const char *format, va_list args)
95 {
96         char    buf[DEBUG_MAX_LINE_LEN];
97 //       int    len;
98         buf[DEBUG_MAX_LINE_LEN-1] = 0;
99         /*len = */vsnprintf(buf, DEBUG_MAX_LINE_LEN-1, format, args);
100         //if( len < DEBUG_MAX_LINE )
101                 // do something
102         Debug_Puts(bUseKTerm, buf);
103         return ;
104 }
105
106 void Debug_FmtS(int bUseKTerm, const char *format, ...)
107 {
108         va_list args;   
109         va_start(args, format);
110         Debug_Fmt(bUseKTerm, format, args);
111         va_end(args);
112 }
113
114 void Debug_KernelPanic(void)
115 {
116         if( !gbDebug_IsKPanic )
117         {
118                 #if LOCK_DEBUG_OUTPUT
119                 SHORTREL(&glDebug_Lock);
120                 #endif
121                 VT_SetTerminal(7);
122         }
123         gbDebug_IsKPanic ++;
124         KernelPanic_SetMode();
125 }
126
127 /**
128  * \fn void LogF(const char *Msg, ...)
129  * \brief Raw debug log (no new line, no prefix)
130  */
131 void LogF(const char *Fmt, ...)
132 {
133         va_list args;
134
135         #if LOCK_DEBUG_OUTPUT
136         SHORTLOCK(&glDebug_Lock);
137         #endif
138         
139         va_start(args, Fmt);
140
141         Debug_Fmt(1, Fmt, args);
142
143         va_end(args);
144         
145         #if LOCK_DEBUG_OUTPUT
146         SHORTREL(&glDebug_Lock);
147         #endif
148 }
149 /**
150  * \fn void Debug(const char *Msg, ...)
151  * \brief Print only to the debug channel (not KTerm)
152  */
153 void Debug(const char *Fmt, ...)
154 {
155         va_list args;
156         
157         #if LOCK_DEBUG_OUTPUT
158         if(!CPU_HAS_LOCK(&glDebug_Lock)) SHORTLOCK(&glDebug_Lock);
159         #endif
160
161         Debug_Puts(0, "Debug: ");
162         va_start(args, Fmt);
163         Debug_DbgOnlyFmt(Fmt, args);
164         va_end(args);
165         Debug_PutCharDebug('\r');
166         Debug_PutCharDebug('\n');
167         #if LOCK_DEBUG_OUTPUT
168         SHORTREL(&glDebug_Lock);
169         #endif
170 }
171
172
173 void LogFV(const char *Fmt, va_list args)
174 {
175         #if LOCK_DEBUG_OUTPUT
176         SHORTLOCK(&glDebug_Lock);
177         #endif
178
179         Debug_Fmt(1, Fmt, args);
180         
181         #if LOCK_DEBUG_OUTPUT
182         SHORTREL(&glDebug_Lock);
183         #endif
184 }
185
186 void LogV(const char *Fmt, va_list args)
187 {
188         #if LOCK_DEBUG_OUTPUT
189         SHORTLOCK(&glDebug_Lock);
190         #endif
191
192         Debug_Puts(1, "Log: ");
193         Debug_Fmt(1, Fmt, args);
194         Debug_Puts(1, "\r\n");
195         
196         #if LOCK_DEBUG_OUTPUT
197         SHORTREL(&glDebug_Lock);
198         #endif
199 }
200
201 /**
202  * \fn void Log(const char *Msg, ...)
203  */
204 void Log(const char *Fmt, ...)
205 {
206         va_list args;
207         va_start(args, Fmt);
208         LogV(Fmt, args);
209         va_end(args);
210 }
211
212 void Warning(const char *Fmt, ...)
213 {
214         va_list args;
215         
216         #if LOCK_DEBUG_OUTPUT
217         SHORTLOCK(&glDebug_Lock);
218         #endif
219         
220         Debug_Puts(1, "Warning: ");
221         va_start(args, Fmt);
222         Debug_Fmt(1, Fmt, args);
223         va_end(args);
224         Debug_Putchar('\r');
225         Debug_Putchar('\n');
226         
227         #if LOCK_DEBUG_OUTPUT
228         SHORTREL(&glDebug_Lock);
229         #endif
230 }
231 void Panic(const char *Fmt, ...)
232 {
233         va_list args;
234         
235         #if LOCK_DEBUG_OUTPUT
236         if( !CPU_HAS_LOCK(&glDebug_Lock) )
237                 SHORTLOCK(&glDebug_Lock);
238         #endif
239         // And never SHORTREL
240         
241         Debug_KernelPanic();
242         
243         Debug_Puts(1, "Panic: ");
244         va_start(args, Fmt);
245         Debug_Fmt(1, Fmt, args);
246         va_end(args);
247         Debug_Putchar('\r');
248         Debug_Putchar('\n');
249
250         Threads_Dump();
251         Heap_Dump();
252
253         for(;;) ;
254 }
255
256 void Debug_SetKTerminal(const char *File)
257 {
258          int    tmp;
259         if(giDebug_KTerm != -1) {
260                 tmp = giDebug_KTerm;
261                 giDebug_KTerm = -1;
262                 VFS_Close(tmp);
263         }
264         tmp = VFS_Open(File, VFS_OPENFLAG_WRITE);
265 //      Log_Log("Debug", "Opened '%s' as 0x%x", File, tmp);
266         giDebug_KTerm = tmp;
267 //      Log_Log("Debug", "Returning to %p", __builtin_return_address(0));
268 }
269
270 void Debug_Enter(const char *FuncName, const char *ArgTypes, ...)
271 {
272         va_list args;
273          int    i;
274          int    pos;
275         tTID    tid = Threads_GetTID();
276          
277         #if LOCK_DEBUG_OUTPUT
278         SHORTLOCK(&glDebug_Lock);
279         #endif
280
281         i = gDebug_Level ++;
282
283         va_start(args, ArgTypes);
284
285         Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
286         while(i--)      Debug_Puts(TRACE_TO_KTERM, " ");
287
288         Debug_Puts(TRACE_TO_KTERM, FuncName);
289         Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
290         Debug_Puts(TRACE_TO_KTERM, ": (");
291
292         while(*ArgTypes)
293         {
294                 pos = strpos(ArgTypes, ' ');
295                 if(pos == -1 || pos > 1) {
296                         if(pos == -1)
297                                 Debug_Puts(TRACE_TO_KTERM, ArgTypes+1);
298                         else {
299                                 Debug_FmtS(TRACE_TO_KTERM, "%.*s", pos-1, ArgTypes+1);
300                         }
301                         Debug_Puts(TRACE_TO_KTERM, "=");
302                 }
303                 switch(*ArgTypes)
304                 {
305                 case 'p':       Debug_FmtS(TRACE_TO_KTERM, "%p", va_arg(args, void*));  break;
306                 case 'P':       Debug_FmtS(TRACE_TO_KTERM, "%P", va_arg(args, tPAddr)); break;
307                 case 's':       Debug_FmtS(TRACE_TO_KTERM, "'%s'", va_arg(args, char*));        break;
308                 case 'i':       Debug_FmtS(TRACE_TO_KTERM, "%i", va_arg(args, int));    break;
309                 case 'u':       Debug_FmtS(TRACE_TO_KTERM, "%u", va_arg(args, Uint));   break;
310                 case 'x':       Debug_FmtS(TRACE_TO_KTERM, "0x%x", va_arg(args, Uint)); break;
311                 case 'b':       Debug_FmtS(TRACE_TO_KTERM, "0b%b", va_arg(args, Uint)); break;
312                 case 'X':       Debug_FmtS(TRACE_TO_KTERM, "0x%llx", va_arg(args, Uint64));     break;  // Extended (64-Bit)
313                 case 'B':       Debug_FmtS(TRACE_TO_KTERM, "0b%llb", va_arg(args, Uint64));     break;  // Extended (64-Bit)
314                 }
315                 if(pos != -1) {
316                         Debug_Puts(TRACE_TO_KTERM, ", ");
317                 }
318
319                 if(pos == -1)   break;
320                 ArgTypes = &ArgTypes[pos+1];
321         }
322
323         va_end(args);
324         Debug_Puts(TRACE_TO_KTERM, ")\r\n");
325         
326         #if LOCK_DEBUG_OUTPUT
327         SHORTREL(&glDebug_Lock);
328         #endif
329 }
330
331 void Debug_Log(const char *FuncName, const char *Fmt, ...)
332 {
333         va_list args;
334          int    i = gDebug_Level;
335         tTID    tid = Threads_GetTID();
336
337         #if LOCK_DEBUG_OUTPUT
338         SHORTLOCK(&glDebug_Lock);
339         #endif
340
341         Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
342         while(i--)      Debug_Puts(TRACE_TO_KTERM, " ");
343
344         Debug_Puts(TRACE_TO_KTERM, FuncName);
345         Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
346         Debug_Puts(TRACE_TO_KTERM, ": ");
347
348         va_start(args, Fmt);
349         Debug_Fmt(TRACE_TO_KTERM, Fmt, args);
350         va_end(args);
351
352         Debug_Puts(TRACE_TO_KTERM, "\r\n");
353         
354         #if LOCK_DEBUG_OUTPUT
355         SHORTREL(&glDebug_Lock);
356         #endif
357 }
358
359 void Debug_Leave(const char *FuncName, char RetType, ...)
360 {
361         va_list args;
362          int    i;
363         tTID    tid = Threads_GetTID();
364
365         #if LOCK_DEBUG_OUTPUT
366         SHORTLOCK(&glDebug_Lock);
367         #endif
368         
369         i = --gDebug_Level;
370
371         va_start(args, RetType);
372
373         if( i == -1 ) {
374                 gDebug_Level = 0;
375                 i = 0;
376         }
377         Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
378         // Indenting
379         while(i--)      Debug_Puts(TRACE_TO_KTERM, " ");
380
381         Debug_Puts(TRACE_TO_KTERM, FuncName);
382         Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
383         Debug_Puts(TRACE_TO_KTERM, ": RETURN");
384
385         // No Return
386         if(RetType == '-') {
387                 Debug_Puts(TRACE_TO_KTERM, "\r\n");
388                 #if LOCK_DEBUG_OUTPUT
389                 SHORTREL(&glDebug_Lock);
390                 #endif
391                 return;
392         }
393
394         switch(RetType)
395         {
396         case 'n':       Debug_Puts(TRACE_TO_KTERM, " NULL");    break;
397         case 'p':       Debug_Fmt(TRACE_TO_KTERM, " %p", args); break;
398         case 'P':       Debug_Fmt(TRACE_TO_KTERM, " %P", args); break;  // PAddr
399         case 's':       Debug_Fmt(TRACE_TO_KTERM, " '%s'", args);       break;
400         case 'i':       Debug_Fmt(TRACE_TO_KTERM, " %i", args); break;
401         case 'u':       Debug_Fmt(TRACE_TO_KTERM, " %u", args); break;
402         case 'x':       Debug_Fmt(TRACE_TO_KTERM, " 0x%x", args);       break;
403         // Extended (64-Bit)
404         case 'X':       Debug_Fmt(TRACE_TO_KTERM, " 0x%llx", args);     break;
405         }
406         Debug_Puts(TRACE_TO_KTERM, "\r\n");
407
408         va_end(args);
409         
410         #if LOCK_DEBUG_OUTPUT
411         SHORTREL(&glDebug_Lock);
412         #endif
413 }
414
415 void Debug_HexDump(const char *Header, const void *Data, size_t Length)
416 {
417         const Uint8     *cdat = Data;
418         Uint    pos = 0;
419         LogF("%014lli ", now());
420         Debug_Puts(1, Header);
421         LogF(" (Hexdump of %p)\r\n", Data);
422
423         #define CH(n)   ((' '<=cdat[(n)]&&cdat[(n)]<0x7F) ? cdat[(n)] : '.')
424
425         while(Length >= 16)
426         {
427                 LogF("%014lli Log: %04x:"
428                         " %02x %02x %02x %02x %02x %02x %02x %02x"
429                         " %02x %02x %02x %02x %02x %02x %02x %02x"
430                         "  %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c\r\n",
431                         now(),
432                         pos,
433                         cdat[ 0], cdat[ 1], cdat[ 2], cdat[ 3], cdat[ 4], cdat[ 5], cdat[ 6], cdat[ 7],
434                         cdat[ 8], cdat[ 9], cdat[10], cdat[11], cdat[12], cdat[13], cdat[14], cdat[15],
435                         CH(0),  CH(1),  CH(2),  CH(3),  CH(4),  CH(5),  CH(6),  CH(7),
436                         CH(8),  CH(9),  CH(10), CH(11), CH(12), CH(13), CH(14), CH(15)
437                         );
438                 Length -= 16;
439                 cdat += 16;
440                 pos += 16;
441         }
442
443         {
444                  int    i ;
445                 LogF("%014lli Log: %04x: ", now(), pos);
446                 for(i = 0; i < Length; i ++)
447                 {
448                         LogF("%02x ", cdat[i]);
449                 }
450                 for( ; i < 16; i ++)    LogF("   ");
451                 LogF(" ");
452                 for(i = 0; i < Length; i ++)
453                 {
454                         if( i == 8 )    LogF(" ");
455                         LogF("%c", CH(i));
456                 }
457         
458                 Debug_Putchar('\r');
459                 Debug_Putchar('\n');
460         }
461 }
462
463 // --- EXPORTS ---
464 EXPORT(Debug);
465 EXPORT(Log);
466 EXPORT(Warning);
467 EXPORT(Debug_Enter);
468 EXPORT(Debug_Log);
469 EXPORT(Debug_Leave);

UCC git Repository :: git.ucc.asn.au