sel4_runtime_common/
tls.rs

1//
2// Copyright 2023, Colias Group, LLC
3//
4// SPDX-License-Identifier: BSD-2-Clause
5//
6
7use sel4_elf_header::PT_TLS;
8use sel4_panicking_env::abort;
9
10#[allow(unused_imports)]
11use sel4_initialize_tls::{SetThreadPointerFn, UncheckedTlsImage, DEFAULT_SET_THREAD_POINTER_FN};
12
13use crate::locate_phdrs;
14
15#[allow(clippy::missing_safety_doc)]
16pub(crate) unsafe fn with_tls(f: impl FnOnce() -> !) -> ! {
17    let phdr = locate_phdrs()
18        .iter()
19        .find(|phdr| phdr.p_type == PT_TLS)
20        .unwrap_or_else(|| abort!("no PT_TLS segment"));
21    let unchecked = UncheckedTlsImage {
22        vaddr: phdr.p_vaddr,
23        filesz: phdr.p_filesz,
24        memsz: phdr.p_memsz,
25        align: phdr.p_align,
26    };
27    unchecked
28        .check()
29        .unwrap_or_else(|_| abort!("invalid TLS image: {unchecked:#x?}"))
30        .with_initialize_on_stack(CHOSEN_SET_THREAD_POINTER_FN, f)
31}
32
33sel4::sel4_cfg_if! {
34    if #[sel4_cfg(all(ARCH_X86_64, SET_TLS_BASE_SELF))] {
35        const CHOSEN_SET_THREAD_POINTER_FN: SetThreadPointerFn = set_thread_pointer_via_syscall;
36
37        unsafe extern "C" fn set_thread_pointer_via_syscall(val: usize) {
38            sel4::set_tls_base(val);
39        }
40    } else {
41        const CHOSEN_SET_THREAD_POINTER_FN: SetThreadPointerFn = DEFAULT_SET_THREAD_POINTER_FN;
42    }
43}
44
45#[cfg(target_arch = "arm")]
46#[no_mangle]
47extern "C" fn __aeabi_read_tp() -> usize {
48    let mut val: usize;
49    unsafe {
50        core::arch::asm!("mrc p15, 0, {val}, c13, c0, 2", val = out(reg) val); // tpidrurw
51    }
52    val
53}