1#![allow(clippy::missing_safety_doc)]
6#![cfg_attr(
7 any(target_arch = "aarch64", target_arch = "riscv64"),
8 allow(incomplete_features)
9)]
10#![cfg_attr(target_arch = "x86_64", feature(abi_x86_interrupt))]
11#![feature(allocator_api)]
12#![feature(linkage)]
13#![feature(linked_list_cursors)]
14#![feature(map_try_insert)]
15#![feature(maybe_uninit_as_bytes)]
16#![feature(maybe_uninit_slice)]
17#![feature(maybe_uninit_write_slice)]
18#![feature(never_type)]
19#![feature(slice_from_ptr_range)]
20#![feature(slice_ptr_get)]
21#![cfg_attr(
22 any(target_arch = "aarch64", target_arch = "riscv64"),
23 feature(specialization)
24)]
25#![feature(thread_local)]
26#![cfg_attr(target_os = "none", no_std)]
27#![cfg_attr(target_os = "none", feature(custom_test_frameworks))]
28#![cfg_attr(all(target_os = "none", test), test_runner(crate::test_runner))]
29#![cfg_attr(
30 all(target_os = "none", test),
31 reexport_test_harness_main = "test_main"
32)]
33#![cfg_attr(all(target_os = "none", test), no_main)]
34
35#[macro_use]
37extern crate alloc;
38#[macro_use]
39extern crate bitflags;
40#[macro_use]
41extern crate log;
42#[cfg(not(target_os = "none"))]
43#[macro_use]
44extern crate std;
45
46#[cfg(feature = "smp")]
47use core::hint::spin_loop;
48#[cfg(feature = "smp")]
49use core::sync::atomic::{AtomicU32, Ordering};
50
51use arch::core_local::*;
52
53pub(crate) use crate::arch::*;
54pub use crate::config::DEFAULT_STACK_SIZE;
55pub(crate) use crate::config::*;
56pub use crate::fs::create_file;
57use crate::kernel::is_uhyve_with_pci;
58use crate::scheduler::{PerCoreScheduler, PerCoreSchedulerExt};
59
60#[macro_use]
61mod macros;
62
63#[macro_use]
64mod logging;
65
66pub mod arch;
67mod config;
68pub mod console;
69mod drivers;
70mod entropy;
71mod env;
72pub mod errno;
73mod executor;
74pub mod fd;
75pub mod fs;
76mod init_cell;
77pub mod io;
78pub mod mm;
79pub mod scheduler;
80#[cfg(all(feature = "shell", target_arch = "x86_64"))]
81mod shell;
82mod synch;
83pub mod syscalls;
84pub mod time;
85
86hermit_entry::define_abi_tag!();
87
88#[cfg(target_os = "none")]
89hermit_entry::define_entry_version!();
90
91#[cfg(test)]
92#[cfg(target_os = "none")]
93#[unsafe(no_mangle)]
94extern "C" fn runtime_entry(_argc: i32, _argv: *const *const u8, _env: *const *const u8) -> ! {
95 println!("Executing hermit unittests. Any arguments are dropped");
96 test_main();
97 core_scheduler().exit(0)
98}
99
100#[cfg(test)]
102pub fn test_runner(tests: &[&dyn Fn()]) {
103 println!("Running {} tests", tests.len());
104 for test in tests {
105 test();
106 }
107 core_scheduler().exit(0)
108}
109
110#[cfg(target_os = "none")]
111#[test_case]
112fn trivial_test() {
113 println!("Test test test");
114 panic!("Test called");
115}
116
117#[cfg(target_os = "none")]
119extern "C" fn initd(_arg: usize) {
120 unsafe extern "C" {
121 #[cfg(all(not(test), not(any(feature = "nostd", feature = "common-os"))))]
122 fn runtime_entry(argc: i32, argv: *const *const u8, env: *const *const u8) -> !;
123 #[cfg(all(not(test), any(feature = "nostd", feature = "common-os")))]
124 fn main(argc: i32, argv: *const *const u8, env: *const *const u8);
125 }
126
127 if env::is_uhyve() {
128 info!("Hermit is running on uhyve!");
129 } else {
130 info!("Hermit is running on common system!");
131 }
132
133 drivers::init();
135 crate::executor::init();
136
137 syscalls::init();
138 fs::init();
139 #[cfg(all(feature = "shell", target_arch = "x86_64"))]
140 shell::init();
141
142 #[cfg(not(test))]
144 let (argc, argv, environ) = syscalls::get_application_parameters();
145
146 core_scheduler().reschedule();
148
149 info!("Jumping into application");
150
151 #[cfg(not(test))]
152 unsafe {
153 #[cfg(all(not(test), not(any(feature = "nostd", feature = "common-os"))))]
155 runtime_entry(argc, argv, environ);
156 #[cfg(all(not(test), any(feature = "nostd", feature = "common-os")))]
157 main(argc, argv, environ);
158 }
159 #[cfg(test)]
160 test_main();
161}
162
163#[cfg(feature = "smp")]
164fn synch_all_cores() {
165 static CORE_COUNTER: AtomicU32 = AtomicU32::new(0);
166
167 CORE_COUNTER.fetch_add(1, Ordering::SeqCst);
168
169 let possible_cpus = kernel::get_possible_cpus();
170 while CORE_COUNTER.load(Ordering::SeqCst) != possible_cpus {
171 spin_loop();
172 }
173}
174
175#[cfg(target_os = "none")]
177fn boot_processor_main() -> ! {
178 hermit_sync::Lazy::force(&console::CONSOLE);
180 unsafe {
181 logging::init();
182 }
183
184 info!("Welcome to Hermit {}", env!("CARGO_PKG_VERSION"));
185 info!("Kernel starts at {:p}", env::get_base_address());
186
187 if let Some(fdt) = env::fdt() {
188 info!("FDT:\n{fdt:#?}");
189 }
190
191 unsafe extern "C" {
192 static mut __bss_start: u8;
193 }
194 let bss_ptr = core::ptr::addr_of_mut!(__bss_start);
195 info!("BSS starts at {bss_ptr:p}");
196 info!("tls_info = {:#x?}", env::boot_info().load_info.tls_info);
197 arch::boot_processor_init();
198
199 #[cfg(not(target_arch = "riscv64"))]
200 scheduler::add_current_core();
201 interrupts::enable();
202
203 arch::kernel::boot_next_processor();
204
205 #[cfg(feature = "smp")]
206 synch_all_cores();
207
208 #[cfg(feature = "pci")]
209 info!("Compiled with PCI support");
210 #[cfg(all(feature = "acpi", target_arch = "x86_64"))]
211 info!("Compiled with ACPI support");
212 #[cfg(all(feature = "fsgsbase", target_arch = "x86_64"))]
213 info!("Compiled with FSGSBASE support");
214 #[cfg(feature = "smp")]
215 info!("Compiled with SMP support");
216
217 if is_uhyve_with_pci() || !env::is_uhyve() {
218 #[cfg(feature = "pci")]
219 crate::drivers::pci::print_information();
220 }
221
222 unsafe {
224 scheduler::PerCoreScheduler::spawn(
225 initd,
226 0,
227 scheduler::task::NORMAL_PRIO,
228 0,
229 USER_STACK_SIZE,
230 )
231 };
232
233 PerCoreScheduler::run();
235}
236
237#[cfg(all(target_os = "none", feature = "smp"))]
239fn application_processor_main() -> ! {
240 arch::application_processor_init();
241 #[cfg(not(target_arch = "riscv64"))]
242 scheduler::add_current_core();
243 interrupts::enable();
244 arch::kernel::boot_next_processor();
245
246 debug!("Entering idle loop for application processor");
247
248 synch_all_cores();
249 crate::executor::init();
250
251 PerCoreScheduler::run();
253}
254
255#[cfg(target_os = "none")]
256#[panic_handler]
257fn panic(info: &core::panic::PanicInfo<'_>) -> ! {
258 let core_id = crate::arch::core_local::core_id();
259 panic_println!("[{core_id}][PANIC] {info}\n");
260
261 crate::scheduler::shutdown(1);
262}