From 561e9029a520bdeb7059f9fcfcbafd548091b45a Mon Sep 17 00:00:00 2001 From: "Rowan (OpenClaw)" Date: Sun, 22 Feb 2026 01:54:33 +0100 Subject: [PATCH 1/2] logging: quiet default boot output; reduce QEMU debug spam --- bootloader/src/drivers/manager.rs | 21 +++++++++++++++++++++ kernel/src/config.rs | 17 +++++++++++++---- kernel/src/drivers/usb/xhci/mod.rs | 10 +++++----- startQemu.sh | 5 ++++- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/bootloader/src/drivers/manager.rs b/bootloader/src/drivers/manager.rs index a06d1ca..2680574 100644 --- a/bootloader/src/drivers/manager.rs +++ b/bootloader/src/drivers/manager.rs @@ -133,6 +133,27 @@ impl OutputDriver { /// Write a line to the global output driver /// This is the main function to use for output throughout the codebase pub fn write_line(message: &str) -> bool { + // Keep default boot output high-signal to conserve context. + // Verbose output can be re-enabled by toggling `VERBOSE_OUTPUT`. + if !crate::VERBOSE_OUTPUT { + let trimmed = message.trim_start(); + let noisy_prefixes = [ + "✓ ", + "Collecting ", + "Getting ", + "Setting ", + "Allocating ", + "Copying ", + "Exiting ", + "Entering ", + "Finalizing ", + "Found ", + ]; + if noisy_prefixes.iter().any(|p| trimmed.starts_with(p)) { + return true; + } + } + let driver_ptr = GLOBAL_OUTPUT_DRIVER.load(Ordering::SeqCst); if driver_ptr.is_null() { return false; diff --git a/kernel/src/config.rs b/kernel/src/config.rs index 1b3ba97..bbd6d38 100644 --- a/kernel/src/config.rs +++ b/kernel/src/config.rs @@ -5,14 +5,20 @@ //! configuration in a single place. /// When `true` enable verbose kernel debug output (many debug traces). -pub const VERBOSE_KERNEL_OUTPUT: bool = true; +/// +/// Default is `false` to keep boot logs high-signal and conserve context when +/// iterating with AI tooling. +pub const VERBOSE_KERNEL_OUTPUT: bool = false; /// When `true` the kernel will idle (keep running) after initialization. /// When `false` the kernel will exit QEMU immediately (useful for CI). pub const KERNEL_SHOULD_IDLE: bool = true; /// When `true`, dump the UEFI hardware inventory entries during driver init. -pub const PRINT_HARDWARE_INVENTORY: bool = true; +/// +/// Default is `false` to avoid logspam; use the monitor or enable verbose logs +/// when actively debugging device discovery. +pub const PRINT_HARDWARE_INVENTORY: bool = false; /// When `true`, enable serial output to COM1. pub const ENABLE_SERIAL_OUTPUT: bool = true; @@ -64,8 +70,11 @@ pub const USB_RUN_SW_INT_SELF_TEST: bool = false; use crate::logging::{LogLevel, OutputTarget}; -/// Default log level for modules without specific configuration -pub const DEFAULT_LOG_LEVEL: LogLevel = LogLevel::Trace; +/// Default log level for modules without specific configuration. +/// +/// Keep this relatively quiet by default; enable DEBUG/TRACE via the kernel +/// monitor (`loglevel ...`) or by changing this constant when doing deep bring-up. +pub const DEFAULT_LOG_LEVEL: LogLevel = LogLevel::Info; /// Per-module log level overrides /// diff --git a/kernel/src/drivers/usb/xhci/mod.rs b/kernel/src/drivers/usb/xhci/mod.rs index ed12187..80641e8 100644 --- a/kernel/src/drivers/usb/xhci/mod.rs +++ b/kernel/src/drivers/usb/xhci/mod.rs @@ -2812,7 +2812,7 @@ impl XhciDriver { let mut first_connected = None; for state in &states { - log_info!("xHCI {} port{:02} {}", ident, state.index, state.summary()); + log_debug!("xHCI {} port{:02} {}", ident, state.index, state.summary()); if first_connected.is_none() && state.connected && !state.overcurrent { first_connected = Some(*state); } @@ -3753,7 +3753,7 @@ impl XhciDriver { product_id, device_release ); - log_info!( + log_debug!( "xHCI {} class={:#04x} subclass={:#04x} protocol={:#04x} max_packet_ep0={}", ident, device_class, @@ -3761,7 +3761,7 @@ impl XhciDriver { device_protocol, max_packet_size ); - log_info!( + log_debug!( "xHCI {} strings: manufacturer={} product={} serial={} configurations={}", ident, manufacturer_index, @@ -3775,14 +3775,14 @@ impl XhciDriver { .map(|byte| format!("{:02x}", byte)) .collect::>() .join(" "); - log_info!( + log_debug!( "xHCI {} device descriptor (first {} bytes): {}", ident, descriptor.len(), partial ); } else { - log_info!( + log_debug!( "xHCI {} device descriptor returned {} byte(s): {:02x?}", ident, descriptor.len(), diff --git a/startQemu.sh b/startQemu.sh index b132651..68e9476 100755 --- a/startQemu.sh +++ b/startQemu.sh @@ -40,7 +40,10 @@ if [[ "$HEADLESS" == "true" || "$HEADLESS" == "headless" ]]; then # QEMU_MONITOR_ARGS=( -chardev pipe,id=mon0,path=/tmp/qemu-monitor -monitor chardev:mon0 -chardev pipe,id=serial0,path=/tmp/qemu-serial -serial chardev:serial0) QEMU_PAUSE_ARGS=() QEMU_DEBUG_ARGS=( -device isa-debugcon,chardev=debugcon ) - QEMU_DEBUG_CHAR_ARGS=( -chardev stdio,id=debugcon -d int,guest_errors,cpu_reset) #,trace:usb_* ) + # QEMU debug flags can create *massive* log output. Keep defaults high-signal. + # Override with: QEMU_DEBUG_FLAGS="int,guest_errors,cpu_reset" ./startQemu.sh headless 10 + QEMU_DEBUG_FLAGS=${QEMU_DEBUG_FLAGS:-guest_errors} + QEMU_DEBUG_CHAR_ARGS=( -chardev stdio,id=debugcon -d "${QEMU_DEBUG_FLAGS}" ) #,trace:usb_* ) else echo "Starting QEMU in headed mode..." echo " QEMU Debug Driver output: debug.log" From be432d68d9c7da871fdfb335c73b7d37cd4476cb Mon Sep 17 00:00:00 2001 From: "Rowan (OpenClaw)" Date: Sun, 22 Feb 2026 02:02:17 +0100 Subject: [PATCH 2/2] docs: add logging policy and verbosity knobs --- docs/logging.md | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 docs/logging.md diff --git a/docs/logging.md b/docs/logging.md new file mode 100644 index 0000000..41b5faa --- /dev/null +++ b/docs/logging.md @@ -0,0 +1,61 @@ +# Logging policy (TheseusOS) + +This project relies heavily on logs during bring-up, but **default boot output must stay high-signal**. +Excessive logs waste developer time and (when using AI tools) consume precious context. + +## Goals + +- **Default config is quiet**: only high-signal INFO, plus WARN/ERROR. +- **Debugging is opt-in**: turn on DEBUG/TRACE intentionally, ideally scoped to a module. +- **Critical boot failures are unmissable**: emit to **serial** and **ISA debugcon (0xE9)**. + +## Current knobs + +### Kernel log level + +- Default: `kernel/src/config.rs` → `DEFAULT_LOG_LEVEL` (should remain relatively quiet, e.g. `Info`). +- Per-module overrides: `MODULE_LOG_LEVELS` (prefer adding temporary overrides while debugging specific areas). + +### Verbose output toggles + +- `VERBOSE_KERNEL_OUTPUT`: enables extra debug traces. +- `PRINT_HARDWARE_INVENTORY`: UEFI inventory dump (very noisy; keep off by default). + +### USB/xHCI diagnostics + +- `USB_ENABLE_POLLING_FALLBACK`: keep `false` for normal runs. +- `USB_IDLE_IMAN_DIAGNOSTICS`: off by default (can spam QEMU host logs depending on tracing). +- `USB_XHCI_EVENT_RING_DIAGNOSTICS`: off by default (enables ring snapshots / extra warnings). +- `USB_RUN_MSIX_SELF_TEST`: on by default (useful, high-signal correctness check). + +### QEMU debug flags (host-side) + +In `startQemu.sh` headless mode: + +- Default `-d` flags are intentionally minimal to avoid enormous output. +- Override with: + +```bash +QEMU_DEBUG_FLAGS="int,guest_errors,cpu_reset" ./startQemu.sh headless 10 +``` + +## Log level guidance + +- **ERROR**: the system cannot proceed or will be incorrect; should be user-visible. +- **WARN**: unexpected but recoverable; should stand out. +- **INFO**: major milestones only ("kernel started", "ACPI init ok", "xHCI MSI enabled"). +- **DEBUG**: detailed state dumps (descriptors, per-port state, per-device enumeration steps). +- **TRACE**: extremely chatty loops or per-register/per-TRB style logs; never default-on. + +## Anti-logspam patterns + +- Use **one-shot** logs ("first time we saw X") +- Use **rate limiting** for repeated warnings +- Use **module-scoped verbosity** rather than raising the global default +- Keep interrupt handlers quiet by default + +## Notes + +If you add new logging: +- ask: "Would I want to see this on every boot?" If not, it probably belongs in DEBUG/TRACE. +- prefer structured summaries over per-item dumps.