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);
90
91fn is_init_ok() -> bool {
92 INITED_CPUS.load(Ordering::Acquire) == axconfig::plat::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 smp = {}\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 axconfig::plat::CPU_NUM,
127 );
128 #[cfg(feature = "rtc")]
129 ax_println!(
130 "Boot at {}\n",
131 chrono::DateTime::from_timestamp_nanos(axhal::time::wall_time_nanos() as _),
132 );
133
134 axlog::init();
135 axlog::set_max_level(option_env!("AX_LOG").unwrap_or("")); info!("Logging is enabled.");
137 info!("Primary CPU {} started, arg = {:#x}.", cpu_id, arg);
138
139 axhal::mem::init();
140 info!("Found physcial memory regions:");
141 for r in axhal::mem::memory_regions() {
142 info!(
143 " [{:x?}, {:x?}) {} ({:?})",
144 r.paddr,
145 r.paddr + r.size,
146 r.name,
147 r.flags
148 );
149 }
150
151 #[cfg(feature = "alloc")]
152 init_allocator();
153
154 #[cfg(feature = "paging")]
155 axmm::init_memory_management();
156
157 info!("Initialize platform devices...");
158 axhal::init_later(cpu_id, arg);
159
160 #[cfg(feature = "multitask")]
161 axtask::init_scheduler();
162
163 #[cfg(any(feature = "fs", feature = "net", feature = "display"))]
164 {
165 #[allow(unused_variables)]
166 let all_devices = axdriver::init_drivers();
167
168 #[cfg(feature = "fs")]
169 axfs::init_filesystems(all_devices.block);
170
171 #[cfg(feature = "net")]
172 axnet::init_network(all_devices.net);
173
174 #[cfg(feature = "display")]
175 axdisplay::init_display(all_devices.display);
176 }
177
178 #[cfg(feature = "smp")]
179 self::mp::start_secondary_cpus(cpu_id);
180
181 #[cfg(feature = "irq")]
182 {
183 info!("Initialize interrupt handlers...");
184 init_interrupt();
185 }
186
187 #[cfg(all(feature = "tls", not(feature = "multitask")))]
188 {
189 info!("Initialize thread local storage...");
190 init_tls();
191 }
192
193 ctor_bare::call_ctors();
194
195 info!("Primary CPU {} init OK.", cpu_id);
196 INITED_CPUS.fetch_add(1, Ordering::Release);
197
198 while !is_init_ok() {
199 core::hint::spin_loop();
200 }
201
202 unsafe { main() };
203
204 #[cfg(feature = "multitask")]
205 axtask::exit(0);
206 #[cfg(not(feature = "multitask"))]
207 {
208 debug!("main task exited: exit_code={}", 0);
209 axhal::power::system_off();
210 }
211}
212
213#[cfg(feature = "alloc")]
214fn init_allocator() {
215 use axhal::mem::{MemRegionFlags, memory_regions, phys_to_virt};
216
217 info!("Initialize global memory allocator...");
218 info!(" use {} allocator.", axalloc::global_allocator().name());
219
220 let mut max_region_size = 0;
221 let mut max_region_paddr = 0.into();
222 for r in memory_regions() {
223 if r.flags.contains(MemRegionFlags::FREE) && r.size > max_region_size {
224 max_region_size = r.size;
225 max_region_paddr = r.paddr;
226 }
227 }
228 for r in memory_regions() {
229 if r.flags.contains(MemRegionFlags::FREE) && r.paddr == max_region_paddr {
230 axalloc::global_init(phys_to_virt(r.paddr).as_usize(), r.size);
231 break;
232 }
233 }
234 for r in memory_regions() {
235 if r.flags.contains(MemRegionFlags::FREE) && r.paddr != max_region_paddr {
236 axalloc::global_add_memory(phys_to_virt(r.paddr).as_usize(), r.size)
237 .expect("add heap memory region failed");
238 }
239 }
240}
241
242#[cfg(feature = "irq")]
243fn init_interrupt() {
244 const PERIODIC_INTERVAL_NANOS: u64 =
246 axhal::time::NANOS_PER_SEC / axconfig::TICKS_PER_SEC as u64;
247
248 #[percpu::def_percpu]
249 static NEXT_DEADLINE: u64 = 0;
250
251 fn update_timer() {
252 let now_ns = axhal::time::monotonic_time_nanos();
253 let mut deadline = unsafe { NEXT_DEADLINE.read_current_raw() };
255 if now_ns >= deadline {
256 deadline = now_ns + PERIODIC_INTERVAL_NANOS;
257 }
258 unsafe { NEXT_DEADLINE.write_current_raw(deadline + PERIODIC_INTERVAL_NANOS) };
259 axhal::time::set_oneshot_timer(deadline);
260 }
261
262 axhal::irq::register(axconfig::devices::TIMER_IRQ, || {
263 update_timer();
264 #[cfg(feature = "multitask")]
265 axtask::on_timer_tick();
266 });
267
268 axhal::asm::enable_irqs();
270}
271
272#[cfg(all(feature = "tls", not(feature = "multitask")))]
273fn init_tls() {
274 let main_tls = axhal::tls::TlsArea::alloc();
275 unsafe { axhal::asm::write_thread_pointer(main_tls.tls_ptr() as usize) };
276 core::mem::forget(main_tls);
277}