vmbase: Define Bionic TLS from Rust
Move the definition of __bionic_tls to Rust and generalize accessing it
through the TPIDR_EL0 in vmbase::bionic, reducing the amount of ASM we
have and giving typed accesses to the TLS from Rust.
Use the linker script to now define __stack_chk_guard at an offset from
__bionic_tls, which can't be done from Rust.
Note that TPIDR_EL0 can't be configured from rust_entry because the
compiler will dereference it during function entry to access
__stack_chk_guard and Rust doesn't support LLVM's
__attribute__((no_stack_protector)).
Test: atest DebugPolicyHostTests#testNoAdbInDebugPolicy_withDebugLevelNone_boots
Test: atest rialto_test vmbase_example.integration_test
Change-Id: Ife1e43a972758bff1cace87d80319465bb643e6d
diff --git a/vmbase/src/bionic.rs b/vmbase/src/bionic.rs
index 5af9ebc..2ce0e83 100644
--- a/vmbase/src/bionic.rs
+++ b/vmbase/src/bionic.rs
@@ -23,9 +23,36 @@
use crate::console;
use crate::eprintln;
+use crate::read_sysreg;
const EOF: c_int = -1;
+/// Bionic thread-local storage.
+#[repr(C)]
+pub struct Tls {
+ /// Unused.
+ _unused: [u8; 40],
+ /// Use by the compiler as stack canary value.
+ pub stack_guard: u64,
+}
+
+/// Bionic TLS.
+///
+/// Provides the TLS used by Bionic code. This is unique as vmbase only supports one thread.
+///
+/// Note that the linker script re-exports __bionic_tls.stack_guard as __stack_chk_guard for
+/// compatibility with non-Bionic LLVM.
+#[link_section = ".data.stack_protector"]
+#[export_name = "__bionic_tls"]
+pub static mut TLS: Tls = Tls { _unused: [0; 40], stack_guard: 0 };
+
+/// Gets a reference to the TLS from the dedicated system register.
+pub fn __get_tls() -> &'static mut Tls {
+ let tpidr = read_sysreg!("tpidr_el0");
+ // SAFETY: The register is currently only written to once, from entry.S, with a valid value.
+ unsafe { &mut *(tpidr as *mut Tls) }
+}
+
#[no_mangle]
extern "C" fn __stack_chk_fail() -> ! {
panic!("stack guard check failed");