1use crate::arch::kernel;
2use crate::arch::kernel::core_local::{core_id, core_scheduler};
3use crate::arch::kernel::interrupts;
4use crate::scheduler::{PerCoreScheduler, PerCoreSchedulerExt};
5use crate::{console, drivers, env, executor, fs, logging, mm, scheduler, syscalls};
6
7mod built_info {
8 include!(concat!(env!("OUT_DIR"), "/built.rs"));
9}
10
11hermit_entry::define_abi_tag!();
12
13hermit_entry::define_entry_version!();
14
15#[cfg(test)]
16#[unsafe(no_mangle)]
17extern "C" fn runtime_entry(_argc: i32, _argv: *const *const u8, _env: *const *const u8) -> ! {
18 println!("Executing hermit unittests. Any arguments are dropped");
19 crate::test_main();
20 core_scheduler().exit(0)
21}
22
23#[cfg(test)]
25pub fn test_runner(tests: &[&dyn Fn()]) {
26 println!("Running {} tests", tests.len());
27 for test in tests {
28 test();
29 }
30 core_scheduler().exit(0)
31}
32
33#[test_case]
34fn trivial_test() {
35 println!("Test test test");
36 panic!("Test called");
37}
38
39extern "C" fn initd(_arg: usize) {
41 unsafe extern "C" {
42 #[cfg(all(not(test), not(any(feature = "nostd", feature = "common-os"))))]
43 fn runtime_entry(argc: i32, argv: *const *const u8, env: *const *const u8) -> !;
44 #[cfg(all(not(test), any(feature = "nostd", feature = "common-os")))]
45 fn main(argc: i32, argv: *const *const u8, env: *const *const u8);
46 }
47
48 drivers::init();
50 fs::init();
52 executor::init();
53
54 syscalls::init();
55 #[cfg(feature = "shell")]
56 crate::shell::init();
57
58 #[cfg(not(test))]
60 let (argc, argv, environ) = syscalls::get_application_parameters();
61
62 core_scheduler().reschedule();
64
65 if cfg!(feature = "warn-prebuilt") {
66 warn!("This is a prebuilt Hermit kernel.");
67 warn!("For non-default device drivers and features, consider building a custom kernel.");
68 }
69
70 info!("Jumping into application");
71
72 #[cfg(not(test))]
73 unsafe {
74 #[cfg(all(not(test), not(any(feature = "nostd", feature = "common-os"))))]
76 runtime_entry(argc, argv, environ);
77 #[cfg(all(not(test), any(feature = "nostd", feature = "common-os")))]
78 main(argc, argv, environ);
79 }
80 #[cfg(test)]
81 crate::test_main();
82}
83
84#[cfg(feature = "smp")]
85fn synch_all_cores() {
86 use core::hint;
87 use core::sync::atomic::{AtomicU32, Ordering};
88
89 static CORE_COUNTER: AtomicU32 = AtomicU32::new(0);
90
91 CORE_COUNTER.fetch_add(1, Ordering::SeqCst);
92
93 let possible_cpus = kernel::get_possible_cpus();
94 while CORE_COUNTER.load(Ordering::SeqCst) != possible_cpus {
95 hint::spin_loop();
96 }
97}
98
99pub fn boot_processor_main() -> ! {
101 use crate::config::USER_STACK_SIZE;
102
103 mm::claim_initial_heap();
105 hermit_sync::Lazy::force(&console::CONSOLE);
106 env::init();
107 unsafe {
108 logging::init();
109 }
110
111 info!("Welcome to Hermit {}", env!("CARGO_PKG_VERSION"));
112 if let Some(git_version) = built_info::GIT_VERSION {
113 let dirty = if built_info::GIT_DIRTY == Some(true) {
114 " (dirty)"
115 } else {
116 ""
117 };
118
119 let opt_level = if built_info::OPT_LEVEL == "3" {
120 format_args!("")
121 } else {
122 format_args!(" (opt-level={})", built_info::OPT_LEVEL)
123 };
124
125 info!("Git version: {git_version}{dirty}{opt_level}");
126 }
127 let arch = built_info::TARGET.split_once('-').unwrap().0;
128 info!("Architecture: {arch}");
129 info!("Enabled features: {}", built_info::FEATURES_LOWERCASE_STR);
130 info!("Built on {}", built_info::BUILT_TIME_UTC);
131
132 info!("Executable start: {:p}", elf_symbols::executable_start());
133 info!("ELF header: {:p}", elf_symbols::elf_header());
134 info!("Text segment end: {:p}", elf_symbols::text_end());
135 info!("Data segment end: {:p}", elf_symbols::data_end());
136 info!("Executable end: {:p}", elf_symbols::executable_end());
137
138 if let Some(fdt) = env::fdt() {
139 info!("FDT:\n{fdt:#?}");
140 }
141
142 kernel::boot_processor_init();
143
144 #[cfg(not(target_arch = "riscv64"))]
145 scheduler::add_current_core();
146 interrupts::enable();
147
148 kernel::boot_next_processor();
149
150 #[cfg(feature = "smp")]
151 synch_all_cores();
152
153 #[cfg(feature = "pci")]
154 drivers::pci::print_information();
155
156 unsafe { PerCoreScheduler::spawn(initd, 0, scheduler::task::NORMAL_PRIO, 0, USER_STACK_SIZE) };
158
159 PerCoreScheduler::run();
161}
162
163#[cfg(feature = "smp")]
165pub fn application_processor_main() -> ! {
166 kernel::application_processor_init();
167 #[cfg(not(target_arch = "riscv64"))]
168 scheduler::add_current_core();
169 interrupts::enable();
170 kernel::boot_next_processor();
171
172 debug!("Entering idle loop for application processor");
173
174 synch_all_cores();
175 executor::init();
176
177 PerCoreScheduler::run();
179}
180
181#[panic_handler]
182fn panic(info: &core::panic::PanicInfo<'_>) -> ! {
183 let core_id = core_id();
184 panic_println!("[{core_id}][PANIC] {info}\n");
185
186 scheduler::shutdown(1);
187}