xref: /relibc/src/platform/redox/redox-exec/src/arch/aarch64.rs (revision ed19381547d66b76981ea1e4ff942c5a4da45ab7)
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