Implement hack to ensure TCB exists in bootstrap.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#![no_std]
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
use core::arch::asm;
|
||||
use core::mem::{self, offset_of};
|
||||
@@ -70,4 +71,42 @@ impl<Os> GenericTcb<Os> {
|
||||
Some(tcb_ptr)
|
||||
}
|
||||
}
|
||||
pub unsafe fn current() -> Option<&'static mut Self> {
|
||||
Some(&mut *Self::current_ptr()?)
|
||||
}
|
||||
}
|
||||
pub fn panic_notls(msg: impl core::fmt::Display) -> ! {
|
||||
//eprintln!("panicked in ld.so: {}", msg);
|
||||
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
|
||||
pub trait ExpectTlsFree {
|
||||
type Unwrapped;
|
||||
|
||||
fn expect_notls(self, msg: &str) -> Self::Unwrapped;
|
||||
}
|
||||
impl<T, E: core::fmt::Debug> ExpectTlsFree for Result<T, E> {
|
||||
type Unwrapped = T;
|
||||
|
||||
fn expect_notls(self, msg: &str) -> T {
|
||||
match self {
|
||||
Ok(t) => t,
|
||||
Err(err) => panic_notls(format_args!(
|
||||
"{}: expect failed for Result with err: {:?}",
|
||||
msg, err
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> ExpectTlsFree for Option<T> {
|
||||
type Unwrapped = T;
|
||||
|
||||
fn expect_notls(self, msg: &str) -> T {
|
||||
match self {
|
||||
Some(t) => t,
|
||||
None => panic_notls(format_args!("{}: expect failed for Option", msg)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ pub struct SigArea {
|
||||
altstack_top: usize,
|
||||
altstack_bottom: usize,
|
||||
tmp: usize,
|
||||
pub disable_signals_depth: u64,
|
||||
}
|
||||
|
||||
/// Deactive TLS, used before exec() on Redox to not trick target executable into thinking TLS
|
||||
@@ -145,10 +146,10 @@ asmfunction!(__relibc_internal_sigentry: ["
|
||||
//
|
||||
// Now that we have a stack, we can finally start initializing the signal stack!
|
||||
|
||||
push ss
|
||||
push 0 // SS
|
||||
push [rax + {tcb_sc_off} + {sc_saved_rsp}]
|
||||
push [rax + {tcb_sc_off} + {sc_saved_rflags}]
|
||||
push cs
|
||||
push 0 // CS
|
||||
push [rax + {tcb_sc_off} + {sc_saved_rip}]
|
||||
|
||||
push rdi
|
||||
@@ -176,7 +177,7 @@ asmfunction!(__relibc_internal_sigentry: ["
|
||||
rep stosb
|
||||
|
||||
// TODO: self-modifying?
|
||||
cmp byte ptr [{supports_xsave}], 0
|
||||
cmp byte ptr [rip + {supports_xsave}], 0
|
||||
je 3f
|
||||
|
||||
mov eax, 0xffffffff
|
||||
@@ -208,11 +209,11 @@ asmfunction!(__relibc_internal_sigentry: ["
|
||||
pop rsi
|
||||
pop rdi
|
||||
|
||||
pop gs:[{tcb_sa_off} + {sa_tmp}]
|
||||
pop qword ptr gs:[{tcb_sa_off} + {sa_tmp}]
|
||||
add rsp, 8
|
||||
popfq
|
||||
pop rsp
|
||||
jmp gs:[{tcb_sa_off} + {sa_tmp}]
|
||||
jmp qword ptr gs:[{tcb_sa_off} + {sa_tmp}]
|
||||
3:
|
||||
fxsave64 [rsp]
|
||||
|
||||
|
||||
+74
-2
@@ -1,8 +1,8 @@
|
||||
#![no_std]
|
||||
#![feature(asm_const, array_chunks, int_roundings, let_chains, slice_ptr_get, sync_unsafe_cell, thread_local)]
|
||||
#![feature(asm_const, array_chunks, int_roundings, let_chains, slice_ptr_get, sync_unsafe_cell)]
|
||||
#![forbid(unreachable_patterns)]
|
||||
|
||||
use generic_rt::GenericTcb;
|
||||
use generic_rt::{ExpectTlsFree, GenericTcb};
|
||||
|
||||
use self::signal::RtSigarea;
|
||||
|
||||
@@ -39,3 +39,75 @@ pub mod sync;
|
||||
pub mod thread;
|
||||
|
||||
pub type Tcb = GenericTcb<RtSigarea>;
|
||||
|
||||
/// OS and architecture specific code to activate TLS - Redox aarch64
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub unsafe fn tcb_activate(tls_end: usize, tls_len: usize) {
|
||||
// Uses ABI page
|
||||
let abi_ptr = tls_end - tls_len - 16;
|
||||
ptr::write(abi_ptr as *mut usize, tls_end);
|
||||
asm!(
|
||||
"msr tpidr_el0, {}",
|
||||
in(reg) abi_ptr,
|
||||
);
|
||||
}
|
||||
|
||||
/// OS and architecture specific code to activate TLS - Redox x86
|
||||
#[cfg(target_arch = "x86")]
|
||||
pub unsafe fn tcb_activate(tls_end: usize, _tls_len: usize) {
|
||||
let mut env = syscall::EnvRegisters::default();
|
||||
|
||||
let file = syscall::open(
|
||||
"thisproc:current/regs/env",
|
||||
syscall::O_CLOEXEC | syscall::O_RDWR,
|
||||
)
|
||||
.expect_notls("failed to open handle for process registers");
|
||||
|
||||
let _ = syscall::read(file, &mut env).expect_notls("failed to read gsbase");
|
||||
|
||||
env.gsbase = tls_end as u32;
|
||||
|
||||
let _ = syscall::write(file, &env).expect_notls("failed to write gsbase");
|
||||
|
||||
let _ = syscall::close(file);
|
||||
}
|
||||
|
||||
/// OS and architecture specific code to activate TLS - Redox x86_64
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub unsafe fn tcb_activate(tls_end_and_tcb_start: usize, _tls_len: usize) {
|
||||
let mut env = syscall::EnvRegisters::default();
|
||||
|
||||
let file = syscall::open(
|
||||
"thisproc:current/regs/env",
|
||||
syscall::O_CLOEXEC | syscall::O_RDWR,
|
||||
)
|
||||
.expect_notls("failed to open handle for process registers");
|
||||
|
||||
let _ = syscall::read(file, &mut env).expect_notls("failed to read fsbase");
|
||||
|
||||
env.fsbase = tls_end_and_tcb_start as u64;
|
||||
|
||||
let _ = syscall::write(file, &env).expect_notls("failed to write fsbase");
|
||||
|
||||
let _ = syscall::close(file);
|
||||
}
|
||||
|
||||
/// Initialize redox-rt in situations where relibc is not used
|
||||
pub fn initialize_freestanding() {
|
||||
// TODO: TLS
|
||||
let page = unsafe {
|
||||
&mut *(syscall::fmap(!0, &syscall::Map {
|
||||
offset: 0,
|
||||
size: syscall::PAGE_SIZE,
|
||||
flags: syscall::MapFlags::PROT_READ | syscall::MapFlags::PROT_WRITE | syscall::MapFlags::MAP_PRIVATE,
|
||||
address: 0,
|
||||
}).unwrap() as *mut Tcb)
|
||||
};
|
||||
page.tcb_ptr = page;
|
||||
page.tcb_len = syscall::PAGE_SIZE;
|
||||
page.tls_end = (page as *mut Tcb).cast();
|
||||
|
||||
unsafe {
|
||||
tcb_activate(page as *mut Tcb as usize, 0)
|
||||
}
|
||||
}
|
||||
|
||||
+8
-14
@@ -4,7 +4,7 @@ use core::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
use syscall::{Error, IntRegisters, Result, SigProcControl, Sigcontrol, EINVAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGW0_TSTP_IS_STOP_BIT, SIGW0_TTIN_IS_STOP_BIT, SIGW0_TTOU_IS_STOP_BIT, SIGWINCH};
|
||||
|
||||
use crate::arch::*;
|
||||
use crate::{arch::*, Tcb};
|
||||
use crate::sync::Mutex;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -160,24 +160,18 @@ pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction
|
||||
todo!()
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn __relibc_internal_get_sigcontrol_addr() -> &'static Sigcontrol;
|
||||
}
|
||||
fn current_sigctl() -> &'static Sigcontrol {
|
||||
unsafe { __relibc_internal_get_sigcontrol_addr() }
|
||||
&unsafe { Tcb::current() }.unwrap().os_specific.control
|
||||
}
|
||||
|
||||
pub struct TmpDisableSignalsGuard { _inner: () }
|
||||
|
||||
#[thread_local]
|
||||
static TMP_DISABLE_SIGNALS_DEPTH: Cell<u64> = Cell::new(0);
|
||||
|
||||
pub fn tmp_disable_signals() -> TmpDisableSignalsGuard {
|
||||
unsafe {
|
||||
let ctl = __relibc_internal_get_sigcontrol_addr().control_flags.get();
|
||||
let ctl = current_sigctl().control_flags.get();
|
||||
ctl.write_volatile(ctl.read_volatile() | syscall::flag::INHIBIT_DELIVERY);
|
||||
// TODO: fence?
|
||||
TMP_DISABLE_SIGNALS_DEPTH.set(TMP_DISABLE_SIGNALS_DEPTH.get() + 1);
|
||||
Tcb::current().unwrap().os_specific.arch.disable_signals_depth += 1;
|
||||
}
|
||||
|
||||
TmpDisableSignalsGuard { _inner: () }
|
||||
@@ -185,11 +179,11 @@ pub fn tmp_disable_signals() -> TmpDisableSignalsGuard {
|
||||
impl Drop for TmpDisableSignalsGuard {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let old = TMP_DISABLE_SIGNALS_DEPTH.get();
|
||||
TMP_DISABLE_SIGNALS_DEPTH.set(old - 1);
|
||||
let depth = &mut Tcb::current().unwrap().os_specific.arch.disable_signals_depth;
|
||||
*depth -= 1;
|
||||
|
||||
if old == 1 {
|
||||
let ctl = __relibc_internal_get_sigcontrol_addr().control_flags.get();
|
||||
if *depth == 0 {
|
||||
let ctl = current_sigctl().control_flags.get();
|
||||
ctl.write_volatile(ctl.read_volatile() & !syscall::flag::INHIBIT_DELIVERY);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-35
@@ -22,47 +22,14 @@ pub mod linker;
|
||||
pub mod start;
|
||||
pub mod tcb;
|
||||
|
||||
pub use generic_rt::{panic_notls, ExpectTlsFree};
|
||||
|
||||
static mut STATIC_TCB_MASTER: Master = Master {
|
||||
ptr: ptr::null_mut(),
|
||||
len: 0,
|
||||
offset: 0,
|
||||
};
|
||||
|
||||
fn panic_notls(msg: impl core::fmt::Display) -> ! {
|
||||
eprintln!("panicked in ld.so: {}", msg);
|
||||
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
|
||||
pub trait ExpectTlsFree {
|
||||
type Unwrapped;
|
||||
|
||||
fn expect_notls(self, msg: &str) -> Self::Unwrapped;
|
||||
}
|
||||
impl<T, E: core::fmt::Debug> ExpectTlsFree for Result<T, E> {
|
||||
type Unwrapped = T;
|
||||
|
||||
fn expect_notls(self, msg: &str) -> T {
|
||||
match self {
|
||||
Ok(t) => t,
|
||||
Err(err) => panic_notls(format_args!(
|
||||
"{}: expect failed for Result with err: {:?}",
|
||||
msg, err
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> ExpectTlsFree for Option<T> {
|
||||
type Unwrapped = T;
|
||||
|
||||
fn expect_notls(self, msg: &str) -> T {
|
||||
match self {
|
||||
Some(t) => t,
|
||||
None => panic_notls(format_args!("{}: expect failed for Option", msg)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
pub fn static_init(sp: &'static Stack) {
|
||||
let mut phdr_opt = None;
|
||||
|
||||
+2
-49
@@ -223,56 +223,9 @@ impl Tcb {
|
||||
syscall!(ARCH_PRCTL, ARCH_SET_FS, tls_end);
|
||||
}
|
||||
|
||||
/// OS and architecture specific code to activate TLS - Redox aarch64
|
||||
#[cfg(all(target_os = "redox", target_arch = "aarch64"))]
|
||||
#[cfg(all(target_os = "redox"))]
|
||||
unsafe fn os_arch_activate(tls_end: usize, tls_len: usize) {
|
||||
// Uses ABI page
|
||||
let abi_ptr = tls_end - tls_len - 16;
|
||||
ptr::write(abi_ptr as *mut usize, tls_end);
|
||||
asm!(
|
||||
"msr tpidr_el0, {}",
|
||||
in(reg) abi_ptr,
|
||||
);
|
||||
}
|
||||
|
||||
/// OS and architecture specific code to activate TLS - Redox x86
|
||||
#[cfg(all(target_os = "redox", target_arch = "x86"))]
|
||||
unsafe fn os_arch_activate(tls_end: usize, _tls_len: usize) {
|
||||
let mut env = syscall::EnvRegisters::default();
|
||||
|
||||
let file = syscall::open(
|
||||
"thisproc:current/regs/env",
|
||||
syscall::O_CLOEXEC | syscall::O_RDWR,
|
||||
)
|
||||
.expect_notls("failed to open handle for process registers");
|
||||
|
||||
let _ = syscall::read(file, &mut env).expect_notls("failed to read gsbase");
|
||||
|
||||
env.gsbase = tls_end as u32;
|
||||
|
||||
let _ = syscall::write(file, &env).expect_notls("failed to write gsbase");
|
||||
|
||||
let _ = syscall::close(file);
|
||||
}
|
||||
|
||||
/// OS and architecture specific code to activate TLS - Redox x86_64
|
||||
#[cfg(all(target_os = "redox", target_arch = "x86_64"))]
|
||||
unsafe fn os_arch_activate(tls_end: usize, _tls_len: usize) {
|
||||
let mut env = syscall::EnvRegisters::default();
|
||||
|
||||
let file = syscall::open(
|
||||
"thisproc:current/regs/env",
|
||||
syscall::O_CLOEXEC | syscall::O_RDWR,
|
||||
)
|
||||
.expect_notls("failed to open handle for process registers");
|
||||
|
||||
let _ = syscall::read(file, &mut env).expect_notls("failed to read fsbase");
|
||||
|
||||
env.fsbase = tls_end as u64;
|
||||
|
||||
let _ = syscall::write(file, &env).expect_notls("failed to write fsbase");
|
||||
|
||||
let _ = syscall::close(file);
|
||||
redox_rt::tcb_activate(tls_end, tls_len)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user