Path: blob/main/crates/fiber/src/stackswitch/x86.rs
3067 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// This file is modeled after x86_64.rs and comments are not copied over. For8// reference be sure to review the other file. Note that the pointer size is9// different so the reserved space at the top of the stack is 8 bytes, not 1610// bytes. Still two pointers though.1112use core::arch::naked_asm;1314#[inline(never)] // FIXME(rust-lang/rust#148307)15pub(crate) unsafe extern "C" fn wasmtime_fiber_switch(top_of_stack: *mut u8) {16unsafe { wasmtime_fiber_switch_(top_of_stack) }17}1819#[unsafe(naked)]20unsafe extern "C" fn wasmtime_fiber_switch_(top_of_stack: *mut u8) {21naked_asm!(22"23// Load our stack-to-use24mov eax, 0x4[esp]25mov ecx, -0x8[eax]2627// Save callee-saved registers28push ebp29push ebx30push esi31push edi3233// Save our current stack and jump to the stack-to-use34mov -0x8[eax], esp35mov esp, ecx3637// Restore callee-saved registers38pop edi39pop esi40pop ebx41pop ebp42ret43",44)45}4647pub(crate) unsafe fn wasmtime_fiber_init(48top_of_stack: *mut u8,49entry_point: extern "C" fn(*mut u8, *mut u8),50entry_arg0: *mut u8,51) {52// Our stack from top-to-bottom looks like:53//54// * 8 bytes of reserved space per unix.rs (two-pointers space)55// * 8 bytes of arguments (two arguments wasmtime_fiber_start forwards)56// * 4 bytes of return address57// * 16 bytes of saved registers58//59// Note that after the return address the stack is conveniently 16-byte60// aligned as required, so we just leave the arguments on the stack in61// `wasmtime_fiber_start` and immediately do the call.62#[repr(C)]63#[derive(Default)]64struct InitialStack {65// state that will get resumed into from a `wasmtime_fiber_switch`66// starting up this fiber.67edi: *mut u8,68esi: *mut u8,69ebx: *mut u8,70ebp: *mut u8,71return_address: *mut u8,7273// two arguments to `entry_point`74arg1: *mut u8,75arg2: *mut u8,7677// unix.rs reserved space78last_sp: *mut u8,79run_result: *mut u8,80}8182unsafe {83let initial_stack = top_of_stack.cast::<InitialStack>().sub(1);84initial_stack.write(InitialStack {85ebp: entry_point as *mut u8,86return_address: wasmtime_fiber_start as *mut u8,87arg1: entry_arg0,88arg2: top_of_stack,89last_sp: initial_stack.cast(),90..InitialStack::default()91});92}93}9495#[unsafe(naked)]96unsafe extern "C" fn wasmtime_fiber_start() -> ! {97naked_asm!(98"99.cfi_startproc simple100.cfi_def_cfa_offset 0101.cfi_escape 0x0f, /* DW_CFA_def_cfa_expression */ \1025, /* the byte length of this expression */ \1030x74, 0x08, /* DW_OP_breg4 (%esp) + 8 */ \1040x06, /* DW_OP_deref */ \1050x23, 0x14 /* DW_OP_plus_uconst 0x14 */106107.cfi_rel_offset eip, -4108.cfi_rel_offset ebp, -8109.cfi_rel_offset ebx, -12110.cfi_rel_offset esi, -16111.cfi_rel_offset edi, -20112113// Our arguments and stack alignment are all prepped by114// `wasmtime_fiber_init`.115call ebp116ud2117.cfi_endproc118",119);120}121122123