diff --git a/src/bin/bootstrap/src/main.rs b/src/bin/bootstrap/src/main.rs index 82c60df8e..a05548d1c 100644 --- a/src/bin/bootstrap/src/main.rs +++ b/src/bin/bootstrap/src/main.rs @@ -73,7 +73,6 @@ fn start_runtime(_runtime_monitor: ObjID, _runtime_library: ObjID) -> ! { .add_compartment("monitor", NewCompartmentFlags::EXPORT_GATES) .unwrap(); - info!("==> {}", monitor_comp_id); let monitor_id = ctx .load_library_in_compartment(monitor_comp_id, unlib, true) .unwrap()[0] diff --git a/src/runtime/README.md b/src/runtime/README.md new file mode 100644 index 000000000..5f3da661f --- /dev/null +++ b/src/runtime/README.md @@ -0,0 +1,11 @@ +# runtime subdirectory + +This subdirectory contains all the crates for the core runtime: + + - dynlink: the dynamic linker code + - minruntime: the minimal (no_std, static linking available) runtime + - monitor: the monitor implementation + - monitor-api: the API crate for interaction with the monitor from runtime or user programs + - rt: reference runtime wrapper crate + - rt-impl: the reference runtime implementation. Users should link against the wrapper crate (rt), not this one. + - secgate: secure gate types and utility functions diff --git a/src/runtime/monitor-api/src/lib.rs b/src/runtime/monitor-api/src/lib.rs index 6deeeb0a3..02587076e 100644 --- a/src/runtime/monitor-api/src/lib.rs +++ b/src/runtime/monitor-api/src/lib.rs @@ -475,6 +475,14 @@ impl CompartmentHandle { pub fn libs(&self) -> LibraryIter<'_> { LibraryIter::new(self) } + + pub fn wait(&self, flags: CompartmentFlags) -> CompartmentFlags { + CompartmentFlags::from_bits_truncate( + gates::monitor_rt_compartment_wait(self.desc(), flags.bits()) + .ok() + .unwrap_or(0), + ) + } } /// An iterator over libraries in a compartment. @@ -534,10 +542,18 @@ bitflags::bitflags! { /// Compartment state flags. #[derive(Clone, Debug, Copy, PartialEq, PartialOrd, Ord, Eq, Hash)] pub struct CompartmentFlags : u64 { - /// Compartment is ready (libraries relocated and constructors run). + /// Compartment is ready (loaded, reloacated, runtime started and ctors run). const READY = 0x1; - /// The main thread has exited. - const EXITED = 0x2; + /// Compartment is a binary, not a library. + const IS_BINARY = 0x2; + /// Compartment runtime thread may exit. + const THREAD_CAN_EXIT = 0x4; + /// Compartment thread has been started once. + const STARTED = 0x8; + /// Compartment destructors have run. + const DESTRUCTED = 0x10; + /// Compartment thread has exited. + const EXITED = 0x20; } } diff --git a/src/runtime/monitor/secapi/gates.rs b/src/runtime/monitor/secapi/gates.rs index 888116e0e..04da16522 100644 --- a/src/runtime/monitor/secapi/gates.rs +++ b/src/runtime/monitor/secapi/gates.rs @@ -190,6 +190,21 @@ impl Display for LoadCompartmentError { } } +#[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))] +#[cfg_attr( + not(feature = "secgate-impl"), + secgate::secure_gate(options(info, api)) +)] +pub fn monitor_rt_compartment_wait( + info: &secgate::GateCallInfo, + desc: Option, + flags: u64, +) -> u64 { + let monitor = crate::mon::get_monitor(); + let caller = info.source_context().unwrap_or(MONITOR_INSTANCE_ID); + monitor.compartment_wait(caller, desc, flags) +} + #[cfg_attr(feature = "secgate-impl", secgate::secure_gate(options(info)))] #[cfg_attr( not(feature = "secgate-impl"), diff --git a/src/runtime/monitor/src/main.rs b/src/runtime/monitor/src/main.rs index 148f1d0a9..4ebccf105 100644 --- a/src/runtime/monitor/src/main.rs +++ b/src/runtime/monitor/src/main.rs @@ -75,53 +75,46 @@ pub fn main() { } fn monitor_init() -> miette::Result<()> { + // If we have monitor tests to run, do so. if let Some(ki_name) = dlengine::get_kernel_init_info() .names() .iter() .find(|iname| iname.name() == "monitor_test_info") { info!("starting monitor tests [{}]", ki_name.name()); + // Read the monitor test binary name. + const MAX_NAMELEN: usize = 0x1000; let info = twizzler_rt_abi::object::twz_rt_map_object(ki_name.id(), MapFlags::READ).unwrap(); let test_name_slice = - unsafe { core::slice::from_raw_parts(info.start().add(NULLPAGE_SIZE), 0x1000) }; + unsafe { core::slice::from_raw_parts(info.start().add(NULLPAGE_SIZE), MAX_NAMELEN) }; let first_null = test_name_slice .iter() .position(|x| *x == 0) - .unwrap_or(0x1000 - 1); + .unwrap_or(MAX_NAMELEN - 1); let test_name = String::from_utf8_lossy(&test_name_slice[0..first_null]); - info!("monitor test binary: {}", test_name); + debug!("monitor test binary: {}", test_name); if let Some(_ki_name) = dlengine::get_kernel_init_info() .names() .iter() .find(|iname| iname.name() == test_name) { + // Load and wait for tests to complete let comp: CompartmentHandle = CompartmentLoader::new("montest", test_name, NewCompartmentFlags::empty()) .args(&["montest"]) .load() .into_diagnostic()?; - let mut eb = 0; - let delay_exp_backoff = |state: &mut u64| { - let val = *state; - if val < 1000 { - if val == 0 { - *state = 1; - } else { - *state *= 2; - } - } - tracing::info!("sleep: {}", val); - std::thread::sleep(Duration::from_millis(val)); - }; - while !comp.info().flags.contains(CompartmentFlags::EXITED) { - delay_exp_backoff(&mut eb); + let mut flags = comp.info().flags; + while !flags.contains(CompartmentFlags::EXITED) { + flags = comp.wait(flags); } } else { tracing::error!("failed to start monitor tests: {}", ki_name.name()); } } info!("monitor early init completed, starting init"); + // TODO: start init... Ok(()) } diff --git a/src/runtime/monitor/src/mon/compartment.rs b/src/runtime/monitor/src/mon/compartment.rs index f9c33b6e1..bdba49860 100644 --- a/src/runtime/monitor/src/mon/compartment.rs +++ b/src/runtime/monitor/src/mon/compartment.rs @@ -245,6 +245,20 @@ impl super::Monitor { ) } + pub fn compartment_wait(&self, caller: ObjID, desc: Option, flags: u64) -> u64 { + let Some(instance) = ({ + let comphandles = self._compartment_handles.write(ThreadKey::get().unwrap()); + let comp_id = desc + .map(|comp| comphandles.lookup(caller, comp).map(|ch| ch.instance)) + .unwrap_or(Some(caller)); + comp_id + }) else { + return 0; + }; + self.wait_for_compartment_state_change(instance, flags); + self.load_compartment_flags(instance) + } + /// Open a handle to the n'th dependency compartment of a given compartment. pub fn get_compartment_deps( &self, @@ -287,7 +301,6 @@ impl super::Monitor { let compname = split.next().ok_or(LoadCompartmentError::Unknown)?; let libname = split.next().ok_or(LoadCompartmentError::Unknown)?; let root = UnloadedLibrary::new(libname); - tracing::info!("A"); // parse args let args_bytes = arg_bytes.split_inclusive(|b| *b == 0); diff --git a/src/runtime/monitor/src/mon/compartment/loader.rs b/src/runtime/monitor/src/mon/compartment/loader.rs index f9c38a885..0c1746d7d 100644 --- a/src/runtime/monitor/src/mon/compartment/loader.rs +++ b/src/runtime/monitor/src/mon/compartment/loader.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, collections::HashSet, ffi::CStr, ptr::null_mut}; +use std::{collections::HashSet, ffi::CStr, ptr::null_mut}; use dynlink::{ compartment::CompartmentId, diff --git a/src/runtime/monitor/src/mon/compartment/runcomp.rs b/src/runtime/monitor/src/mon/compartment/runcomp.rs index 4bb26896a..39d590b5e 100644 --- a/src/runtime/monitor/src/mon/compartment/runcomp.rs +++ b/src/runtime/monitor/src/mon/compartment/runcomp.rs @@ -1,6 +1,5 @@ use std::{ alloc::Layout, - borrow::Cow, collections::HashMap, ffi::{CStr, CString}, ptr::NonNull, @@ -8,7 +7,7 @@ use std::{ }; use dynlink::{compartment::CompartmentId, context::Context}; -use monitor_api::{RuntimeThreadControl, SharedCompConfig, TlsTemplateInfo}; +use monitor_api::{CompartmentFlags, RuntimeThreadControl, SharedCompConfig, TlsTemplateInfo}; use secgate::util::SimpleBuffer; use talc::{ErrOnOom, Talc}; use twizzler_abi::syscall::{ @@ -26,17 +25,17 @@ use crate::mon::{ }; /// Compartment is ready (loaded, reloacated, runtime started and ctors run). -pub const COMP_READY: u64 = 0x1; +pub const COMP_READY: u64 = CompartmentFlags::READY.bits(); /// Compartment is a binary, not a library. -pub const COMP_IS_BINARY: u64 = 0x2; +pub const COMP_IS_BINARY: u64 = CompartmentFlags::IS_BINARY.bits(); /// Compartment runtime thread may exit. -pub const COMP_THREAD_CAN_EXIT: u64 = 0x4; +pub const COMP_THREAD_CAN_EXIT: u64 = CompartmentFlags::THREAD_CAN_EXIT.bits(); /// Compartment thread has been started once. -pub const COMP_STARTED: u64 = 0x8; +pub const COMP_STARTED: u64 = CompartmentFlags::STARTED.bits(); /// Compartment destructors have run. -pub const COMP_DESTRUCTED: u64 = 0x10; +pub const COMP_DESTRUCTED: u64 = CompartmentFlags::DESTRUCTED.bits(); /// Compartment thread has exited. -pub const COMP_EXITED: u64 = 0x20; +pub const COMP_EXITED: u64 = CompartmentFlags::EXITED.bits(); /// A runnable or running compartment. pub struct RunComp { diff --git a/src/runtime/monitor/src/mon/mod.rs b/src/runtime/monitor/src/mon/mod.rs index 84312f1a4..a20946cc6 100644 --- a/src/runtime/monitor/src/mon/mod.rs +++ b/src/runtime/monitor/src/mon/mod.rs @@ -258,7 +258,7 @@ impl Monitor { cmd: MonitorCompControlCmd, ) -> Option { let src = info.source_context()?; - tracing::trace!( + tracing::debug!( "compartment ctrl from: {:?}, thread = {:?}: {:?}", src, info.thread_id(), diff --git a/src/runtime/monitor/tests/montest/src/main.rs b/src/runtime/monitor/tests/montest/src/main.rs index 19dd8d932..27c3018c1 100644 --- a/src/runtime/monitor/tests/montest/src/main.rs +++ b/src/runtime/monitor/tests/montest/src/main.rs @@ -11,7 +11,6 @@ extern crate twizzler_runtime; mod montest_lib { #[link(name = "montest_lib")] extern "C" {} - use secgate::GateCallInfo; #[secgate::secure_gate(options(info, api))] pub fn test_was_ctor_run(info: &GateCallInfo) -> bool {} diff --git a/src/runtime/rt-impl/src/runtime/thread/internal.rs b/src/runtime/rt-impl/src/runtime/thread/internal.rs index 065408ea6..2f92dfaae 100644 --- a/src/runtime/rt-impl/src/runtime/thread/internal.rs +++ b/src/runtime/rt-impl/src/runtime/thread/internal.rs @@ -79,7 +79,7 @@ impl Drop for InternalThread { // Args is allocated by a box. let _args = Box::from_raw(self.args_box as *mut ThreadSpawnArgs); drop(_args); - tracing::warn!("TODO: drop TLS"); + tracing::debug!("TODO: drop TLS"); } } } diff --git a/tools/xtask/src/build.rs b/tools/xtask/src/build.rs index 09d832275..e16e37e99 100644 --- a/tools/xtask/src/build.rs +++ b/tools/xtask/src/build.rs @@ -313,6 +313,8 @@ fn maybe_build_tests_static<'a>( Ok(Some(cargo::ops::compile(workspace, &options)?)) } +// Once we merge the runtimes fully and switch to using the dynamic runtime as default, +// we can merge a lot of this test infrastructure. fn maybe_build_tests_dynamic<'a>( workspace: &'a Workspace, build_config: &crate::BuildConfig, diff --git a/tools/xtask/src/image.rs b/tools/xtask/src/image.rs index 30e3898d4..b4f3fcafb 100644 --- a/tools/xtask/src/image.rs +++ b/tools/xtask/src/image.rs @@ -183,6 +183,7 @@ fn build_initrd(cli: &ImageOptions, comp: &TwizzlerCompilation) -> anyhow::Resul } } + // all the tests for init to run. if let Some(ref test_comp) = comp.borrow_static_test_compilation() { let mut testlist = String::new(); for bin in test_comp.tests.iter() { @@ -206,6 +207,8 @@ fn build_initrd(cli: &ImageOptions, comp: &TwizzlerCompilation) -> anyhow::Resul assert!(!cli.tests && !cli.benches); } + // all the tests for the monitor to run. Eventually this and the above will merge into + // one thing, but that will have to wait until the dynamic runtime is default. if let Some(ref test_comp) = comp.borrow_user_test_compilation() { let mut testlist = String::new(); for bin in test_comp.tests.iter() { diff --git a/tools/xtask/src/toolchain.rs b/tools/xtask/src/toolchain.rs index 3936cabd9..0ac05987a 100644 --- a/tools/xtask/src/toolchain.rs +++ b/tools/xtask/src/toolchain.rs @@ -289,7 +289,7 @@ pub(crate) fn do_bootstrap(cli: BootstrapOptions) -> anyhow::Result<()> { pub fn set_dynamic() { std::env::set_var( "RUSTFLAGS", - "-C prefer-dynamic=y -Z staticlib-prefer-dynamic=y -C link-arg=--allow-shlib-undefined -Z macro-backtrace", + "-C prefer-dynamic=y -Z staticlib-prefer-dynamic=y -C link-arg=--allow-shlib-undefined", ); std::env::set_var("CARGO_TARGET_DIR", "target/dynamic"); }