From e5136e66c123d88899ef2f9a97985e097a183961 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 2 Aug 2024 11:47:59 +0200 Subject: [PATCH] Draft of updated aarch64 signal trampoline. --- redox-rt/src/arch/aarch64.rs | 118 ++++++++++++++++++++++++++++++----- 1 file changed, 102 insertions(+), 16 deletions(-) diff --git a/redox-rt/src/arch/aarch64.rs b/redox-rt/src/arch/aarch64.rs index 02ac534153..e6bf9827c0 100644 --- a/redox-rt/src/arch/aarch64.rs +++ b/redox-rt/src/arch/aarch64.rs @@ -1,10 +1,10 @@ -use core::mem::offset_of; +use core::{mem::offset_of, ptr::NonNull}; use syscall::{data::*, error::*}; use crate::{ proc::{fork_inner, FdGuard}, - signal::{inner_c, RtSigarea, SigStack, PROC_CONTROL_STRUCT}, + signal::{inner_c, PosixStackt, RtSigarea, SigStack, PROC_CONTROL_STRUCT}, RtTcb, Tcb, }; @@ -19,11 +19,14 @@ pub struct SigArea { pub altstack_bottom: usize, pub tmp_x1_x2: [usize; 2], pub tmp_x3_x4: [usize; 2], + pub tmp_x5_x6: [usize; 2], pub tmp_sp: usize, pub onstack: u64, pub disable_signals_depth: u64, pub pctl: usize, // TODO: remove pub last_sig_was_restart: bool, + pub last_sigstack: Option>, + pub tmp_inf: RtSigInfo, } #[repr(C)] #[derive(Debug, Default)] @@ -150,32 +153,92 @@ asmfunction!(__relibc_internal_fork_ret: [" ret "] <= [child_hook = sym child_hook]); +// https://devblogs.microsoft.com/oldnewthing/20220811-00/?p=106963 asmfunction!(__relibc_internal_sigentry: [" - // old pc and x0 are saved in the sigcontrol struct + // Clear any active reservation. + clrex + + // The 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 + // Save x1-x6 and sp stp x1, x2, [x0, #{tcb_sa_off} + {sa_tmp_x1_x2}] stp x3, x4, [x0, #{tcb_sa_off} + {sa_tmp_x3_x4}] + stp x5, x6, [x0, #{tcb_sa_off} + {sa_tmp_x5_x6}] mov x1, sp str x1, [x0, #{tcb_sa_off} + {sa_tmp_sp}] - sub x1, x1, 128 - and x1, x1, -16 + // Calculate new sp wrt redzone and alignment + sub x1, x1, {REDZONE_SIZE} + and x1, x1, -{STACK_ALIGN} 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) + ldr x6, [x0, #{tcb_sa_off} + {sa_pctl}] +1: + // Load x1 and x2 with each signal group's bits (tearing between x1 and x2 can occur) with // 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 + // First check if there are standard thread signals, + and x4, x1, x1, lsr #32 // x4 := x1 & (x1 >> 32) + cbnz x4, 3f // jump if x4 != 0 + + // and if not, load process pending bitset. + add x3, x6, #{pctl_pending} + ldaxr x3, [x3] + + // Check if there are standard proc signals: + lsr x4, x1, #32 // mask + and w4, w4, w3 // pending unblocked proc + cbz w4, 4f // skip 'fetch_andn' step if zero + + // If there was one, find which one, and try clearing the bit (last value in x3, addr in x6) + // this picks the MSB rather than the LSB, unlike x86. POSIX does not require any specific + // ordering though. + clz x4, x4 + mov x5, #32 + sub x4, x5, x4 + + mov x5, #1 + lsl x5, x5, x4 // bit to remove + + sub x5, x3, x5 // bit was certainly set, so sub is allowed + add x3, x6, #{pctl_pending} + + // Try clearing the bit, retrying on failure. + add x3, x6, #{pctl_pending} + stxr w1, x5, [x3] // try setting [x3] to x5, set x5 := 0 on success + cbnz x1, 1b + mov x1, x4 + b 2f +4: + // Check for realtime signals, thread/proc. x1 is now free real estate (but needs to contain + // the selected signal number when entering Rust). + + b . + + mov w1, w2 + orr w1, w1, w3 + and x1, x1, x1, lsr #32 + + rbit x1, x1 + clz x1, x1 + mov x2, #32 + sub x1, x2, x1 + mov x2, #1 + lsl x2, x2, x1 + + mov x5, x0 + mov x4, x8 + mov x8, {SYS_SIGDEQUEUE} + // x1 contains signal + add x2, x0, #{tcb_sa_off} + {sa_tmp_inf} + svc 0 + cbnz x0, 1b + mov x0, x5 + mov x8, x4 // count trailing zeroes, to find signal bit rbit x1, x1 @@ -183,12 +246,18 @@ asmfunction!(__relibc_internal_sigentry: [" mov x2, #32 sub x1, x2, x1 - // TODO: NOT ATOMIC! + ldr x3, [x0, #{tcb_sa_off} + {sa_pctl}] + add x2, x2, {pctl_actions} add x2, x3, w1, uxtb #4 // actions_base + sig_idx * sizeof Action + // TODO: NOT ATOMIC (tearing allowed between regs)! ldxp x2, x3, [x2] // skip sigaltstack step if SA_ONSTACK is clear - // tbz x2, #57, 2f + // tbz x2, #{SA_ONSTACK_BIT}, 2f +3: + clz x1, x1 + mov x2, #32 + 64 + sub x1, x2, x1 2: ldr x2, [x0, #{tcb_sc_off} + {sc_saved_pc}] ldr x3, [x0, #{tcb_sc_off} + {sc_saved_x0}] @@ -202,7 +271,9 @@ asmfunction!(__relibc_internal_sigentry: [" stp x2, x3, [sp], #-16 ldp x3, x4, [x0, #{tcb_sa_off} + {sa_tmp_x3_x4}] stp x4, x3, [sp], #-16 + ldp x5, x6, [x0, #{tcb_sa_off} + {sa_tmp_x5_x6}] stp x6, x5, [sp], #-16 + stp x8, x7, [sp], #-16 stp x10, x9, [sp], #-16 stp x12, x11, [sp], #-16 @@ -246,16 +317,25 @@ asmfunction!(__relibc_internal_sigentry: [" ldp x18, x0, [x0] br x18 "] <= [ + pctl_pending = const (offset_of!(SigProcControl, pending)), + pctl_actions = const (offset_of!(SigProcControl, actions)), 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_x5_x6 = const offset_of!(SigArea, tmp_x5_x6), sa_tmp_sp = const offset_of!(SigArea, tmp_sp), + sa_tmp_inf = const offset_of!(SigArea, tmp_inf), 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, + + SA_ONSTACK_BIT = const 58, // (1 << 58) >> 32 = 0x0400_0000 + SYS_SIGDEQUEUE = const syscall::SYS_SIGDEQUEUE, + STACK_ALIGN = const 16, + REDZONE_SIZE = const 128, ]); asmfunction!(__relibc_internal_rlct_clone_ret: [" @@ -294,4 +374,10 @@ pub unsafe fn manually_enter_trampoline() { ", inout("x0") ip_location => _, out("lr") _); } -pub unsafe fn arch_pre(stack: &mut SigStack, os: &mut SigArea) {} +pub unsafe fn arch_pre(stack: &mut SigStack, os: &mut SigArea) -> PosixStackt { + PosixStackt { + sp: core::ptr::null_mut(), // TODO + size: 0, // TODO + flags: 0, // TODO + } +}