ostd/lib.rs
1// SPDX-License-Identifier: MPL-2.0
2//! The standard library for Asterinas and other Rust OSes.
3#![feature(alloc_error_handler)]
4#![feature(allocator_api)]
5#![feature(btree_cursors)]
6#![feature(const_trait_impl)]
7#![feature(core_intrinsics)]
8#![feature(coroutines)]
9#![feature(fn_traits)]
10#![feature(iter_advance_by)]
11#![feature(iter_from_coroutine)]
12#![feature(linkage)]
13#![feature(min_specialization)]
14//#![feature(negative_impls)]
15#![feature(ptr_metadata)]
16#![feature(sync_unsafe_cell)]
17#![expect(internal_features)]
18#![no_std]
19// Disable `missing_docs`: verification-only `inv`/`type_inv` items are
20// explained by proof context rather than API docs.
21// #![warn(missing_docs)]
22#![feature(proc_macro_hygiene)]
23#![allow(unused_parens)]
24#![allow(unused_braces)]
25#![allow(rustdoc::invalid_rust_codeblocks)]
26#![allow(rustdoc::invalid_html_tags)]
27#![allow(rustdoc::broken_intra_doc_links)]
28// Allow Verus-style specification names that mirror constants or proof-level
29// concepts rather than Rust's conventional function naming.
30#![allow(non_snake_case)]
31
32extern crate alloc;
33
34use vstd_extra::prelude;
35
36//#[cfg(target_arch = "x86_64")]
37#[path = "arch/x86/mod.rs"]
38pub mod arch;
39//#[cfg(target_arch = "riscv64")]
40//#[path = "arch/riscv/mod.rs"]
41//pub mod arch;
42pub mod boot;
43/*pub mod bus;
44pub mod console;
45pub mod cpu;*/
46pub mod error;
47/*pub mod io;
48pub mod logger;*/
49pub mod mm;
50/*pub mod panic;
51pub mod prelude;
52pub mod smp;*/
53pub mod sync;
54pub mod task;
55// pub mod timer;
56pub mod trap;
57// pub mod user;
58#[path = "../specs/lib.rs"]
59pub mod specs;
60pub mod util;
61
62/*use core::sync::atomic::{AtomicBool, Ordering};
63
64pub use ostd_macros::{
65 global_frame_allocator, global_heap_allocator, global_heap_allocator_slot_map, main,
66 panic_handler,
67};
68pub use ostd_pod::Pod;
69
70pub use self::{error::Error, prelude::Result};
71
72/// Initializes OSTD.
73///
74/// This function represents the first phase booting up the system. It makes
75/// all functionalities of OSTD available after the call.
76///
77/// # Safety
78///
79/// This function should be called only once and only on the BSP.
80//
81// TODO: We need to refactor this function to make it more modular and
82// make inter-initialization-dependencies more clear and reduce usages of
83// boot stage only global variables.
84#[doc(hidden)]
85unsafe fn init() {
86 arch::enable_cpu_features();
87
88 // SAFETY: This function is called only once, before `allocator::init`
89 // and after memory regions are initialized.
90 unsafe { mm::frame::allocator::init_early_allocator() };
91
92 #[cfg(target_arch = "x86_64")]
93 arch::if_tdx_enabled!({
94 } else {
95 arch::serial::init();
96 });
97 #[cfg(not(target_arch = "x86_64"))]
98 arch::serial::init();
99
100 logger::init();
101
102 // SAFETY:
103 // 1. They are only called once in the boot context of the BSP.
104 // 2. The number of CPUs are available because ACPI has been initialized.
105 // 3. No CPU-local objects have been accessed yet.
106 unsafe { cpu::init_on_bsp() };
107
108 // SAFETY: We are on the BSP and APs are not yet started.
109 let meta_pages = unsafe { mm::frame::meta::init() };
110 // The frame allocator should be initialized immediately after the metadata
111 // is initialized. Otherwise the boot page table can't allocate frames.
112 // SAFETY: This function is called only once.
113 unsafe { mm::frame::allocator::init() };
114
115 mm::kspace::init_kernel_page_table(meta_pages);
116
117 sync::init();
118
119 boot::init_after_heap();
120
121 mm::dma::init();
122
123 unsafe { arch::late_init_on_bsp() };
124
125 #[cfg(target_arch = "x86_64")]
126 arch::if_tdx_enabled!({
127 arch::serial::init();
128 });
129
130 smp::init();
131
132 // SAFETY: This function is called only once on the BSP.
133 unsafe {
134 mm::kspace::activate_kernel_page_table();
135 }
136
137 bus::init();
138
139 arch::irq::enable_local();
140
141 invoke_ffi_init_funcs();
142
143 IN_BOOTSTRAP_CONTEXT.store(false, Ordering::Relaxed);
144}
145
146/// Indicates whether the kernel is in bootstrap context.
147pub(crate) static IN_BOOTSTRAP_CONTEXT: AtomicBool = AtomicBool::new(true);
148
149/// Invoke the initialization functions defined in the FFI.
150/// The component system uses this function to call the initialization functions of
151/// the components.
152fn invoke_ffi_init_funcs() {
153 extern "C" {
154 fn __sinit_array();
155 fn __einit_array();
156 }
157 let call_len = (__einit_array as usize - __sinit_array as usize) / 8;
158 for i in 0..call_len {
159 unsafe {
160 let function = (__sinit_array as usize + 8 * i) as *const fn();
161 (*function)();
162 }
163 }
164}
165
166/// Simple unit tests for the ktest framework.
167#[cfg(ktest)]
168mod test {
169 use crate::prelude::*;
170
171 #[ktest]
172 #[expect(clippy::eq_op)]
173 fn trivial_assertion() {
174 assert_eq!(0, 0);
175 }
176
177 #[ktest]
178 #[should_panic]
179 fn failing_assertion() {
180 assert_eq!(0, 1);
181 }
182
183 #[ktest]
184 #[should_panic(expected = "expected panic message")]
185 fn expect_panic() {
186 panic!("expected panic message");
187 }
188}
189
190#[doc(hidden)]
191pub mod ktest {
192 //! The module re-exports everything from the [`ostd_test`] crate, as well
193 //! as the test entry point macro.
194 //!
195 //! It is rather discouraged to use the definitions here directly. The
196 //! `ktest` attribute is sufficient for all normal use cases.
197
198 pub use ostd_macros::{test_main as main, test_panic_handler as panic_handler};
199 pub use ostd_test::*;
200}
201*/