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