From 58d1153536793565ceb13feb17f66e835c4f6251 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 20 Jun 2024 22:38:36 +0200 Subject: [PATCH] Split part of TCB into generic-rt --- Cargo.lock | 6 +++ Cargo.toml | 2 + generic-rt/Cargo.toml | 6 +++ generic-rt/src/lib.rs | 73 +++++++++++++++++++++++++ redox-rt/Cargo.toml | 2 + redox-rt/src/arch/x86_64.rs | 3 +- redox-rt/src/signal.rs | 17 ++++-- src/ld_so/tcb.rs | 103 +++++++++++------------------------- src/start.rs | 2 +- 9 files changed, 135 insertions(+), 79 deletions(-) create mode 100644 generic-rt/Cargo.toml create mode 100644 generic-rt/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index fc8e8ae2d7..7164fbfd51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -143,6 +143,10 @@ dependencies = [ "version_check", ] +[[package]] +name = "generic-rt" +version = "0.1.0" + [[package]] name = "goblin" version = "0.7.1" @@ -362,6 +366,7 @@ name = "redox-rt" version = "0.1.0" dependencies = [ "bitflags", + "generic-rt", "goblin", "plain", "redox_syscall", @@ -395,6 +400,7 @@ dependencies = [ "cbitset", "cc", "dlmalloc", + "generic-rt", "goblin", "libc", "md-5", diff --git a/Cargo.toml b/Cargo.toml index 031a2214bb..da68a3e725 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ members = [ "src/crtn", "redox-rt", "ld_so", + "generic-rt", ] exclude = ["tests", "dlmalloc-rs"] @@ -42,6 +43,7 @@ bcrypt-pbkdf = { version = "0.10", default-features = false, features = ["alloc" scrypt = { version = "0.11", default-features = false, features = ["simple"]} pbkdf2 = { version = "0.12", features = ["sha2"]} sha2 = { version = "0.10", default-features = false } +generic-rt = { path = "generic-rt" } [dependencies.goblin] version = "0.7" diff --git a/generic-rt/Cargo.toml b/generic-rt/Cargo.toml new file mode 100644 index 0000000000..11e01ee046 --- /dev/null +++ b/generic-rt/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "generic-rt" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/generic-rt/src/lib.rs b/generic-rt/src/lib.rs new file mode 100644 index 0000000000..97e277a045 --- /dev/null +++ b/generic-rt/src/lib.rs @@ -0,0 +1,73 @@ +#![no_std] + +use core::arch::asm; +use core::mem::{self, offset_of}; + +#[derive(Debug)] +#[repr(C)] +pub struct GenericTcb { + /// Pointer to the end of static TLS. Must be the first member + pub tls_end: *mut u8, + /// Size of the memory allocated for the static TLS in bytes (multiple of page size) + pub tls_len: usize, + /// Pointer to this structure + pub tcb_ptr: *mut Self, + /// Size of the memory allocated for this structure in bytes (should be same as page size) + pub tcb_len: usize, + pub os_specific: Os, +} +impl GenericTcb { + /// Architecture specific code to read a usize from the TCB - aarch64 + #[inline(always)] + #[cfg(target_arch = "aarch64")] + pub unsafe fn arch_read(offset: usize) -> usize { + let abi_ptr: usize; + asm!( + "mrs {}, tpidr_el0", + out(reg) abi_ptr, + ); + + 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 + #[inline(always)] + #[cfg(target_arch = "x86")] + pub unsafe fn arch_read(offset: usize) -> usize { + let value; + asm!( + " + mov {}, gs:[{}] + ", + out(reg) value, + in(reg) offset, + ); + value + } + + /// Architecture specific code to read a usize from the TCB - x86_64 + #[inline(always)] + #[cfg(target_arch = "x86_64")] + pub unsafe fn arch_read(offset: usize) -> usize { + let value; + asm!( + " + mov {}, fs:[{}] + ", + out(reg) value, + in(reg) offset, + ); + value + } + + pub unsafe fn current_ptr() -> Option<*mut Self> { + let tcb_ptr = Self::arch_read(offset_of!(Self, tcb_ptr)) as *mut Self; + let tcb_len = Self::arch_read(offset_of!(Self, tcb_len)); + if tcb_ptr.is_null() || tcb_len < mem::size_of::() { + None + } else { + Some(tcb_ptr) + } + } +} diff --git a/redox-rt/Cargo.toml b/redox-rt/Cargo.toml index 210e5b8884..0cffcdca3b 100644 --- a/redox-rt/Cargo.toml +++ b/redox-rt/Cargo.toml @@ -13,3 +13,5 @@ bitflags = "2" goblin = { version = "0.7", default-features = false, features = ["elf32", "elf64", "endian_fd"] } plain = "0.2" redox_syscall = "0.5.1" + +generic-rt = { path = "../generic-rt" } diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index cba03eb0f3..580fb94655 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -11,12 +11,11 @@ use crate::signal::inner_c; pub(crate) const STACK_TOP: usize = 1 << 47; pub(crate) const STACK_SIZE: usize = 1024 * 1024; -// NOTE: MUST MATCH TCB STRUCT +#[derive(Debug, Default)] pub struct SigArea { altstack_top: usize, altstack_bottom: usize, tmp: usize, - _rsvd: usize, } /// Deactive TLS, used before exec() on Redox to not trick target executable into thinking TLS diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index f822bfaf53..d805f4cf3e 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -143,9 +143,15 @@ pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction // TODO: handle tmp_disable_signals } // TODO: Handle pending signals before these flags are set. - (SIGTSTP, Sigaction::Default) => PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TSTP_IS_STOP_BIT, Ordering::SeqCst), - (SIGTTIN, Sigaction::Default) => PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTIN_IS_STOP_BIT, Ordering::SeqCst), - (SIGTTOU, Sigaction::Default) => PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTOU_IS_STOP_BIT, Ordering::SeqCst), + (SIGTSTP, Sigaction::Default) => { + PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TSTP_IS_STOP_BIT, Ordering::SeqCst); + } + (SIGTTIN, Sigaction::Default) => { + PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTIN_IS_STOP_BIT, Ordering::SeqCst); + } + (SIGTTOU, Sigaction::Default) => { + PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTOU_IS_STOP_BIT, Ordering::SeqCst); + } (_, Sigaction::Default) => (), (_, Sigaction::Handled { .. }) => (), @@ -275,3 +281,8 @@ pub fn setup_sighandler(control: &Sigcontrol) { syscall::write(fd, &data).expect("failed to write to thisproc:current/sighandler"); let _ = syscall::close(fd); } +#[derive(Debug, Default)] +pub struct RtSigarea { + pub control: Sigcontrol, + pub arch: crate::arch::SigArea, +} diff --git a/src/ld_so/tcb.rs b/src/ld_so/tcb.rs index 784131c8be..b2176b6989 100644 --- a/src/ld_so/tcb.rs +++ b/src/ld_so/tcb.rs @@ -1,6 +1,7 @@ use alloc::vec::Vec; +use generic_rt::GenericTcb; use syscall::Sigcontrol; -use core::{arch::asm, cell::UnsafeCell, mem::{self, offset_of}, ptr, slice, sync::atomic::AtomicBool}; +use core::{arch::asm, cell::UnsafeCell, mem, ops::{Deref, DerefMut}, ptr, slice, sync::atomic::AtomicBool}; use goblin::error::{Error, Result}; use super::ExpectTlsFree; @@ -30,18 +31,17 @@ impl Master { } } +#[cfg(target_os = "linux")] +type OsSpecific = (); + +#[cfg(target_os = "redox")] +type OsSpecific = redox_rt::signal::RtSigarea; + #[derive(Debug)] #[repr(C)] // FIXME: Only return &Tcb, and use interior mutability, since it contains the Pthread struct pub struct Tcb { - /// Pointer to the end of static TLS. Must be the first member - pub tls_end: *mut u8, - /// Size of the memory allocated for the static TLS in bytes (multiple of page size) - pub tls_len: usize, - /// Pointer to this structure - pub tcb_ptr: *mut Tcb, - /// Size of the memory allocated for this structure in bytes (should be same as page size) - pub tcb_len: usize, + pub generic: GenericTcb, /// Pointer to a list of initial TLS data pub masters_ptr: *mut Master, /// Size of the masters list in bytes (multiple of mem::size_of::()) @@ -54,13 +54,6 @@ pub struct Tcb { pub mspace: *const Mutex, /// Underlying pthread_t struct, pthread_self() returns &self.pthread pub pthread: Pthread, - #[cfg(target_os = "redox")] - pub sigcontrol: RtSigarea, -} -#[derive(Debug, Default)] -pub struct RtSigarea { - pub control: Sigcontrol, - pub internal: [usize; 4], } impl Tcb { @@ -74,10 +67,13 @@ impl Tcb { ptr::write( tcb_ptr, Self { - tls_end: tls.as_mut_ptr().add(tls.len()), - tls_len: tls.len(), - tcb_ptr, - tcb_len: tcb_page.len(), + generic: GenericTcb { + tls_end: tls.as_mut_ptr().add(tls.len()), + tls_len: tls.len(), + tcb_ptr: tcb_ptr.cast(), + tcb_len: tcb_page.len(), + os_specific: OsSpecific::default(), + }, masters_ptr: ptr::null_mut(), masters_len: 0, num_copied_masters: 0, @@ -92,8 +88,6 @@ impl Tcb { stack_size: 0, os_tid: UnsafeCell::new(OsTid::default()), }, - #[cfg(target_os = "redox")] - sigcontrol: Default::default(), }, ); @@ -102,13 +96,7 @@ impl Tcb { /// Get the current TCB pub unsafe fn current() -> Option<&'static mut Self> { - let tcb_ptr = Self::arch_read(offset_of!(Self, tcb_ptr)) as *mut Self; - let tcb_len = Self::arch_read(offset_of!(Self, tcb_len)); - if tcb_ptr.is_null() || tcb_len < mem::size_of::() { - None - } else { - Some(&mut *tcb_ptr) - } + Some(&mut *GenericTcb::::current_ptr()?.cast()) } /// A slice for all of the TLS data @@ -228,50 +216,6 @@ impl Tcb { Ok((abi, tls, tcb)) } - /// Architecture specific code to read a usize from the TCB - aarch64 - #[inline(always)] - #[cfg(target_arch = "aarch64")] - unsafe fn arch_read(offset: usize) -> usize { - let abi_ptr: usize; - asm!( - "mrs {}, tpidr_el0", - out(reg) abi_ptr, - ); - - 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 - #[inline(always)] - #[cfg(target_arch = "x86")] - unsafe fn arch_read(offset: usize) -> usize { - let value; - asm!( - " - mov {}, gs:[{}] - ", - out(reg) value, - in(reg) offset, - ); - value - } - - /// Architecture specific code to read a usize from the TCB - x86_64 - #[inline(always)] - #[cfg(target_arch = "x86_64")] - unsafe fn arch_read(offset: usize) -> usize { - let value; - asm!( - " - mov {}, fs:[{}] - ", - out(reg) value, - in(reg) offset, - ); - value - } - /// OS and architecture specific code to activate TLS - Linux x86_64 #[cfg(all(target_os = "linux", target_arch = "x86_64"))] unsafe fn os_arch_activate(tls_end: usize, _tls_len: usize) { @@ -331,3 +275,16 @@ impl Tcb { let _ = syscall::close(file); } } + +impl Deref for Tcb { + type Target = GenericTcb; + + fn deref(&self) -> &Self::Target { + &self.generic + } +} +impl DerefMut for Tcb { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.generic + } +} diff --git a/src/start.rs b/src/start.rs index d0301b1b2b..9bf2f8da5b 100644 --- a/src/start.rs +++ b/src/start.rs @@ -158,7 +158,7 @@ pub unsafe extern "C" fn relibc_start(sp: &'static Stack) -> ! { tcb.linker_ptr = Box::into_raw(Box::new(Mutex::new(linker))); } #[cfg(target_os = "redox")] - redox_rt::signal::setup_sighandler(&tcb.sigcontrol.control); + redox_rt::signal::setup_sighandler(&tcb.os_specific.control); } // Set up argc and argv