Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/util/debug.c need to be fixed.

0001 /*                    The Quest Operating System
0002  *  Copyright (C) 2005-2010  Richard West, Boston University
0003  *
0004  *  This program is free software: you can redistribute it and/or modify
0005  *  it under the terms of the GNU General Public License as published by
0006  *  the Free Software Foundation, either version 3 of the License, or
0007  *  (at your option) any later version.
0008  *
0009  *  This program is distributed in the hope that it will be useful,
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  *  GNU General Public License for more details.
0013  *
0014  *  You should have received a copy of the GNU General Public License
0015  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0016  */
0017 
0018 #include "kernel.h"
0019 #include "util/printf.h"
0020 
0021 #ifndef GDBSTUB_TCP
0022 void putDebugChar (int c)
0023 {
0024   while (!(inb (serial_port1 + 5) & 0x20));    /* check line status register, empty transmitter bit */
0025   outb (c, serial_port1);
0026 }
0027 
0028 int getDebugChar (void)
0029 {
0030   while (!(inb (serial_port1 + 5) & 1));
0031   return inb (serial_port1);
0032 }
0033 #endif
0034 
0035 void
0036 com1_putc (char c)
0037 {
0038 #ifdef COM1_TO_SCREEN
0039   _putchar (c);
0040 #elif !defined(ENABLE_GDBSTUB) || defined(GDBSTUB_TCP)
0041   if (c == '\n') {
0042     /* output CR before NL */
0043     while (!(inb (serial_port1 + 5) & 0x20));  /* check line status register, empty transmitter bit */
0044     outb ('\r', serial_port1);
0045   }
0046 
0047   while (!(inb (serial_port1 + 5) & 0x20));    /* check line status register, empty transmitter bit */
0048   outb (c, serial_port1);
0049 #endif
0050 }
0051 
0052 void
0053 com1_puts (char *p)
0054 {
0055   while (*p)
0056     com1_putc (*p++);
0057 }
0058 
0059 void
0060 com1_putx (uint32 l)
0061 {
0062   int i, li;
0063 
0064   for (i = 7; i >= 0; i--)
0065     if ((li = (l >> (i << 2)) & 0x0F) > 9)
0066       com1_putc ('A' + li - 0x0A);
0067     else
0068       com1_putc ('0' + li);
0069 }
0070 
0071 void
0072 stacktrace (void)
0073 {
0074   uint32 esp, ebp;
0075   extern void com1_putc (char);
0076   extern void com1_puts (char *);
0077   extern void com1_putx (uint32);
0078   asm volatile ("movl %%esp, %0":"=r" (esp));
0079   asm volatile ("movl %%ebp, %0":"=r" (ebp));
0080   com1_printf ("Stacktrace:\n");
0081   while (ebp >= KERN_STK && ebp <= KERN_STK + 0x1000) {
0082     com1_printf ("%0.8X\n", *((uint32 *) (ebp + 4)));
0083     ebp = *((uint32 *) ebp);
0084   }
0085 }
0086 
0087 void
0088 stacktrace_frame (uint esp, uint ebp)
0089 {
0090   uint min = esp & (~0xFFF), max = min + 0x1000;
0091   extern void com1_putc (char);
0092   extern void com1_puts (char *);
0093   extern void com1_putx (uint32);
0094   com1_printf ("Stacktrace:\n");
0095   while (ebp >= min && ebp <= max) {
0096     com1_printf ("%0.8X\n", *((uint32 *) (ebp + 4)));
0097     ebp = *((uint32 *) ebp);
0098   }
0099 }
0100 
0101 static char b64lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
0102 /* 11000000 22221111 33333322 */
0103 /* aabbccdd aabbccdd aabbccdd */
0104 /* 01234567 89012345 67890123 */
0105 union v8 {
0106   struct {
0107     u8 a:2;
0108     u8 b:2;
0109     u8 c:2;
0110     u8 d:2;
0111   };
0112   struct {
0113     u8 ab:4;
0114     u8 cd:4;
0115   };
0116   struct {
0117     u8 _a_:2;
0118     u8 bcd:6;
0119   };
0120   struct {
0121     u8 abc:6;
0122     u8 _d_:2;
0123   };
0124 } __attribute__((packed));
0125 
0126 #define OUT(c) logger_putc(c)
0127 void
0128 base64encode_dump (u8 *str, int n)
0129 {
0130   int i;
0131   for (i=0; i<n; i+=3) {
0132     union v8 *p = (union v8 *)&str[i];
0133     OUT (b64lookup[p[0].bcd]);
0134     if (i+1 < n)
0135       OUT (b64lookup[(p[0].a << 4) | (p[1].cd)]);
0136     else {
0137       OUT (b64lookup[p[0].a << 4]);
0138       OUT ('=');
0139       OUT ('=');
0140       break;
0141     }
0142     if (i+2 < n)
0143       OUT (b64lookup[(p[1].ab << 2) | p[2].d]);
0144     else {
0145       OUT (b64lookup[p[1].ab << 2]);
0146       OUT ('=');
0147       break;
0148     }
0149     OUT (b64lookup[p[2].abc]);
0150   }
0151 }
0152 #undef OUT
0153 
0154 void
0155 dump_page (u8 *addr)
0156 {
0157   logger_printf ("***dump 0x%p\n", addr);
0158   base64encode_dump (addr, 0x1000);
0159   logger_printf ("\n");
0160 }
0161 
0162 static int getc (void)
0163 {
0164   while (!(inb (serial_port1 + 5) & 1));
0165   return inb (serial_port1);
0166 }
0167 
0168 void
0169 crash_debug (char *reason)
0170 {
0171   extern void acpi_reboot (void);
0172   extern bool mp_ACPI_enabled;
0173   char c;
0174   u8 state;
0175 
0176   com1_printf ("Entering crash debug: %s\n", reason);
0177   for (;;) {
0178     com1_printf ("crash> ");
0179     c = getc ();
0180     com1_printf ("\nyou typed '%c' (=%d)\n", c, c);
0181     if (c == '6') {
0182       com1_printf ("REBOOTING...\n");
0183       tsc_delay_usec (100000);
0184       if (mp_ACPI_enabled) acpi_reboot ();
0185 #define KEYBOARD_STATUS_PORT 0x64
0186       while (((state = inb (KEYBOARD_STATUS_PORT)) & 2) != 0);
0187       outb (0xFE, KEYBOARD_STATUS_PORT);
0188     }
0189   }
0190 }
0191 
0192 /*
0193  * Local Variables:
0194  * indent-tabs-mode: nil
0195  * mode: C
0196  * c-file-style: "gnu"
0197  * c-basic-offset: 2
0198  * End:
0199  */
0200 
0201 /* vi: set et sw=2 sts=2: */