// SPDX-License-Identifier: MPL-2.0 //! The standard library for Asterinas and other Rust OSes. #![feature(alloc_error_handler)] #![feature(allocator_api)] #![feature(btree_cursors)] #![feature(const_ptr_sub_ptr)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] #![feature(coroutines)] #![feature(fn_traits)] #![feature(iter_from_coroutine)] #![feature(let_chains)] #![feature(linkage)] #![feature(min_specialization)] #![feature(negative_impls)] #![feature(ptr_metadata)] #![feature(ptr_sub_ptr)] #![feature(sync_unsafe_cell)] #![feature(trait_upcasting)] #![feature(iter_advance_by)] #![expect(internal_features)] #![no_std] #![warn(missing_docs)] extern crate alloc; pub mod arch; pub mod boot; pub mod bus; pub mod collections; pub mod console; pub mod cpu; mod error; pub mod io; pub mod logger; pub mod mm; pub mod panic; pub mod prelude; pub mod smp; pub mod sync; pub mod task; pub mod timer; pub mod trap; pub mod user; pub(crate) mod util; use core::sync::atomic::{AtomicBool, Ordering}; pub use ostd_macros::{ global_frame_allocator, global_heap_allocator, global_heap_allocator_slot_map, main, panic_handler, }; pub use ostd_pod::Pod; pub use self::{error::Error, prelude::Result}; /// Initializes OSTD. /// /// This function represents the first phase booting up the system. It makes /// all functionalities of OSTD available after the call. /// /// # Safety /// /// This function should be called only once and only on the BSP. // // TODO: We need to refactor this function to make it more modular and // make inter-initialization-dependencies more clear and reduce usages of // boot stage only global variables. #[doc(hidden)] unsafe fn init() { arch::enable_cpu_features(); // SAFETY: This function is called only once, before `allocator::init` // and after memory regions are initialized. unsafe { mm::frame::allocator::init_early_allocator(); } if_tdx_enabled!({ } else { arch::serial::init(); }); logger::init(); // SAFETY: // 1. They are only called once in the boot context of the BSP. // 2. The number of CPUs are available because ACPI has been initialized. // 3. No CPU-local objects have been accessed yet. unsafe { cpu::init_on_bsp() }; // SAFETY: We are on the BSP and APs are not yet started. let meta_pages = unsafe { mm::frame::meta::init() }; // The frame allocator should be initialized immediately after the metadata // is initialized. Otherwise the boot page table can't allocate frames. // SAFETY: This function is called only once. unsafe { mm::frame::allocator::init() }; mm::kspace::init_kernel_page_table(meta_pages); crate::sync::init(); boot::init_after_heap(); mm::dma::init(); unsafe { arch::late_init_on_bsp() }; if_tdx_enabled!({ arch::serial::init(); }); arch::serial::callback_init(); smp::init(); // SAFETY: This function is called only once on the BSP. unsafe { mm::kspace::activate_kernel_page_table(); } bus::init(); arch::irq::enable_local(); invoke_ffi_init_funcs(); IN_BOOTSTRAP_CONTEXT.store(false, Ordering::Relaxed); } /// Indicates whether the kernel is in bootstrap context. pub(crate) static IN_BOOTSTRAP_CONTEXT: AtomicBool = AtomicBool::new(true); /// Invoke the initialization functions defined in the FFI. /// The component system uses this function to call the initialization functions of /// the components. fn invoke_ffi_init_funcs() { extern "C" { fn __sinit_array(); fn __einit_array(); } let call_len = (__einit_array as usize - __sinit_array as usize) / 8; for i in 0..call_len { unsafe { let function = (__sinit_array as usize + 8 * i) as *const fn(); (*function)(); } } } /// Simple unit tests for the ktest framework. #[cfg(ktest)] mod test { use crate::prelude::*; #[ktest] #[expect(clippy::eq_op)] fn trivial_assertion() { assert_eq!(0, 0); } #[ktest] #[should_panic] fn failing_assertion() { assert_eq!(0, 1); } #[ktest] #[should_panic(expected = "expected panic message")] fn expect_panic() { panic!("expected panic message"); } } #[doc(hidden)] pub mod ktest { //! The module re-exports everything from the [`ostd_test`] crate, as well //! as the test entry point macro. //! //! It is rather discouraged to use the definitions here directly. The //! `ktest` attribute is sufficient for all normal use cases. pub use ostd_macros::{test_main as main, test_panic_handler as panic_handler}; pub use ostd_test::*; }