diff options
Diffstat (limited to 'kernel/include/util/debug.h')
-rw-r--r-- | kernel/include/util/debug.h | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/kernel/include/util/debug.h b/kernel/include/util/debug.h new file mode 100644 index 0000000..7e6eb91 --- /dev/null +++ b/kernel/include/util/debug.h @@ -0,0 +1,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 |