use core::sync::atomic::{AtomicU8, Ordering}; use crate::error::KernelError; use crate::proc::context::CpuContext; use crate::syscall::{SyscallResult, copy_from_user}; static LOG_THRESHOLD: AtomicU8 = AtomicU8::new(2); #[allow(dead_code)] pub fn threshold() -> u8 { LOG_THRESHOLD.load(Ordering::Relaxed) } #[allow(dead_code)] pub fn set_threshold(level: u8) { LOG_THRESHOLD.store(level.min(3), Ordering::Relaxed); } const GLASS_BIT: u8 = 0x80; pub fn sys_log(ctx: &mut CpuContext) { let raw_level = ctx.rdi as u8; let glass = raw_level & GLASS_BIT != 0; let level = raw_level & !GLASS_BIT; let ptr = ctx.rsi; let len = ctx.rdx; if level > 3 { ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); return; } if !glass && level > LOG_THRESHOLD.load(Ordering::Relaxed) { ctx.rax = SyscallResult::ok().raw(); return; } let irq = match crate::sync::InterruptsDisabledToken::new_checked() { Some(tok) => tok, None => { x86_64::instructions::interrupts::disable(); match crate::sync::InterruptsDisabledToken::new_checked() { Some(tok) => tok, None => { ctx.rax = SyscallResult::error(KernelError::BadState).raw(); return; } } } }; if len > 256 { ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); return; } let mut buf = [0u8; 256]; match copy_from_user(ptr, &mut buf, len as usize, &irq) { Err(e) => { ctx.rax = SyscallResult::error(e).raw(); } Ok(()) => match core::str::from_utf8(&buf[..len as usize]) { Err(_) => { ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); } Ok(msg) => { let pid = crate::arch::syscall::current_pid(); let mut name_buf = [0u8; 32]; let name_len = { let ptable = crate::proc::PROCESSES.lock(); let name = ptable.exec(pid).map(|e| e.name_str()).unwrap_or("?"); let n = name.len().min(32); name_buf[..n].copy_from_slice(&name.as_bytes()[..n]); n }; let name_str = unsafe { core::str::from_utf8_unchecked(&name_buf[..name_len]) }; let severity = lancer_log::Severity::from_u8(level).unwrap_or(lancer_log::Severity::Info); let tsc = crate::wcet::tsc::read_tsc(); crate::flight::recorder().append(tsc, severity, name_str, format_args!("{}", msg)); if glass { use core::fmt::Write; let mut w = crate::arch::serial::SerialWriter; let _ = lancer_log::format::write_gutter( &mut w, name_str, severity, format_args!("{}", msg), crate::log::KLOG_GUTTER, ); let _ = w.write_str("\n"); } ctx.rax = SyscallResult::ok().raw(); } }, } } pub fn sys_get_proc_name(ctx: &mut CpuContext) { let dst_ptr = ctx.rdi; let dst_cap = ctx.rsi; let irq = match crate::sync::InterruptsDisabledToken::new_checked() { Some(tok) => tok, None => { x86_64::instructions::interrupts::disable(); match crate::sync::InterruptsDisabledToken::new_checked() { Some(tok) => tok, None => { ctx.rax = SyscallResult::error(KernelError::BadState).raw(); return; } } } }; let pid = crate::arch::syscall::current_pid(); let mut name_buf = [0u8; 32]; let name_len = { let ptable = crate::proc::PROCESSES.lock(); let name = ptable.exec(pid).map(|e| e.name_str()).unwrap_or("?"); let n = name.len().min(32); name_buf[..n].copy_from_slice(&name.as_bytes()[..n]); n }; let copy_len = name_len.min(dst_cap as usize); if copy_len > 0 { match crate::syscall::copy_to_user(dst_ptr, &name_buf[..copy_len], copy_len, &irq) { Ok(()) => { ctx.rax = SyscallResult::success(copy_len as u64).raw(); } Err(e) => { ctx.rax = SyscallResult::error(e).raw(); } } } else { ctx.rax = SyscallResult::success(0).raw(); } } pub fn sys_blackbox_read(ctx: &mut CpuContext) { let cursor = ctx.rdi as usize; let dst_ptr = ctx.rsi; let dst_len = ctx.rdx as usize; ctx.rsi = 0; let irq = match crate::sync::InterruptsDisabledToken::new_checked() { Some(tok) => tok, None => { x86_64::instructions::interrupts::disable(); match crate::sync::InterruptsDisabledToken::new_checked() { Some(tok) => tok, None => { ctx.rax = SyscallResult::error(KernelError::BadState).raw(); return; } } } }; if dst_len == 0 || dst_len > 65536 { ctx.rax = SyscallResult::error(KernelError::InvalidParameter).raw(); return; } let mut tmp = [0u8; 4096]; let read_cap = dst_len.min(4096); let (new_cursor, bytes_read) = crate::flight::recorder().read(cursor, &mut tmp[..read_cap]); if bytes_read > 0 { match crate::syscall::copy_to_user(dst_ptr, &tmp[..bytes_read], bytes_read, &irq) { Ok(()) => { ctx.rax = new_cursor as u64; ctx.rsi = bytes_read as u64; } Err(e) => { ctx.rax = SyscallResult::error(e).raw(); } } } else { ctx.rax = new_cursor as u64; ctx.rsi = 0; } }