Skip to content
Snippets Groups Projects
Commit c59b94d1 authored by Jeremy Soller's avatar Jeremy Soller
Browse files

Hacks to support aarch64 static TLS

parent b0d3e5b1
No related branches found
No related tags found
No related merge requests found
Pipeline #10545 failed
...@@ -55,7 +55,7 @@ impl Tcb { ...@@ -55,7 +55,7 @@ impl Tcb {
/// Create a new TCB /// Create a new TCB
pub unsafe fn new(size: usize) -> Result<&'static mut Self> { pub unsafe fn new(size: usize) -> Result<&'static mut Self> {
let page_size = Sys::getpagesize(); let page_size = Sys::getpagesize();
let (tls, tcb_page) = Self::os_new(round_up(size, page_size))?; let (abi_page, tls, tcb_page) = Self::os_new(round_up(size, page_size))?;
let tcb_ptr = tcb_page.as_mut_ptr() as *mut Self; let tcb_ptr = tcb_page.as_mut_ptr() as *mut Self;
trace!("New TCB: {:p}", tcb_ptr); trace!("New TCB: {:p}", tcb_ptr);
...@@ -123,8 +123,14 @@ impl Tcb { ...@@ -123,8 +123,14 @@ impl Tcb {
.filter(|m| m.len > 0) .filter(|m| m.len > 0)
.enumerate() .enumerate()
{ {
let range = let range = if cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
self.tls_len - master.offset..self.tls_len - master.offset + master.len; // x86 TLS layout is backwards
self.tls_len - master.offset..self.tls_len - master.offset + master.len
} else {
//TODO: fix aarch64 TLS layout when there is more than one master
assert_eq!(i, 0, "aarch64 TLS layout only supports one master");
0..master.len
};
if let Some(tls_data) = tls.get_mut(range) { if let Some(tls_data) = tls.get_mut(range) {
let data = master.data(); let data = master.data();
trace!( trace!(
...@@ -165,7 +171,7 @@ impl Tcb { ...@@ -165,7 +171,7 @@ impl Tcb {
/// Activate TLS /// Activate TLS
pub unsafe fn activate(&mut self) { pub unsafe fn activate(&mut self) {
Self::os_arch_activate(self.tcb_ptr as usize); Self::os_arch_activate(self.tls_end as usize, self.tls_len);
} }
/// Mapping with correct flags for TCB and TLS /// Mapping with correct flags for TCB and TLS
...@@ -189,23 +195,26 @@ impl Tcb { ...@@ -189,23 +195,26 @@ impl Tcb {
/// OS specific code to create a new TLS and TCB - Linux and Redox /// OS specific code to create a new TLS and TCB - Linux and Redox
#[cfg(any(target_os = "linux", target_os = "redox"))] #[cfg(any(target_os = "linux", target_os = "redox"))]
unsafe fn os_new(size: usize) -> Result<(&'static mut [u8], &'static mut [u8])> { unsafe fn os_new(size: usize) -> Result<(&'static mut [u8], &'static mut [u8], &'static mut [u8])> {
let page_size = Sys::getpagesize(); let page_size = Sys::getpagesize();
let tls_tcb = Self::map(size + page_size)?; let abi_tls_tcb = Self::map(page_size + size + page_size)?;
Ok(tls_tcb.split_at_mut(size)) let (abi, tls_tcb) = abi_tls_tcb.split_at_mut(page_size);
let (tls, tcb) = tls_tcb.split_at_mut(size);
Ok((abi, tls, tcb))
} }
/// Architecture specific code to read a usize from the TCB - aarch64 /// Architecture specific code to read a usize from the TCB - aarch64
#[inline(always)] #[inline(always)]
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
unsafe fn arch_read(offset: usize) -> usize { unsafe fn arch_read(offset: usize) -> usize {
let tp: usize; let abi_ptr: usize;
asm!( asm!(
"mrs {}, tpidr_el0", "mrs {}, tpidr_el0",
out(reg) tp, out(reg) abi_ptr,
); );
*((tp + offset) as *const usize) let tcb_ptr = *(abi_ptr as *const usize);
*((tcb_ptr + offset) as *const usize)
} }
/// Architecture specific code to read a usize from the TCB - x86 /// Architecture specific code to read a usize from the TCB - x86
...@@ -240,33 +249,26 @@ impl Tcb { ...@@ -240,33 +249,26 @@ impl Tcb {
/// OS and architecture specific code to activate TLS - Linux x86_64 /// OS and architecture specific code to activate TLS - Linux x86_64
#[cfg(all(target_os = "linux", target_arch = "x86_64"))] #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
unsafe fn os_arch_activate(tp: usize) { unsafe fn os_arch_activate(tls_end: usize, _tls_len: usize) {
const ARCH_SET_FS: usize = 0x1002; const ARCH_SET_FS: usize = 0x1002;
syscall!(ARCH_PRCTL, ARCH_SET_FS, tp); syscall!(ARCH_PRCTL, ARCH_SET_FS, tls_end);
} }
/// OS and architecture specific code to activate TLS - Redox aarch64 /// OS and architecture specific code to activate TLS - Redox aarch64
#[cfg(all(target_os = "redox", target_arch = "aarch64"))] #[cfg(all(target_os = "redox", target_arch = "aarch64"))]
unsafe fn os_arch_activate(tp: usize) { unsafe fn os_arch_activate(tls_end: usize, tls_len: usize) {
let mut env = syscall::EnvRegisters::default(); // Uses ABI page
let abi_ptr = tls_end - tls_len - 16;
let file = syscall::open("thisproc:current/regs/env", syscall::O_CLOEXEC | syscall::O_RDWR) ptr::write(abi_ptr as *mut usize, tls_end);
.expect_notls("failed to open handle for process registers"); asm!(
"msr tpidr_el0, {}",
let _ = syscall::read(file, &mut env) in(reg) abi_ptr,
.expect_notls("failed to read thread pointer"); );
env.tpidr_el0 = tp;
let _ = syscall::write(file, &env)
.expect_notls("failed to write thread pointer");
let _ = syscall::close(file);
} }
/// OS and architecture specific code to activate TLS - Redox x86 /// OS and architecture specific code to activate TLS - Redox x86
#[cfg(all(target_os = "redox", target_arch = "x86"))] #[cfg(all(target_os = "redox", target_arch = "x86"))]
unsafe fn os_arch_activate(tp: usize) { unsafe fn os_arch_activate(tls_end: usize, _tls_len: usize) {
let mut env = syscall::EnvRegisters::default(); let mut env = syscall::EnvRegisters::default();
let file = syscall::open("thisproc:current/regs/env", syscall::O_CLOEXEC | syscall::O_RDWR) let file = syscall::open("thisproc:current/regs/env", syscall::O_CLOEXEC | syscall::O_RDWR)
...@@ -275,7 +277,7 @@ impl Tcb { ...@@ -275,7 +277,7 @@ impl Tcb {
let _ = syscall::read(file, &mut env) let _ = syscall::read(file, &mut env)
.expect_notls("failed to read gsbase"); .expect_notls("failed to read gsbase");
env.gsbase = tp as u32; env.gsbase = tls_end as u32;
let _ = syscall::write(file, &env) let _ = syscall::write(file, &env)
.expect_notls("failed to write gsbase"); .expect_notls("failed to write gsbase");
...@@ -285,7 +287,7 @@ impl Tcb { ...@@ -285,7 +287,7 @@ impl Tcb {
/// OS and architecture specific code to activate TLS - Redox x86_64 /// OS and architecture specific code to activate TLS - Redox x86_64
#[cfg(all(target_os = "redox", target_arch = "x86_64"))] #[cfg(all(target_os = "redox", target_arch = "x86_64"))]
unsafe fn os_arch_activate(tp: usize) { unsafe fn os_arch_activate(tls_end: usize, _tls_len: usize) {
let mut env = syscall::EnvRegisters::default(); let mut env = syscall::EnvRegisters::default();
let file = syscall::open("thisproc:current/regs/env", syscall::O_CLOEXEC | syscall::O_RDWR) let file = syscall::open("thisproc:current/regs/env", syscall::O_CLOEXEC | syscall::O_RDWR)
...@@ -294,7 +296,7 @@ impl Tcb { ...@@ -294,7 +296,7 @@ impl Tcb {
let _ = syscall::read(file, &mut env) let _ = syscall::read(file, &mut env)
.expect_notls("failed to read fsbase"); .expect_notls("failed to read fsbase");
env.fsbase = tp as u64; env.fsbase = tls_end as u64;
let _ = syscall::write(file, &env) let _ = syscall::write(file, &env)
.expect_notls("failed to write fsbase"); .expect_notls("failed to write fsbase");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment