moana_std 0.1.4

moana 用户标准库
Documentation
//! C Runtime 初始化
//!
//! `_start` (由 `#[moana_std::main]` 生成) 调用 `__moana_crt_init`,
//! 流程:ctors → `rt_init` → main → dtors → exit。

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();
}

/// `sp`:`_start` 透传的初始用户栈顶(来自内核 `init_user`)。预留给将来内核在栈上放置的
/// 启动数据(argc/argv/envp/auxv 之类);当前尚无该约定,暂未使用。
#[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);
}