Skip to main content

strat9_kernel/syscall/
debug.rs

1//! Debug log syscall handler.
2//!
3//! Provides `SYS_DEBUG_LOG` for userspace-to-kernel diagnostic messages.
4
5use super::error::SyscallError;
6use crate::memory::UserSliceRead;
7/// SYS_DEBUG_LOG (600): write a debug message to serial and silo output.
8///
9/// arg1 = buffer pointer, arg2 = buffer length.
10pub fn sys_debug_log(buf_ptr: u64, buf_len: u64) -> Result<u64, SyscallError> {
11    if buf_len == 0 {
12        return Ok(0);
13    }
14
15    // Restrict debug logging to admin or console-capable tasks.
16    crate::silo::enforce_console_access()?;
17
18    let len = core::cmp::min(buf_len as usize, 4096);
19
20    // Validate the user buffer via UserSlice
21    let user_buf = UserSliceRead::new(buf_ptr, len)?;
22
23    // Copy into kernel buffer
24    let mut kbuf = [0u8; 4096];
25    let copied = user_buf.copy_to(&mut kbuf);
26
27    let msg = core::str::from_utf8(&kbuf[..copied]).unwrap_or("<invalid utf8>");
28
29    // Mirror to serial while debugging userspace/network flows; keep E9 too.
30    crate::serial_println!("[user-debug] {}", msg);
31    crate::e9_println!("[user-debug] {}", msg);
32
33    // Mirror critical boot/network userspace logs to the serial console so
34    // early silo failures are visible without attaching to per-silo output.
35    if msg.starts_with("[init]")
36        || msg.starts_with("[strate-net]")
37        || msg.starts_with("[dhcp-client]")
38    {
39        crate::serial_print!("{}", msg);
40    }
41
42    if let Some(task) = crate::process::current_task_clone() {
43        if let Some(silo_id) = crate::silo::task_silo_id(task.id) {
44            crate::silo::silo_output_write(silo_id, &kbuf[..copied]);
45        }
46    }
47
48    Ok(copied as u64)
49}