aboutsummaryrefslogtreecommitdiff
path: root/kernel/include/util/debug.h
diff options
context:
space:
mode:
authornthnluu <nate1299@me.com>2024-01-28 21:20:27 -0500
committernthnluu <nate1299@me.com>2024-01-28 21:20:27 -0500
commitc63f340d90800895f007de64b7d2d14624263331 (patch)
tree2c0849fa597dd6da831c8707b6f2603403778d7b /kernel/include/util/debug.h
Created student weenix repository
Diffstat (limited to 'kernel/include/util/debug.h')
-rw-r--r--kernel/include/util/debug.h305
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