use crate::sys;
unsafe extern "Rust" {
fn __moana_user_main();
}
unsafe extern "C" {
static __init_array_start: unsafe extern "C" fn();
static __init_array_end: unsafe extern "C" fn();
static __fini_array_start: unsafe extern "C" fn();
static __fini_array_end: unsafe extern "C" fn();
static __tdata_start: u8;
static __tdata_end: u8;
static __tbss_start: u8;
static __tbss_end: u8;
}
unsafe fn run_array(start: *const unsafe extern "C" fn(), end: *const unsafe extern "C" fn()) {
let mut p = start;
while p < end {
let f = unsafe { p.read() };
unsafe { f() };
p = unsafe { p.add(1) };
}
}
struct SyncCell(core::cell::UnsafeCell<[u8; 4096]>);
unsafe impl Sync for SyncCell {}
static TLS_AREA: SyncCell = SyncCell(core::cell::UnsafeCell::new([0; 4096]));
fn tls_init() {
let tdata_start = &raw const __tdata_start as usize;
let tdata_end = &raw const __tdata_end as usize;
let tbss_end = &raw const __tbss_end as usize;
let tls_size = tbss_end - tdata_start;
if tls_size == 0 {
return;
}
let tdata_len = tdata_end - tdata_start;
unsafe {
let dst = TLS_AREA.0.get().cast::<u8>();
core::ptr::copy_nonoverlapping(tdata_start as *const u8, dst, tdata_len);
core::ptr::write_bytes(dst.add(tdata_len), 0, tls_size - tdata_len);
core::cfg_select! {
aarch64_moana_std => {
core::arch::asm!("msr tpidr_el0, {0}", in(reg) dst);
}
riscv64_moana_std => {
core::arch::asm!("mv tp, {0}", in(reg) dst);
}
_ => {}
}
}
}
fn rt_init() {
tls_init();
}
#[unsafe(no_mangle)]
extern "C" fn __moana_crt_init(_sp: usize) -> ! {
unsafe { run_array(&raw const __init_array_start, &raw const __init_array_end) };
rt_init();
unsafe { __moana_user_main() };
unsafe { run_array(&raw const __fini_array_start, &raw const __fini_array_end) };
sys::misc::exit(0, moa_uapi::task::ExitFlags::GROUP);
}