1 use syscall::error::*; 2 3 use crate::{FdGuard, fork_inner}; 4 5 // Setup a stack starting from the very end of the address space, and then growing downwards. 6 pub(crate) const STACK_TOP: usize = 1 << 47; 7 pub(crate) const STACK_SIZE: usize = 1024 * 1024; 8 9 /// Deactive TLS, used before exec() on Redox to not trick target executable into thinking TLS 10 /// is already initialized as if it was a thread. 11 pub unsafe fn deactivate_tcb(open_via_dup: usize) -> Result<()> { 12 let mut env = syscall::EnvRegisters::default(); 13 14 let file = FdGuard::new(syscall::dup(open_via_dup, b"regs/env")?); 15 16 env.tpidr_el0 = 0; 17 18 let _ = syscall::write(*file, &mut env)?; 19 Ok(()) 20 } 21 22 pub fn copy_env_regs(cur_pid_fd: usize, new_pid_fd: usize) -> Result<()> { 23 // Copy environment registers. 24 { 25 let cur_env_regs_fd = FdGuard::new(syscall::dup(cur_pid_fd, b"regs/env")?); 26 let new_env_regs_fd = FdGuard::new(syscall::dup(new_pid_fd, b"regs/env")?); 27 28 let mut env_regs = syscall::EnvRegisters::default(); 29 let _ = syscall::read(*cur_env_regs_fd, &mut env_regs)?; 30 let _ = syscall::write(*new_env_regs_fd, &env_regs)?; 31 } 32 33 Ok(()) 34 } 35 36 #[no_mangle] 37 unsafe extern "C" fn __relibc_internal_fork_impl(initial_rsp: *mut usize) -> usize { 38 Error::mux(fork_inner(initial_rsp)) 39 } 40 41 #[no_mangle] 42 unsafe extern "C" fn __relibc_internal_fork_hook(cur_filetable_fd: usize, new_pid_fd: usize) { 43 let _ = syscall::close(cur_filetable_fd); 44 let _ = syscall::close(new_pid_fd); 45 } 46 47 core::arch::global_asm!(" 48 .p2align 6 49 .globl __relibc_internal_fork_wrapper 50 .type __relibc_internal_fork_wrapper, @function 51 __relibc_internal_fork_wrapper: 52 str x19, [sp, #-8]! 53 str x20, [sp, #-8]! 54 str x21, [sp, #-8]! 55 str x22, [sp, #-8]! 56 str x23, [sp, #-8]! 57 str x24, [sp, #-8]! 58 str x25, [sp, #-8]! 59 str x26, [sp, #-8]! 60 str x27, [sp, #-8]! 61 str x28, [sp, #-8]! 62 str x29, [sp, #-8]! 63 str x30, [sp, #-8]! 64 65 sub sp, sp, #32 66 67 //TODO: store floating point regs 68 69 mov x0, sp 70 bl __relibc_internal_fork_impl 71 b 2f 72 73 .size __relibc_internal_fork_wrapper, . - __relibc_internal_fork_wrapper 74 75 .p2align 6 76 .globl __relibc_internal_fork_ret 77 .type __relibc_internal_fork_ret, @function 78 __relibc_internal_fork_ret: 79 ldr x0, [sp] 80 ldr x1, [sp, #8] 81 bl __relibc_internal_fork_hook 82 83 //TODO: load floating point regs 84 85 mov x0, xzr 86 87 .p2align 4 88 2: 89 add sp, sp, #32 90 ldr x30, [sp], #8 91 ldr x29, [sp], #8 92 ldr x28, [sp], #8 93 ldr x27, [sp], #8 94 ldr x26, [sp], #8 95 ldr x25, [sp], #8 96 ldr x24, [sp], #8 97 ldr x23, [sp], #8 98 ldr x22, [sp], #8 99 ldr x21, [sp], #8 100 ldr x20, [sp], #8 101 ldr x19, [sp], #8 102 ret 103 104 .size __relibc_internal_fork_ret, . - __relibc_internal_fork_ret" 105 ); 106 107 extern "C" { 108 pub(crate) fn __relibc_internal_fork_wrapper() -> usize; 109 pub(crate) fn __relibc_internal_fork_ret(); 110 } 111