feat(kernel): console cap gates DebugPutchar, no uart fast path; spawn start arg in a0; delegate returns slot
This commit is contained in:
@@ -4,8 +4,11 @@ struct Writer;
|
||||
|
||||
impl fmt::Write for Writer {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
for &b in s.as_bytes() {
|
||||
crate::syscall::debug_putchar(b);
|
||||
// Without a console capability, output goes nowhere.
|
||||
if let Some(console) = crate::start::console() {
|
||||
for &b in s.as_bytes() {
|
||||
crate::syscall::debug_putchar(console, b);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ pub mod fs;
|
||||
pub mod input;
|
||||
pub mod io;
|
||||
mod rt;
|
||||
pub mod start;
|
||||
pub mod syscall;
|
||||
|
||||
#[cfg(target_os = "none")]
|
||||
|
||||
@@ -7,6 +7,8 @@ core::arch::global_asm!(
|
||||
.section .text.entry
|
||||
.globl _start
|
||||
_start:
|
||||
lla t0, LIBKOS_START_ARG
|
||||
sd a0, 0(t0)
|
||||
call main
|
||||
li a7, 16
|
||||
ecall
|
||||
|
||||
36
crates/libkos/src/start.rs
Normal file
36
crates/libkos/src/start.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
//! What this process was handed at start (see `types::start_arg`).
|
||||
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use types::bounded::CapSlot;
|
||||
use types::start_arg;
|
||||
|
||||
/// Set by `_start` from `a0` before `main` runs.
|
||||
#[unsafe(no_mangle)]
|
||||
static LIBKOS_START_ARG: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
/// Overrides the start argument's console once set; `NONE` drops output.
|
||||
static CONSOLE: AtomicUsize = AtomicUsize::new(UNSET);
|
||||
const UNSET: usize = usize::MAX;
|
||||
const NONE: usize = usize::MAX - 1;
|
||||
|
||||
fn arg() -> usize {
|
||||
LIBKOS_START_ARG.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// The console capability this process prints through, if any.
|
||||
pub fn console() -> Option<CapSlot> {
|
||||
match CONSOLE.load(Ordering::Relaxed) {
|
||||
UNSET => start_arg::console(arg()),
|
||||
v => CapSlot::new(u8::try_from(v).ok()?),
|
||||
}
|
||||
}
|
||||
|
||||
/// For a process that gets its console some other way (init, from BootInfo).
|
||||
pub fn set_console(slot: Option<CapSlot>) {
|
||||
CONSOLE.store(slot.map_or(NONE, |s| s.value() as usize), Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// The log server endpoint this process was given, if any.
|
||||
pub fn log() -> Option<CapSlot> {
|
||||
start_arg::log(arg())
|
||||
}
|
||||
@@ -8,8 +8,9 @@ use types::syscall_abi::*;
|
||||
|
||||
// ---- capabilities ----
|
||||
|
||||
pub fn delegate(slot: CapSlot, to: CapSlot, permissions: PermissionSet) -> bool {
|
||||
raw(
|
||||
/// Returns the slot the copy landed in, in `to`'s table.
|
||||
pub fn delegate(slot: CapSlot, to: CapSlot, permissions: PermissionSet) -> Option<CapSlot> {
|
||||
slot_of(raw(
|
||||
SYS_DELEGATE,
|
||||
[
|
||||
slot.value() as usize,
|
||||
@@ -19,8 +20,8 @@ pub fn delegate(slot: CapSlot, to: CapSlot, permissions: PermissionSet) -> bool
|
||||
0,
|
||||
0,
|
||||
],
|
||||
)
|
||||
.is_ok()
|
||||
))
|
||||
.ok()
|
||||
}
|
||||
|
||||
/// Copies an unbadged endpoint or notification capability with `badge`
|
||||
|
||||
@@ -46,18 +46,19 @@ pub fn create_process(create_cap: CapSlot) -> Option<CapSlot> {
|
||||
.ok()
|
||||
}
|
||||
|
||||
pub fn spawn_thread(entry: EntryPoint, stack: StackPointer) -> usize {
|
||||
raw(SYS_SPAWN_THREAD, [entry.raw(), stack.raw(), 0, 0, 0, 0]).map_or(NONE, |r| r[1])
|
||||
/// `arg` arrives in the new thread's `a0` (see `libkos::start`).
|
||||
pub fn spawn_thread(entry: EntryPoint, stack: StackPointer, arg: usize) -> usize {
|
||||
raw(SYS_SPAWN_THREAD, [entry.raw(), stack.raw(), arg, 0, 0, 0]).map_or(NONE, |r| r[1])
|
||||
}
|
||||
|
||||
pub fn spawn_thread_in(process_cap: CapSlot, entry: EntryPoint, stack: StackPointer) -> usize {
|
||||
pub fn spawn_thread_in(process_cap: CapSlot, entry: EntryPoint, stack: StackPointer, arg: usize) -> usize {
|
||||
raw(
|
||||
SYS_SPAWN_THREAD_IN,
|
||||
[
|
||||
process_cap.value() as usize,
|
||||
entry.raw(),
|
||||
stack.raw(),
|
||||
0,
|
||||
arg,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
@@ -69,6 +70,6 @@ pub fn kill(process_cap: CapSlot) -> bool {
|
||||
raw(SYS_KILL, [process_cap.value() as usize, 0, 0, 0, 0, 0]).is_ok()
|
||||
}
|
||||
|
||||
pub fn debug_putchar(byte: u8) {
|
||||
let _ = raw(SYS_DEBUG_PUTCHAR, [byte as usize, 0, 0, 0, 0, 0]);
|
||||
pub fn debug_putchar(console: CapSlot, byte: u8) {
|
||||
let _ = raw(SYS_DEBUG_PUTCHAR, [console.value() as usize, byte as usize, 0, 0, 0, 0]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user