Merge branch 'master' into 'master'

tcb: fix non x86

See merge request redox-os/relibc!650
This commit is contained in:
Jeremy Soller
2025-04-19 16:51:43 +00:00
2 changed files with 74 additions and 21 deletions
+4 -4
View File
@@ -662,8 +662,7 @@ impl Linker {
// We are now loading the main program or its dependencies. The TLS for all initially
// loaded objects reside in the static TLS block. Depending on the architecture, the
// static TLS block is either placed before the TP or after the TP.
let tcb_ptr = tcb as *mut Tcb;
//
// Setup the DTVs.
tcb.setup_dtv(tcb_masters.len());
@@ -677,7 +676,7 @@ impl Linker {
if cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
// Below the TP
tcb.dtv_mut()[dtv_idx] = tcb_ptr.cast::<u8>().sub(obj.tls_offset);
tcb.dtv_mut()[dtv_idx] = tcb.tls_end.sub(obj.tls_offset);
} else {
// FIMXE(andypython): Make it above the TP
//
@@ -685,7 +684,8 @@ impl Linker {
// tcb_ptr.add(1).cast::<u8>().add(obj.tls_offset);
//
// FIXME(andypython): https://gitlab.redox-os.org/redox-os/relibc/-/merge_requests/570#note_35788
tcb.dtv_mut()[dtv_idx] = tcb.tls_end.sub(tcb.tls_len).add(obj.tls_offset);
let tls_start = tcb.tls_end.sub(tcb.tls_len);
tcb.dtv_mut()[dtv_idx] = tls_start.add(obj.tls_offset);
}
}
+70 -17
View File
@@ -126,22 +126,22 @@ impl Tcb {
if self.tls_end.is_null() || self.tls_len == 0 {
None
} else {
Some(slice::from_raw_parts_mut(
self.tls_end.offset(-(self.tls_len as isize)),
self.tls_len,
))
let tls_start = self.tls_end.sub(self.tls_len);
Some(slice::from_raw_parts_mut(tls_start, self.tls_len))
}
}
/// The initial images for TLS
pub unsafe fn masters(&self) -> Option<&'static mut [Master]> {
pub fn masters(&self) -> Option<&'static mut [Master]> {
if self.masters_ptr.is_null() || self.masters_len == 0 {
None
} else {
Some(slice::from_raw_parts_mut(
self.masters_ptr,
self.masters_len / mem::size_of::<Master>(),
))
Some(unsafe {
slice::from_raw_parts_mut(
self.masters_ptr,
self.masters_len / mem::size_of::<Master>(),
)
})
}
}
@@ -150,19 +150,16 @@ impl Tcb {
//TODO: Complain if masters or tls exist without the other
if let Some(tls) = self.tls() {
if let Some(masters) = self.masters() {
for (i, master) in masters
for master in masters
.iter()
.skip(self.num_copied_masters)
.filter(|m| m.len > 0)
.enumerate()
.filter(|master| master.len != 0)
{
let range = if cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
// x86 TLS layout is backwards
// x86{_64} 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
master.offset..master.offset + master.len
};
if let Some(tls_data) = tls.get_mut(range) {
let data = master.data();
@@ -211,7 +208,22 @@ impl Tcb {
pub fn setup_dtv(&mut self, n: usize) {
if self.dtv_ptr.is_null() {
let dtv = vec![ptr::null_mut(); n];
let mut dtv = vec![ptr::null_mut(); n];
if let Some(masters) = self.masters() {
for (i, master) in masters.iter().enumerate() {
let tls = unsafe { self.tls().unwrap() };
let offset = if cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
// x86{_64} TLS layout is backwards
self.tls_len - master.offset
} else {
master.offset
};
dtv[i] = unsafe { tls.as_mut_ptr().add(offset) };
}
}
let (ptr, len, _) = dtv.into_raw_parts();
self.dtv_ptr = ptr;
@@ -255,6 +267,47 @@ impl Tcb {
}
/// OS specific code to create a new TLS and TCB - Linux and Redox
///
/// Memory layout:
///
/// ```text
/// 0 page_size size (size + page_size * 2)
/// |----------|---------------------------|----------|
/// +++++++++++++++++++++++++++++++++++++++++++++++++++
/// | ABI Page | TLS | TCB Page |
/// +++++++++++++++++++++++++++++++++++++++++++++++++++
/// ^ $tp (aarch64) ^ $tp (x86_64)
/// ```
///
/// `$tp` refers to the architecture specific thread pointer.
///
/// **Note**: On x86{_64}, the TLS layout is backwards (i.e. the first byte of the TLS is at
/// the end of the TLS region).
///
/// ABI page layout for aarch64:
/// ```text
/// 0 4096
/// +---------------------+
/// | ABI Page |
/// +---------------------+
/// ^
/// |
/// +-------> (page_size - 16): pointer to the start of the TCB page
/// ```
///
/// ABI page layout for riscv64:
///
/// ```text
/// 0 4096
/// +---------------------+
/// | ABI Page |
/// +---------------------+
/// ^
/// |
/// +-------> (page_size - 8): pointer to the start of the TCB page
/// ```
///
/// For x86_64, the ABI page is not used.
#[cfg(any(target_os = "linux", target_os = "redox"))]
unsafe fn os_new(
size: usize,