xref: /relibc/src/platform/redox/redox-exec/src/arch/x86.rs (revision fd22fbbabfdcb99dacbd9e8317399ad91050d6cd)
1 use syscall::error::*;
2 
3 use crate::{fork_inner, FdGuard};
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 << 31;
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.fsbase = 0;
17     env.gsbase = 0;
18 
19     let _ = syscall::write(*file, &mut env)?;
20     Ok(())
21 }
22 
23 pub fn copy_env_regs(cur_pid_fd: usize, new_pid_fd: usize) -> Result<()> {
24     // Copy environment registers.
25     {
26         let cur_env_regs_fd = FdGuard::new(syscall::dup(cur_pid_fd, b"regs/env")?);
27         let new_env_regs_fd = FdGuard::new(syscall::dup(new_pid_fd, b"regs/env")?);
28 
29         let mut env_regs = syscall::EnvRegisters::default();
30         let _ = syscall::read(*cur_env_regs_fd, &mut env_regs)?;
31         let _ = syscall::write(*new_env_regs_fd, &env_regs)?;
32     }
33 
34     Ok(())
35 }
36 
37 #[no_mangle]
38 unsafe extern "cdecl" fn __relibc_internal_fork_impl(initial_rsp: *mut usize) -> usize {
39     Error::mux(fork_inner(initial_rsp))
40 }
41 
42 #[no_mangle]
43 unsafe extern "cdecl" fn __relibc_internal_fork_hook(cur_filetable_fd: usize, new_pid_fd: usize) {
44     let _ = syscall::close(cur_filetable_fd);
45     let _ = syscall::close(new_pid_fd);
46 }
47 
48 //TODO: x86
49 core::arch::global_asm!(
50     "
51     .p2align 6
52     .globl __relibc_internal_fork_wrapper
53     .type __relibc_internal_fork_wrapper, @function
54 __relibc_internal_fork_wrapper:
55     push ebp
56     mov ebp, esp
57 
58     // Push preserved registers
59     push ebx
60     push edi
61     push esi
62     push ebp
63 
64     sub esp, 32
65 
66     //TODO stmxcsr [esp+16]
67     fnstcw [esp+24]
68 
69     push esp
70     call __relibc_internal_fork_impl
71     pop esp
72     jmp 2f
73 
74     .size __relibc_internal_fork_wrapper, . - __relibc_internal_fork_wrapper
75 
76     .p2align 6
77     .globl __relibc_internal_fork_ret
78     .type __relibc_internal_fork_ret, @function
79 __relibc_internal_fork_ret:
80     // Arguments already on the stack
81     call __relibc_internal_fork_hook
82 
83     //TODO ldmxcsr [esp+16]
84     fldcw [esp+24]
85 
86     xor eax, eax
87 
88     .p2align 4
89 2:
90     add esp, 32
91 
92     // Pop preserved registers
93     pop ebp
94     pop esi
95     pop edi
96     pop ebx
97 
98     pop ebp
99     ret
100 
101     .size __relibc_internal_fork_ret, . - __relibc_internal_fork_ret"
102 );
103 
104 extern "cdecl" {
105     pub(crate) fn __relibc_internal_fork_wrapper() -> usize;
106     pub(crate) fn __relibc_internal_fork_ret();
107 }
108