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/example/src/layout.rs b/vmbase/example/src/layout.rs
index b032a30..fc578bc 100644
--- a/vmbase/example/src/layout.rs
+++ b/vmbase/example/src/layout.rs
@@ -15,7 +15,6 @@
//! Memory layout.
use aarch64_paging::paging::{MemoryRegion, VirtualAddress};
-use core::arch::asm;
use core::ops::Range;
use log::info;
use vmbase::layout;
@@ -55,13 +54,3 @@
boot_stack.end - boot_stack.start
);
}
-
-/// Bionic-compatible thread-local storage entry, at the given offset from TPIDR_EL0.
-pub fn bionic_tls(off: usize) -> u64 {
- let mut base: usize;
- unsafe {
- asm!("mrs {base}, tpidr_el0", base = out(reg) base);
- let ptr = (base + off) as *const u64;
- *ptr
- }
-}
diff --git a/vmbase/example/src/main.rs b/vmbase/example/src/main.rs
index 849302d..8aa9f04 100644
--- a/vmbase/example/src/main.rs
+++ b/vmbase/example/src/main.rs
@@ -23,7 +23,7 @@
extern crate alloc;
-use crate::layout::{bionic_tls, boot_stack_range, print_addresses, DEVICE_REGION};
+use crate::layout::{boot_stack_range, print_addresses, DEVICE_REGION};
use crate::pci::{check_pci, get_bar_region};
use aarch64_paging::paging::MemoryRegion;
use aarch64_paging::MapError;
@@ -32,9 +32,9 @@
use libfdt::Fdt;
use log::{debug, error, info, trace, warn, LevelFilter};
use vmbase::{
- configure_heap, cstr,
- layout::{dtb_range, rodata_range, scratch_range, stack_chk_guard, text_range},
- logger, main,
+ bionic, configure_heap, cstr,
+ layout::{dtb_range, rodata_range, scratch_range, text_range},
+ linker, logger, main,
memory::{PageTable, SIZE_64KB},
};
@@ -105,10 +105,18 @@
}
fn check_stack_guard() {
- const BIONIC_TLS_STACK_GRD_OFF: usize = 40;
-
info!("Testing stack guard");
- assert_eq!(bionic_tls(BIONIC_TLS_STACK_GRD_OFF), stack_chk_guard());
+ // SAFETY: No concurrency issue should occur when running these tests.
+ let stack_guard = unsafe { bionic::TLS.stack_guard };
+ assert_ne!(stack_guard, 0);
+ // Check that the TLS and guard are properly accessible from the dedicated register.
+ assert_eq!(stack_guard, bionic::__get_tls().stack_guard);
+ // Check that the LLVM __stack_chk_guard alias is also properly set up.
+ assert_eq!(
+ stack_guard,
+ // SAFETY: No concurrency issue should occur when running these tests.
+ unsafe { linker::__stack_chk_guard },
+ );
}
fn check_data() {