From c9d22e484bc89e08828c5bffeab5677f4c8c8f57 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Tue, 2 Jul 2024 11:53:29 +0200 Subject: [PATCH] Write draft aarch64 trampoline that compiles. --- redox-rt/src/arch/aarch64.rs | 185 ++++++++++++++++++++++++++++++++++- 1 file changed, 180 insertions(+), 5 deletions(-) diff --git a/redox-rt/src/arch/aarch64.rs b/redox-rt/src/arch/aarch64.rs index be9afcc0..fc69eec0 100644 --- a/redox-rt/src/arch/aarch64.rs +++ b/redox-rt/src/arch/aarch64.rs @@ -1,19 +1,68 @@ +use core::mem::offset_of; + +use syscall::data::*; use syscall::error::*; use crate::proc::{fork_inner, FdGuard}; -use crate::signal::inner_c; +use crate::signal::SigStack; +use crate::signal::{inner_c, RtSigarea, PROC_CONTROL_STRUCT}; +use crate::Tcb; // Setup a stack starting from the very end of the address space, and then growing downwards. pub(crate) const STACK_TOP: usize = 1 << 47; pub(crate) const STACK_SIZE: usize = 1024 * 1024; #[derive(Debug, Default)] +#[repr(C)] pub struct SigArea { pub altstack_top: usize, pub altstack_bottom: usize, - pub tmp: usize, + pub tmp_x1_x2: [usize; 2], + pub tmp_x3_x4: [usize; 2], + pub tmp_sp: usize, pub onstack: u64, pub disable_signals_depth: u64, + pub pctl: usize, // TODO: remove +} +#[repr(C)] +#[derive(Debug, Default)] +pub struct ArchIntRegs { + pub x30: usize, + pub x29: usize, + pub x28: usize, + pub x27: usize, + pub x26: usize, + pub x25: usize, + pub x24: usize, + pub x23: usize, + pub x22: usize, + pub x21: usize, + pub x20: usize, + pub x19: usize, + pub x18: usize, + pub x17: usize, + pub x16: usize, + pub x15: usize, + pub x14: usize, + pub x13: usize, + pub x12: usize, + pub x11: usize, + pub x10: usize, + pub x9: usize, + pub x8: usize, + pub x7: usize, + pub x6: usize, + pub x5: usize, + pub x4: usize, + pub x3: usize, + pub x2: usize, + pub x1: usize, + + pub sp: usize, + pub nzcv: usize, // user-accessible PSTATE bits + + pub pc: usize, + pub x0: usize, } /// Deactive TLS, used before exec() on Redox to not trick target executable into thinking TLS @@ -91,12 +140,112 @@ asmfunction!(__relibc_internal_fork_ret: [" "] <= [child_hook = sym child_hook]); asmfunction!(__relibc_internal_sigentry: [" + // old pc and x0 are saved in the sigcontrol struct + mrs x0, tpidr_el0 // ABI ptr + ldr x0, [x0] // TCB ptr + + // save x1-x3 and sp + stp x1, x2, [x0, #{tcb_sa_off} + {sa_tmp_x1_x2}] + stp x3, x4, [x0, #{tcb_sa_off} + {sa_tmp_x3_x4}] + mov x1, sp + str x1, [x0, #{tcb_sa_off} + {sa_tmp_sp}] + + sub x1, x1, 128 + and x1, x1, -16 + mov sp, x1 + + ldr x3, [x0, #{tcb_sa_off} + {sa_pctl}] + + // load x1 and x2 with each word (tearing between x1 and x2 can occur) + // acquire ordering + add x2, x0, #{tcb_sc_off} + {sc_word} + ldaxp x1, x2, [x2] + + // reduce them by ANDing the upper and lower 32 bits + and x1, x1, x1, lsr #32 // put result in lo half + and x2, x2, x2, lsl #32 // put result in hi half + orr x1, x1, x2 // combine them into the set of pending unblocked + + // count trailing zeroes, to find signal bit + rbit x1, x1 + clz x1, x1 + mov x2, #32 + sub x1, x2, x1 + + // TODO: NOT ATOMIC! + add x2, x3, w1, uxtb #4 // actions_base + sig_idx * sizeof Action + ldxp x2, x3, [x2] + + // skip sigaltstack step if SA_ONSTACK is clear + // tbz x2, #57, 2f +2: + ldr x2, [x0, #{tcb_sc_off} + {sc_saved_pc}] + ldr x3, [x0, #{tcb_sc_off} + {sc_saved_x0}] + stp x2, x3, [sp], #-16 + + ldr x2, [x0, #{tcb_sa_off} + {sa_tmp_sp}] + mrs x3, nzcv + stp x2, x3, [sp], #-16 + + ldp x2, x3, [x0, #{tcb_sa_off} + {sa_tmp_x1_x2}] + stp x2, x3, [sp], #-16 + ldp x3, x4, [x0, #{tcb_sa_off} + {sa_tmp_x3_x4}] + stp x4, x3, [sp], #-16 + stp x6, x5, [sp], #-16 + stp x8, x7, [sp], #-16 + stp x10, x9, [sp], #-16 + stp x12, x11, [sp], #-16 + stp x14, x13, [sp], #-16 + stp x16, x15, [sp], #-16 + stp x18, x17, [sp], #-16 + stp x20, x19, [sp], #-16 + stp x22, x21, [sp], #-16 + stp x24, x23, [sp], #-16 + stp x26, x25, [sp], #-16 + stp x28, x27, [sp], #-16 + stp x30, x29, [sp], #-16 + mov x0, sp bl {inner} - // FIXME - b . -"] <= [inner = sym inner_c]); + ldp x30, x29, [sp], #16 + ldp x28, x27, [sp], #16 + ldp x26, x25, [sp], #16 + ldp x24, x23, [sp], #16 + ldp x22, x21, [sp], #16 + ldp x20, x19, [sp], #16 + ldp x18, x17, [sp], #16 + ldp x16, x15, [sp], #16 + ldp x14, x13, [sp], #16 + ldp x12, x11, [sp], #16 + ldp x10, x9, [sp], #16 + ldp x8, x7, [sp], #16 + ldp x6, x5, [sp], #16 + ldp x4, x3, [sp], #16 + ldp x2, x1, [sp], #16 + ldr x0, [sp, #8] + msr nzcv, x0 + + // x18 is reserved by ABI as 'platform register', so clobbering it should be safe. + mov x18, sp + ldr x0, [sp], #16 + mov sp, x0 + mov x0, x18 + + ldp x18, x0, [x0] + br x18 +"] <= [ + tcb_sc_off = const (offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, control)), + tcb_sa_off = const (offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, arch)), + sa_tmp_x1_x2 = const offset_of!(SigArea, tmp_x1_x2), + sa_tmp_x3_x4 = const offset_of!(SigArea, tmp_x3_x4), + sa_tmp_sp = const offset_of!(SigArea, tmp_sp), + sa_pctl = const offset_of!(SigArea, pctl), + sc_saved_pc = const offset_of!(Sigcontrol, saved_ip), + sc_saved_x0 = const offset_of!(Sigcontrol, saved_archdep_reg), + sc_word = const offset_of!(Sigcontrol, word), + inner = sym inner_c, +]); asmfunction!(__relibc_internal_rlct_clone_ret: [" # Load registers @@ -109,3 +258,29 @@ asmfunction!(__relibc_internal_rlct_clone_ret: [" ret "] <= []); + +pub fn current_sp() -> usize { + let sp: usize; + unsafe { + core::arch::asm!("mov {}, sp", out(reg) sp); + } + sp +} + +pub unsafe fn manually_enter_trampoline() { + let ctl = &Tcb::current().unwrap().os_specific.control; + + ctl.saved_archdep_reg.set(0); + let ip_location = &ctl.saved_ip as *const _ as usize; + + core::arch::asm!(" + bl 2f + b 3f + 2: + ldr lr, [x0] + b __relibc_internal_sigentry + 3: + ", inout("x0") ip_location => _, out("lr") _); +} + +pub unsafe fn arch_pre(stack: &mut SigStack, os: &mut SigArea) {} -- GitLab