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