sel4_runtime_common/
lib.rs

1//
2// Copyright 2023, Colias Group, LLC
3//
4// SPDX-License-Identifier: BSD-2-Clause
5//
6
7#![no_std]
8#![feature(cfg_target_thread_local)]
9#![feature(never_type)]
10#![feature(core_intrinsics)]
11#![feature(linkage)]
12#![allow(internal_features)]
13
14use core::sync::atomic::{AtomicBool, Ordering};
15
16use sel4_elf_header::{ElfHeader, ProgramHeader};
17use sel4_panicking_env::abort;
18
19mod abort;
20mod start;
21
22#[cfg(target_thread_local)]
23mod tls;
24
25#[cfg(panic = "unwind")]
26mod unwinding;
27
28#[cfg(not(any(
29    target_arch = "aarch64",
30    target_arch = "arm",
31    target_arch = "riscv64",
32    target_arch = "riscv32",
33    target_arch = "x86_64",
34)))]
35compile_error!("unsupported architecture");
36
37#[allow(clippy::missing_safety_doc)]
38pub unsafe fn with_local_init(f: impl FnOnce() -> !) -> ! {
39    cfg_if::cfg_if! {
40        if #[cfg(target_thread_local)] {
41            unsafe {
42                tls::with_tls(f)
43            }
44        } else {
45            f()
46        }
47    }
48}
49
50static GLOBAL_INIT_COMPLETE: AtomicBool = AtomicBool::new(false);
51
52unsafe fn global_init() {
53    #[cfg(panic = "unwind")]
54    {
55        unwinding::init_unwinding();
56    }
57
58    sel4_ctors_dtors::run_ctors().unwrap_or_else(|err| abort!("{err}"));
59
60    GLOBAL_INIT_COMPLETE.swap(true, Ordering::Release);
61}
62
63pub fn global_init_complete() -> bool {
64    GLOBAL_INIT_COMPLETE.load(Ordering::Acquire)
65}
66
67#[allow(dead_code)]
68fn locate_phdrs() -> &'static [ProgramHeader] {
69    unsafe extern "C" {
70        static __ehdr_start: ElfHeader;
71    }
72    unsafe {
73        if !__ehdr_start.is_magic_valid() {
74            abort!("ELF header magic mismatch")
75        }
76        __ehdr_start.locate_phdrs()
77    }
78}
79
80#[cfg(target_arch = "arm")]
81#[linkage = "weak"]
82#[unsafe(no_mangle)]
83extern "C" fn __aeabi_read_tp() -> usize {
84    let mut val: usize;
85    unsafe {
86        core::arch::asm!("mrc p15, 0, {val}, c13, c0, 2", val = out(reg) val); // tpidrurw
87    }
88    val
89}
90
91#[doc(hidden)]
92#[allow(unreachable_code)]
93pub unsafe fn _run_entrypoint(global_init_cond: bool, f: impl FnOnce() -> !) -> ! {
94    unsafe {
95        with_local_init(|| {
96            if global_init_cond {
97                global_init();
98            }
99            f()
100        });
101    }
102}
103
104#[doc(hidden)]
105pub mod _private {
106    pub use super::_run_entrypoint;
107    pub use cfg_if::cfg_if;
108    pub use core::arch::global_asm;
109    pub use sel4_stack::{Stack, StackBottom};
110}