1#![cfg_attr(not(test), no_std)]
20#![feature(doc_auto_cfg)]
21
22#[macro_use]
23extern crate axlog;
24
25#[cfg(all(target_os = "none", not(test)))]
26mod lang_items;
27
28#[cfg(feature = "smp")]
29mod mp;
30
31#[cfg(feature = "smp")]
32pub use self::mp::rust_main_secondary;
33
34const LOGO: &str = r#"
35 d8888 .d88888b. .d8888b.
36 d88888 d88P" "Y88b d88P Y88b
37 d88P888 888 888 Y88b.
38 d88P 888 888d888 .d8888b .d88b. 888 888 "Y888b.
39 d88P 888 888P" d88P" d8P Y8b 888 888 "Y88b.
40 d88P 888 888 888 88888888 888 888 "888
41 d8888888888 888 Y88b. Y8b. Y88b. .d88P Y88b d88P
42d88P 888 888 "Y8888P "Y8888 "Y88888P" "Y8888P"
43"#;
44
45unsafe extern "C" {
46 fn main();
48}
49
50struct LogIfImpl;
51
52#[crate_interface::impl_interface]
53impl axlog::LogIf for LogIfImpl {
54 fn console_write_str(s: &str) {
55 axhal::console::write_bytes(s.as_bytes());
56 }
57
58 fn current_time() -> core::time::Duration {
59 axhal::time::monotonic_time()
60 }
61
62 fn current_cpu_id() -> Option<usize> {
63 #[cfg(feature = "smp")]
64 if is_init_ok() {
65 Some(axhal::percpu::this_cpu_id())
66 } else {
67 None
68 }
69 #[cfg(not(feature = "smp"))]
70 Some(0)
71 }
72
73 fn current_task_id() -> Option<u64> {
74 if is_init_ok() {
75 #[cfg(feature = "multitask")]
76 {
77 axtask::current_may_uninit().map(|curr| curr.id().as_u64())
78 }
79 #[cfg(not(feature = "multitask"))]
80 None
81 } else {
82 None
83 }
84 }
85}
86
87use core::sync::atomic::{AtomicUsize, Ordering};
88
89static INITED_CPUS: AtomicUsize = AtomicUsize::new(0);
91
92fn is_init_ok() -> bool {
93 INITED_CPUS.load(Ordering::Acquire) == axhal::cpu_num()
94}
95
96#[cfg_attr(not(test), axplat::main)]
107pub fn rust_main(cpu_id: usize, arg: usize) -> ! {
108 unsafe { axhal::mem::clear_bss() };
109 axhal::init_percpu(cpu_id);
110 axhal::init_early(cpu_id, arg);
111
112 ax_println!("{}", LOGO);
113 ax_println!(
114 "\
115 arch = {}\n\
116 platform = {}\n\
117 target = {}\n\
118 build_mode = {}\n\
119 log_level = {}\n\
120 ",
121 axconfig::ARCH,
122 axconfig::PLATFORM,
123 option_env!("AX_TARGET").unwrap_or(""),
124 option_env!("AX_MODE").unwrap_or(""),
125 option_env!("AX_LOG").unwrap_or(""),
126 );
127 #[cfg(feature = "rtc")]
128 ax_println!(
129 "Boot at {}\n",
130 chrono::DateTime::from_timestamp_nanos(axhal::time::wall_time_nanos() as _),
131 );
132
133 axlog::init();
134 axlog::set_max_level(option_env!("AX_LOG").unwrap_or("")); info!("Logging is enabled.");
136 info!("Primary CPU {} started, arg = {:#x}.", cpu_id, arg);
137
138 axhal::mem::init();
139 info!("Found physcial memory regions:");
140 for r in axhal::mem::memory_regions() {
141 info!(
142 " [{:x?}, {:x?}) {} ({:?})",
143 r.paddr,
144 r.paddr + r.size,
145 r.name,
146 r.flags
147 );
148 }
149
150 #[cfg(feature = "alloc")]
151 init_allocator();
152
153 #[cfg(feature = "paging")]
154 axmm::init_memory_management();
155
156 info!("Initialize platform devices...");
157 axhal::init_later(cpu_id, arg);
158
159 #[cfg(feature = "multitask")]
160 axtask::init_scheduler();
161
162 #[cfg(any(feature = "fs", feature = "net", feature = "display"))]
163 {
164 #[allow(unused_variables)]
165 let all_devices = axdriver::init_drivers();
166
167 #[cfg(feature = "fs")]
168 axfs::init_filesystems(all_devices.block);
169
170 #[cfg(feature = "net")]
171 axnet::init_network(all_devices.net);
172
173 #[cfg(feature = "display")]
174 axdisplay::init_display(all_devices.display);
175 }
176
177 #[cfg(feature = "smp")]
178 self::mp::start_secondary_cpus(cpu_id);
179
180 #[cfg(feature = "irq")]
181 {
182 info!("Initialize interrupt handlers...");
183 init_interrupt();
184 }
185
186 #[cfg(all(feature = "tls", not(feature = "multitask")))]
187 {
188 info!("Initialize thread local storage...");
189 init_tls();
190 }
191
192 ctor_bare::call_ctors();
193
194 info!("Primary CPU {} init OK.", cpu_id);
195 INITED_CPUS.fetch_add(1, Ordering::Release);
196
197 while !is_init_ok() {
198 core::hint::spin_loop();
199 }
200
201 unsafe { main() };
202
203 #[cfg(feature = "multitask")]
204 axtask::exit(0);
205 #[cfg(not(feature = "multitask"))]
206 {
207 debug!("main task exited: exit_code={}", 0);
208 axhal::power::system_off();
209 }
210}
211
212#[cfg(feature = "alloc")]
213fn init_allocator() {
214 use axhal::mem::{MemRegionFlags, memory_regions, phys_to_virt};
215
216 info!("Initialize global memory allocator...");
217 info!(" use {} allocator.", axalloc::global_allocator().name());
218
219 let mut max_region_size = 0;
220 let mut max_region_paddr = 0.into();
221 for r in memory_regions() {
222 if r.flags.contains(MemRegionFlags::FREE) && r.size > max_region_size {
223 max_region_size = r.size;
224 max_region_paddr = r.paddr;
225 }
226 }
227 for r in memory_regions() {
228 if r.flags.contains(MemRegionFlags::FREE) && r.paddr == max_region_paddr {
229 axalloc::global_init(phys_to_virt(r.paddr).as_usize(), r.size);
230 break;
231 }
232 }
233 for r in memory_regions() {
234 if r.flags.contains(MemRegionFlags::FREE) && r.paddr != max_region_paddr {
235 axalloc::global_add_memory(phys_to_virt(r.paddr).as_usize(), r.size)
236 .expect("add heap memory region failed");
237 }
238 }
239}
240
241#[cfg(feature = "irq")]
242fn init_interrupt() {
243 const PERIODIC_INTERVAL_NANOS: u64 =
245 axhal::time::NANOS_PER_SEC / axconfig::TICKS_PER_SEC as u64;
246
247 #[percpu::def_percpu]
248 static NEXT_DEADLINE: u64 = 0;
249
250 fn update_timer() {
251 let now_ns = axhal::time::monotonic_time_nanos();
252 let mut deadline = unsafe { NEXT_DEADLINE.read_current_raw() };
254 if now_ns >= deadline {
255 deadline = now_ns + PERIODIC_INTERVAL_NANOS;
256 }
257 unsafe { NEXT_DEADLINE.write_current_raw(deadline + PERIODIC_INTERVAL_NANOS) };
258 axhal::time::set_oneshot_timer(deadline);
259 }
260
261 axhal::irq::register(axconfig::devices::TIMER_IRQ, || {
262 update_timer();
263 #[cfg(feature = "multitask")]
264 axtask::on_timer_tick();
265 });
266
267 #[cfg(feature = "ipi")]
268 axhal::irq::register(axhal::irq::IPI_IRQ, || {
269 axipi::ipi_handler();
270 });
271
272 axhal::asm::enable_irqs();
274}
275
276#[cfg(all(feature = "tls", not(feature = "multitask")))]
277fn init_tls() {
278 let main_tls = axhal::tls::TlsArea::alloc();
279 unsafe { axhal::asm::write_thread_pointer(main_tls.tls_ptr() as usize) };
280 core::mem::forget(main_tls);
281}