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