Path: blob/main/crates/fiber/src/stackswitch/s390x.rs
2459 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!67use core::arch::naked_asm;89#[inline(never)] // FIXME(rust-lang/rust#148307)10pub(crate) unsafe extern "C" fn wasmtime_fiber_switch(top_of_stack: *mut u8) {11unsafe { wasmtime_fiber_switch_(top_of_stack) }12}1314#[unsafe(naked)]15unsafe extern "C" fn wasmtime_fiber_switch_(top_of_stack: *mut u8 /* x0 */) {16naked_asm!(17"18// Save all callee-saved registers on the stack since we're assuming19// they're clobbered as a result of the stack switch.20stmg %r6, %r15, 48(%r15)21aghi %r15, -6422std %f8, 0(%r15)23std %f9, 8(%r15)24std %f10, 16(%r15)25std %f11, 24(%r15)26std %f12, 32(%r15)27std %f13, 40(%r15)28std %f14, 48(%r15)29std %f15, 56(%r15)3031// Load our previously saved stack pointer to resume to, and save off our32// current stack pointer on where to come back to eventually.33lg %r1, -16(%r2)34stg %r15, -16(%r2)3536// Switch to the new stack and restore all our callee-saved registers after37// the switch and return to our new stack.38ld %f8, 0(%r1)39ld %f9, 8(%r1)40ld %f10, 16(%r1)41ld %f11, 24(%r1)42ld %f12, 32(%r1)43ld %f13, 40(%r1)44ld %f14, 48(%r1)45ld %f15, 56(%r1)46lmg %r6, %r15, 112(%r1)47br %r1448",49);50}5152pub(crate) unsafe fn wasmtime_fiber_init(53top_of_stack: *mut u8,54entry_point: extern "C" fn(*mut u8, *mut u8),55entry_arg0: *mut u8,56) {57#[repr(C)]58#[derive(Default)]59struct InitialStack {60f8: *mut u8,61f9: *mut u8,62f10: *mut u8,63f11: *mut u8,64f12: *mut u8,65f13: *mut u8,66f14: *mut u8,67f15: *mut u8,6869back_chain: *mut u8,70compiler_reserved: *mut u8,7172r2: *mut u8,73r3: *mut u8,74r4: *mut u8,75r5: *mut u8,7677r6: *mut u8,78r7: *mut u8,79r8: *mut u8,80r9: *mut u8,81r10: *mut u8,82r11: *mut u8,83r12: *mut u8,84r13: *mut u8,85r14: *mut u8,86r15: *mut u8,8788f0: *mut u8,89f2: *mut u8,90f4: *mut u8,91f6: *mut u8,9293// unix.rs reserved space94last_sp: *mut u8,95run_result: *mut u8,96}9798unsafe {99let initial_stack = top_of_stack.cast::<InitialStack>().sub(1);100initial_stack.write(InitialStack {101r15: (&raw mut (*initial_stack).back_chain).cast(),102r14: wasmtime_fiber_start as *mut u8,103r6: top_of_stack,104r7: entry_point as *mut u8,105r8: entry_arg0,106107last_sp: initial_stack.cast(),108..InitialStack::default()109});110}111}112113#[unsafe(naked)]114unsafe extern "C" fn wasmtime_fiber_start() -> ! {115naked_asm!(116"117.cfi_startproc simple118.cfi_def_cfa_offset 0119120// See the x86_64 file for more commentary on what these CFI directives are121// doing. Like over there note that the relative offsets to registers here122// match the frame layout in `wasmtime_fiber_switch`.123.cfi_escape 0x0f, /* DW_CFA_def_cfa_expression */ \1247, /* the byte length of this expression */ \1250x7f, 0xa0, 0x1, /* DW_OP_breg15 0x90 */ \1260x06, /* DW_OP_deref */ \1270x23, 0xe0, 0x1 /* DW_OP_plus_uconst 0xe0 */128129.cfi_rel_offset 6, -112130.cfi_rel_offset 7, -104131.cfi_rel_offset 8, -96132.cfi_rel_offset 9, -88133.cfi_rel_offset 10, -80134.cfi_rel_offset 11, -72135.cfi_rel_offset 12, -64136.cfi_rel_offset 13, -56137.cfi_rel_offset 14, -48138.cfi_rel_offset 15, -40139140// Load our two arguments prepared by `wasmtime_fiber_init`.141lgr %r2, %r8 // entry_arg0142lgr %r3, %r6 // top_of_stack143144// ... and then we call the function! Note that this is a function call so145// our frame stays on the stack to backtrace through.146basr %r14, %r7 // entry_point147// .. technically we shouldn't get here, so just trap.148.word 0x0000149.cfi_endproc150",151);152}153154155