Path: blob/main/crates/fiber/src/stackswitch/arm.rs
3054 views
// A WORD OF CAUTION1//2// This entire file basically needs to be kept in sync with itself. It's not3// really possible to modify just one bit of this file without understanding4// all the other bits. Documentation tries to reference various bits here and5// there but try to make sure to read over everything before tweaking things!6//7// Also at this time this file is heavily based off the x86_64 file, so you'll8// probably want to read that one as well.910use core::arch::naked_asm;1112#[inline(never)] // FIXME(rust-lang/rust#148307)13pub(crate) unsafe extern "C" fn wasmtime_fiber_switch(top_of_stack: *mut u8) {14unsafe { wasmtime_fiber_switch_(top_of_stack) }15}1617#[unsafe(naked)]18unsafe extern "C" fn wasmtime_fiber_switch_(top_of_stack: *mut u8 /* r0 */) {19naked_asm!(20"21// Save callee-saved registers22push {{r4-r11,lr}}2324// Swap stacks, recording our current stack pointer25ldr r4, [r0, #-0x08]26str sp, [r0, #-0x08]27mov sp, r42829// Restore and return30pop {{r4-r11,lr}}31bx lr32",33);34}3536pub(crate) unsafe fn wasmtime_fiber_init(37top_of_stack: *mut u8,38entry_point: extern "C" fn(*mut u8, *mut u8),39entry_arg0: *mut u8,40) {41#[repr(C)]42#[derive(Default)]43struct InitialStack {44r4: *mut u8,45r5: *mut u8,46r6: *mut u8,47r7: *mut u8,48r8: *mut u8,49r9: *mut u8,50r10: *mut u8,51r11: *mut u8,52lr: *mut u8,5354// unix.rs reserved space55last_sp: *mut u8,56run_result: *mut u8,57}5859unsafe {60let initial_stack = top_of_stack.cast::<InitialStack>().sub(1);61initial_stack.write(InitialStack {62r9: entry_arg0,63r10: entry_point as *mut u8,64r11: top_of_stack,65lr: wasmtime_fiber_start as *mut u8,66last_sp: initial_stack.cast(),67..InitialStack::default()68});69}70}7172#[unsafe(naked)]73unsafe extern "C" fn wasmtime_fiber_start() -> ! {74naked_asm!(75"76.cfi_startproc simple77.cfi_def_cfa_offset 078// See the x86_64 file for more commentary on what these CFI directives79// are doing. Like over there note that the relative offsets to80// registers here match the frame layout in `wasmtime_fiber_switch`.81//82// TODO: this is only lightly tested. This gets backtraces in gdb but83// not at runtime. Perhaps the libgcc at runtime was too old? Doesn't84// support something here? Unclear. Will need investigation if someone85// ends up needing this and it still doesn't work.86.cfi_escape 0x0f, /* DW_CFA_def_cfa_expression */ \875, /* the byte length of this expression */ \880x7d, 0x00, /* DW_OP_breg14(%sp) + 0 */ \890x06, /* DW_OP_deref */ \900x23, 0x24 /* DW_OP_plus_uconst 0x24 */9192.cfi_rel_offset lr, -0x0493.cfi_rel_offset r11, -0x0894.cfi_rel_offset r10, -0x0c95.cfi_rel_offset r9, -0x1096.cfi_rel_offset r8, -0x1497.cfi_rel_offset r7, -0x1898.cfi_rel_offset r6, -0x1c99.cfi_rel_offset r5, -0x20100.cfi_rel_offset r4, -0x24101102mov r1, r11103mov r0, r9104blx r10105.cfi_endproc106",107);108}109110111