From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- library/std/src/sys/sgx/abi/mod.rs | 108 +++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 library/std/src/sys/sgx/abi/mod.rs (limited to 'library/std/src/sys/sgx/abi/mod.rs') diff --git a/library/std/src/sys/sgx/abi/mod.rs b/library/std/src/sys/sgx/abi/mod.rs new file mode 100644 index 000000000..9508c3874 --- /dev/null +++ b/library/std/src/sys/sgx/abi/mod.rs @@ -0,0 +1,108 @@ +#![cfg_attr(test, allow(unused))] // RT initialization logic is not compiled for test + +use crate::io::Write; +use core::arch::global_asm; +use core::sync::atomic::{AtomicUsize, Ordering}; + +// runtime features +pub(super) mod panic; +mod reloc; + +// library features +pub mod mem; +pub mod thread; +pub mod tls; +#[macro_use] +pub mod usercalls; + +#[cfg(not(test))] +global_asm!(include_str!("entry.S"), options(att_syntax)); + +#[repr(C)] +struct EntryReturn(u64, u64); + +#[cfg(not(test))] +#[no_mangle] +unsafe extern "C" fn tcs_init(secondary: bool) { + // Be very careful when changing this code: it runs before the binary has been + // relocated. Any indirect accesses to symbols will likely fail. + const UNINIT: usize = 0; + const BUSY: usize = 1; + const DONE: usize = 2; + // Three-state spin-lock + static RELOC_STATE: AtomicUsize = AtomicUsize::new(UNINIT); + + if secondary && RELOC_STATE.load(Ordering::Relaxed) != DONE { + rtabort!("Entered secondary TCS before main TCS!") + } + + // Try to atomically swap UNINIT with BUSY. The returned state can be: + match RELOC_STATE.compare_exchange(UNINIT, BUSY, Ordering::Acquire, Ordering::Acquire) { + // This thread just obtained the lock and other threads will observe BUSY + Ok(_) => { + reloc::relocate_elf_rela(); + RELOC_STATE.store(DONE, Ordering::Release); + } + // We need to wait until the initialization is done. + Err(BUSY) => { + while RELOC_STATE.load(Ordering::Acquire) == BUSY { + core::hint::spin_loop(); + } + } + // Initialization is done. + Err(DONE) => {} + _ => unreachable!(), + } +} + +// FIXME: this item should only exist if this is linked into an executable +// (main function exists). If this is a library, the crate author should be +// able to specify this +#[cfg(not(test))] +#[no_mangle] +extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> EntryReturn { + // FIXME: how to support TLS in library mode? + let tls = Box::new(tls::Tls::new()); + let tls_guard = unsafe { tls.activate() }; + + if secondary { + let join_notifier = super::thread::Thread::entry(); + drop(tls_guard); + drop(join_notifier); + + EntryReturn(0, 0) + } else { + extern "C" { + fn main(argc: isize, argv: *const *const u8) -> isize; + } + + // check entry is being called according to ABI + rtassert!(p3 == 0); + rtassert!(p4 == 0); + rtassert!(p5 == 0); + + unsafe { + // The actual types of these arguments are `p1: *const Arg, p2: + // usize`. We can't currently customize the argument list of Rust's + // main function, so we pass these in as the standard pointer-sized + // values in `argc` and `argv`. + let ret = main(p2 as _, p1 as _); + exit_with_code(ret) + } + } +} + +pub(super) fn exit_with_code(code: isize) -> ! { + if code != 0 { + if let Some(mut out) = panic::SgxPanicOutput::new() { + let _ = write!(out, "Exited with status code {code}"); + } + } + usercalls::exit(code != 0); +} + +#[cfg(not(test))] +#[no_mangle] +extern "C" fn abort_reentry() -> ! { + usercalls::exit(false) +} -- cgit v1.2.3