feat(kernel): console cap gates DebugPutchar, no uart fast path; spawn start arg in a0; delegate returns slot

This commit is contained in:
2026-10-27 14:54:36 +01:00
parent 33e1c849d1
commit 7415bab7f5
31 changed files with 290 additions and 64 deletions

View File

@@ -34,6 +34,7 @@ pub struct BootInfo {
pub magic: u64,
pub device_count: u64,
pub system_control_slot: u64,
pub console_slot: u64,
pub devices: [BootDevice; MAX_BOOT_DEVICES],
}

View File

@@ -12,6 +12,7 @@ pub mod mapping;
pub mod permission;
#[cfg(kani)]
pub mod proofs;
pub mod start_arg;
pub mod storage;
pub mod syscall_abi;
pub mod time;

View File

@@ -0,0 +1,43 @@
//! The word a process's first thread gets in `a0`: the slots of the
//! capabilities any process may be handed at start (console, log endpoint).
//! Each field is slot + 1 in one byte; 0 means none.
use crate::bounded::CapSlot;
const CONSOLE_SHIFT: u32 = 0;
const LOG_SHIFT: u32 = 8;
fn field(arg: usize, shift: u32) -> Option<CapSlot> {
let v = (arg >> shift) & 0xFF;
CapSlot::new(u8::try_from(v.checked_sub(1)?).ok()?)
}
fn put(slot: Option<CapSlot>, shift: u32) -> usize {
slot.map_or(0, |s| (s.value() as usize + 1) << shift)
}
pub fn encode(console: Option<CapSlot>, log: Option<CapSlot>) -> usize {
put(console, CONSOLE_SHIFT) | put(log, LOG_SHIFT)
}
pub fn console(arg: usize) -> Option<CapSlot> {
field(arg, CONSOLE_SHIFT)
}
pub fn log(arg: usize) -> Option<CapSlot> {
field(arg, LOG_SHIFT)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn slots_round_trip_and_zero_is_none() {
let (c, l) = (CapSlot::new(0), CapSlot::new(63));
let arg = encode(c, l);
assert_eq!((console(arg), log(arg)), (c, l));
assert_eq!((console(0), log(0)), (None, None));
assert_eq!(log(encode(c, None)), None);
}
}