Skip to content

Commit

Permalink
Update asm:
Browse files Browse the repository at this point in the history
- for __eabi_read_tp, simplify to just directly load TLS_CORE_[01]
  as needed without the need for an indirection. This only uses r0
  and doesn't touch the stack.
- Write the tdata copy in Rust, being careful to only use raw pointers.
  The generated asm is functionally identical to the hand-written asm.
  • Loading branch information
jsgf committed Apr 21, 2024
1 parent 5716506 commit 45aeac8
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 40 deletions.
4 changes: 3 additions & 1 deletion rp2040-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ bitfield = { version = "0.14.0" }

i2c-write-iter = { version = "1.0.0", features = ["async"], optional = true }

cortex-m-rt = { version = "0.7", optional = true }

[dev-dependencies]
cortex-m-rt = "0.7"
cortex-m-rtic = "1.1.4"
Expand Down Expand Up @@ -107,7 +109,7 @@ rtic-monotonic = ["dep:rtic-monotonic"]
i2c-write-iter = ["dep:i2c-write-iter"]

# Enable use of thread-local variables for multicore state
thread_local = []
thread_local = ["dep:cortex-m-rt"]

[[example]]
# irq example uses cortex-m-rt::interrupt, need rt feature for that
Expand Down
61 changes: 22 additions & 39 deletions rp2040-hal/src/multicore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,18 +335,14 @@ impl<'p> Core<'p> {
#[cfg(all(target_arch = "arm", feature = "thread_local"))]
mod thread_local {
use core::arch::global_asm;
use core::ptr::addr_of;
use core::ptr::{addr_of, addr_of_mut};

extern "C" {
static TLS_CORE_0: u8;
static TLS_CORE_1: u8;
static mut TLS_CORE_0: u8;
static mut TLS_CORE_1: u8;
static __tdata_start: u8;
static __tdata_len: u8;
}
// Not really a const pointer, but we reform it into mut in the asm
static mut TLS_STATE: [*const u8; 2] = [
// Point to linker-allocated space in .bss
unsafe { addr_of!(TLS_CORE_0) },
unsafe { addr_of!(TLS_CORE_1) },
];

// Define `__aeabi_read_tp` called by the compiler to get access to
// thread-local storage.
Expand All @@ -358,41 +354,28 @@ mod thread_local {
".type __aeabi_read_tp,%function",

"__aeabi_read_tp:",
" push {{r1, lr}}",
" ldr r1, =0xd0000000", // Load SIO CPUID addr
" ldr r1, [r1]", // Get current CPUID
" lsls r1, r1, #2", // Scale by 4
" ldr r0, ={tls_state}", // Load TLS_STATE base addr
" ldr r0, [r0, r1]", // Load CPU per-thread
" pop {{r1, pc}}",
" ldr r0, =0xd0000000", // Load SIO CPUID addr
" ldr r0, [r0]", // Load CPUID
" cmp r0, #0", // Check core 0
" ldr r0, ={core_0}", // Set TLS_CORE_0
" beq 1f", // skip if done
" ldr r0, ={core_1}", // Set TLS_CORE_1
"1: bx lr",

".popsection",
tls_state = sym TLS_STATE,
core_0 = sym TLS_CORE_0,
core_1 = sym TLS_CORE_1,
}

// Intercept __pre_init to hook into the startup code to copy the tdata into
// TLS_CORE_[01].
global_asm! {
".pushsection .text.__pre_init",
".align 4",
".p2align 4,,15",
".global __pre_init",
".type __pre_init,%function",

"__pre_init:",
" push {{lr}}",
" ldr r0, ={tls_core_0}",
" ldr r1, =__tdata_start",
" ldr r2, =__tdata_len",
" bl __aeabi_memcpy",
" ldr r0, ={tls_core_1}",
" ldr r1, =__tdata_start",
" ldr r2, =__tdata_len",
" bl __aeabi_memcpy",
" pop {{pc}}",

".popsection",
tls_core_0 = sym TLS_CORE_0,
tls_core_1 = sym TLS_CORE_1,
//
// NB: Run as the very first thing, nothing has been initialized and memory
// could be in arbitrary state, so we only deal with things via raw pointers.
#[cortex_m_rt::pre_init]
unsafe fn tls_pre_init_hook() {
for dst in [ addr_of_mut!(TLS_CORE_0), addr_of_mut!(TLS_CORE_1) ] {
core::ptr::copy(addr_of!(__tdata_start), dst, addr_of!(__tdata_len) as usize);
}
}
}

0 comments on commit 45aeac8

Please sign in to comment.