From f05a1d3310be98e9b633f6b50900a3a940a8bf18 Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Wed, 8 Feb 2023 22:32:01 -0800 Subject: [PATCH] [kernel] Revive the debugcon logger as a kernel thread The debugcon logger is now separate from logger::output, and is instead a kernel-internal thread that watches for logs and prints them to the deubcon device. --- assets/build/base.yaml | 2 + configure | 1 + scripts/bonnibel/module.py | 4 +- scripts/bonnibel/project.py | 1 + src/kernel/debugcon.cpp | 66 +++++++++++++++++++++++++++++++ src/kernel/debugcon.h | 30 ++++++++++++++ src/kernel/kernel.module | 3 ++ src/kernel/kernel_main.cpp | 6 ++- src/kernel/logger.cpp | 2 +- src/kernel/scheduler.cpp | 8 ++-- src/libraries/util/util/counted.h | 10 +++++ 11 files changed, 124 insertions(+), 9 deletions(-) create mode 100644 src/kernel/debugcon.cpp create mode 100644 src/kernel/debugcon.h diff --git a/assets/build/base.yaml b/assets/build/base.yaml index 36fd0e1..114c4fc 100644 --- a/assets/build/base.yaml +++ b/assets/build/base.yaml @@ -13,6 +13,8 @@ variables: "-fcolor-diagnostics", "-U__STDCPP_THREADS__", "-D_LIBCPP_HAS_NO_THREADS", + "-D__jsix_config=${build_config}", + "-D__jsix_config_${build_config}", "-DVERSION_MAJOR=${version_major}", "-DVERSION_MINOR=${version_minor}", "-DVERSION_PATCH=${version_patch}", diff --git a/configure b/configure index a428a6c..117cb92 100755 --- a/configure +++ b/configure @@ -35,6 +35,7 @@ def generate(output, config, manifest): "source_root": root, "build_root": output, "module_root": path, + "config": config, } code = compile(open(modfile, 'r').read(), modfile, "exec") diff --git a/scripts/bonnibel/module.py b/scripts/bonnibel/module.py index 494e3e1..9b3da4f 100644 --- a/scripts/bonnibel/module.py +++ b/scripts/bonnibel/module.py @@ -274,8 +274,8 @@ class Module: build.default(dump) def add_input(self, path, **kwargs): - from .source import Source - s = Source(self.root, path, **kwargs) + from .source import make_source + s = make_source(self.root, path, **kwargs) self.sources.append(s) return s.outputs diff --git a/scripts/bonnibel/project.py b/scripts/bonnibel/project.py index a4d8d70..d7c0a2d 100644 --- a/scripts/bonnibel/project.py +++ b/scripts/bonnibel/project.py @@ -28,6 +28,7 @@ class Project: build.variable("ninja_required_version", "1.3") build.variable("build_root", output) build.variable("source_root", root) + build.variable("build_config", config) build.newline() build.include(root / "assets/build/rules.ninja") diff --git a/src/kernel/debugcon.cpp b/src/kernel/debugcon.cpp new file mode 100644 index 0000000..4660e03 --- /dev/null +++ b/src/kernel/debugcon.cpp @@ -0,0 +1,66 @@ +#include + +#include "debugcon.h" +#include "interrupts.h" +#include "logger.h" + +namespace debugcon { + +namespace { + const char *level_names[] = {"", "fatal", "error", "warn", "info", "verbose", "spam"}; + const char *area_names[] = { +#define LOG(name, lvl) #name , +#include +#undef LOG + nullptr + }; + + inline void debug_out(const char *msg, size_t size) { + asm ( "rep outsb;" :: "c"(size), "d"(port), "S"(msg) ); + } + + inline void debug_newline() { + static const char *newline = "\r\n"; + asm ( "rep outsb;" :: "c"(2), "d"(port), "S"(newline) ); + } +} // anon namespace + +void +output(logs area, log::level level, const char *message, size_t mlen) +{ + char buffer [256]; + size_t dlen = util::format({buffer, sizeof(buffer)}, "%7s %7s| ", + area_names[static_cast(area)], + level_names[static_cast(level)]); + debug_out(buffer, dlen); + + debug_out(message, mlen); + debug_newline(); +} + +void +logger_task() +{ + using entry = log::logger::entry; + + uint64_t seen = 0; + size_t buf_size = 128; + uint8_t *buf = new uint8_t [buf_size]; + entry *header = reinterpret_cast(buf); + + while (true) { + size_t size = g_logger.get_entry(seen, buf, buf_size); + if (size > buf_size) { + delete [] buf; + buf_size *= 2; + buf = new uint8_t [buf_size]; + header = reinterpret_cast(buf); + continue; + } + + output(header->area, header->severity, header->message, size - sizeof(entry)); + seen = header->id; + } +} + +} // namespace debugcon diff --git a/src/kernel/debugcon.h b/src/kernel/debugcon.h new file mode 100644 index 0000000..3c2cd0f --- /dev/null +++ b/src/kernel/debugcon.h @@ -0,0 +1,30 @@ +#pragma once +/// \file debugcon.h +/// Kernel debugcon log output process + +#include "scheduler.h" + +namespace debugcon { + +static constexpr bool enable = +#ifdef __jsix_config_debug + true; +#else + false; +#endif + +static constexpr uint16_t port = 0x6600; + +void logger_task(); + +inline void +init_logger() +{ + if constexpr (enable) { + static constexpr uint8_t pri = scheduler::max_priority - 1; + scheduler &s = scheduler::get(); + s.create_kernel_task(logger_task, pri, true); + } +} + +} // namespace debugcon diff --git a/src/kernel/kernel.module b/src/kernel/kernel.module index 57f2f4f..0a013a3 100644 --- a/src/kernel/kernel.module +++ b/src/kernel/kernel.module @@ -69,6 +69,9 @@ kernel = module("kernel", "wait_queue.cpp", ]) +if config == "debug": + kernel.add_input("debugcon.cpp") + from glob import glob from os.path import join diff --git a/src/kernel/kernel_main.cpp b/src/kernel/kernel_main.cpp index f35a0fb..6c62603 100644 --- a/src/kernel/kernel_main.cpp +++ b/src/kernel/kernel_main.cpp @@ -8,6 +8,7 @@ #include "assert.h" #include "capabilities.h" #include "cpu.h" +#include "debugcon.h" #include "device_manager.h" #include "interrupts.h" #include "logger.h" @@ -50,7 +51,6 @@ kernel_main(bootproto::args *args) disable_legacy_pic(); - bsp_late_init(); using bootproto::boot_flags; @@ -71,6 +71,10 @@ kernel_main(bootproto::args *args) scheduler *sched = new scheduler {g_num_cpus}; smp::ready(); + // Initialize the debug console logger (does nothing if not built + // in debug mode) + debugcon::init_logger(); + // Load the init server load_init_server(args->init, args->init_modules); diff --git a/src/kernel/logger.cpp b/src/kernel/logger.cpp index 6d7e8fc..ce9f462 100644 --- a/src/kernel/logger.cpp +++ b/src/kernel/logger.cpp @@ -61,7 +61,7 @@ logger::output(level severity, logs area, const char *fmt, va_list args) char buffer[buffer_len]; entry *header = reinterpret_cast(buffer); - size_t size = sizeof(buffer); + size_t size = sizeof(entry); size += util::vformat({header->message, message_len}, fmt, args); util::scoped_lock lock {m_lock}; diff --git a/src/kernel/scheduler.cpp b/src/kernel/scheduler.cpp index f07b968..d52a77a 100644 --- a/src/kernel/scheduler.cpp +++ b/src/kernel/scheduler.cpp @@ -67,7 +67,8 @@ inline T * push(uintptr_t &rsp, size_t size = sizeof(T)) { void scheduler::create_kernel_task(void (*task)(), uint8_t priority, bool constant) { - thread *th = process::kernel_process().create_thread(0, priority); + process &kp = process::kernel_process(); + thread *th = kp.create_thread(0, priority); auto *tcb = th->tcb(); th->add_thunk_kernel(reinterpret_cast(task)); @@ -78,10 +79,7 @@ scheduler::create_kernel_task(void (*task)(), uint8_t priority, bool constant) th->set_state(thread::state::ready); - log::verbose(logs::task, "Creating kernel task: thread %llx pri %d", th->koid(), tcb->priority); - log::verbose(logs::task, " RSP0 %016lx", tcb->rsp0); - log::verbose(logs::task, " RSP %016lx", tcb->rsp); - log::verbose(logs::task, " PML4 %016lx", tcb->pml4); + log::verbose(logs::task, "Spawned new kernel task <%02lx:%02lx>", kp.obj_id(), th->obj_id()); } uint32_t diff --git a/src/libraries/util/util/counted.h b/src/libraries/util/util/counted.h index 948e81d..b6053e3 100644 --- a/src/libraries/util/util/counted.h +++ b/src/libraries/util/util/counted.h @@ -157,4 +157,14 @@ const T * read(const_buffer &b) { return p; } +template +T * at(buffer &b, size_t i) { + return reinterpret_cast(util::offset_pointer(b.pointer, i)); +} + +template +const T * at(const_buffer &b, size_t i) { + return reinterpret_cast(util::offset_pointer(b.pointer, i)); +} + } // namespace util