1 // A WORD OF CAUTION 2 // 3 // This entire file basically needs to be kept in sync with itself. It's not 4 // really possible to modify just one bit of this file without understanding 5 // all the other bits. Documentation tries to reference various bits here and 6 // there but try to make sure to read over everything before tweaking things! 7 8 use core::arch::naked_asm; 9 10 #[inline(never)] // FIXME(rust-lang/rust#148307) 11 pub(crate) unsafe extern "C" fn wasmtime_fiber_switch(top_of_stack: *mut u8) { 12 unsafe { wasmtime_fiber_switch_(top_of_stack) } 13 } 14 15 #[unsafe(naked)] 16 unsafe extern "C" fn wasmtime_fiber_switch_(top_of_stack: *mut u8 /* a0 */) { 17 naked_asm!( 18 " 19 // See https://github.com/rust-lang/rust/issues/80608. 20 .attribute arch, \"rv64gc\" 21 22 // We're switching to arbitrary code somewhere else, so pessimistically 23 // assume that all callee-save register are clobbered. This means we need 24 // to save/restore all of them. 25 // 26 // Note that this order for saving is important since we use CFI directives 27 // below to point to where all the saved registers are. 28 sd ra,-0x8(sp) 29 sd fp,-0x10(sp) 30 sd s1,-0x18(sp) 31 sd s2,-0x20(sp) 32 sd s3,-0x28(sp) 33 sd s4,-0x30(sp) 34 sd s5,-0x38(sp) 35 sd s6,-0x40(sp) 36 sd s7,-0x48(sp) 37 sd s8,-0x50(sp) 38 sd s9,-0x58(sp) 39 sd s10,-0x60(sp) 40 sd s11,-0x68(sp) 41 fsd fs0,-0x70(sp) 42 fsd fs1,-0x78(sp) 43 fsd fs2,-0x80(sp) 44 fsd fs3,-0x88(sp) 45 fsd fs4,-0x90(sp) 46 fsd fs5,-0x98(sp) 47 fsd fs6,-0xa0(sp) 48 fsd fs7,-0xa8(sp) 49 fsd fs8,-0xb0(sp) 50 fsd fs9,-0xb8(sp) 51 fsd fs10,-0xc0(sp) 52 fsd fs11,-0xc8(sp) 53 addi sp , sp , -0xd0 54 55 ld t0 ,-0x10(a0) 56 sd sp ,-0x10(a0) 57 58 // Swap stacks and restore all our callee-saved registers 59 mv sp,t0 60 61 fld fs11,0x8(sp) 62 fld fs10,0x10(sp) 63 fld fs9,0x18(sp) 64 fld fs8,0x20(sp) 65 fld fs7,0x28(sp) 66 fld fs6,0x30(sp) 67 fld fs5,0x38(sp) 68 fld fs4,0x40(sp) 69 fld fs3,0x48(sp) 70 fld fs2,0x50(sp) 71 fld fs1,0x58(sp) 72 fld fs0,0x60(sp) 73 ld s11,0x68(sp) 74 ld s10,0x70(sp) 75 ld s9,0x78(sp) 76 ld s8,0x80(sp) 77 ld s7,0x88(sp) 78 ld s6,0x90(sp) 79 ld s5,0x98(sp) 80 ld s4,0xa0(sp) 81 ld s3,0xa8(sp) 82 ld s2,0xb0(sp) 83 ld s1,0xb8(sp) 84 ld fp,0xc0(sp) 85 ld ra,0xc8(sp) 86 addi sp , sp , 0xd0 87 jr ra 88 ", 89 ); 90 } 91 92 pub(crate) unsafe fn wasmtime_fiber_init( 93 top_of_stack: *mut u8, 94 entry_point: extern "C" fn(*mut u8, *mut u8), 95 entry_arg0: *mut u8, 96 ) { 97 #[repr(C)] 98 #[derive(Default)] 99 struct InitialStack { 100 align_to_16_byte_size: u64, 101 102 fs: [f64; 12], 103 104 s11: *mut u8, 105 s10: *mut u8, 106 s9: *mut u8, 107 s8: *mut u8, 108 s7: *mut u8, 109 s6: *mut u8, 110 s5: *mut u8, 111 s4: *mut u8, 112 s3: *mut u8, 113 s2: *mut u8, 114 s1: *mut u8, 115 fp: *mut u8, 116 117 ra: *mut u8, 118 119 // unix.rs reserved space 120 last_sp: *mut u8, 121 run_result: *mut u8, 122 } 123 124 unsafe { 125 let initial_stack = top_of_stack.cast::<InitialStack>().sub(1); 126 initial_stack.write(InitialStack { 127 s1: entry_point as *mut u8, 128 s2: entry_arg0, 129 fp: top_of_stack, 130 ra: wasmtime_fiber_start as *mut u8, 131 last_sp: initial_stack.cast(), 132 ..InitialStack::default() 133 }); 134 } 135 } 136 137 #[unsafe(naked)] 138 unsafe extern "C" fn wasmtime_fiber_start() -> ! { 139 naked_asm!( 140 " 141 .cfi_startproc simple 142 .cfi_def_cfa_offset 0 143 144 145 .cfi_escape 0x0f, /* DW_CFA_def_cfa_expression */ \ 146 5, /* the byte length of this expression */ \ 147 0x52, /* DW_OP_reg2 (sp) */ \ 148 0x06, /* DW_OP_deref */ \ 149 0x08, 0xd0 , /* DW_OP_const1u 0xc8 */ \ 150 0x22 /* DW_OP_plus */ 151 152 153 .cfi_rel_offset ra,-0x8 154 .cfi_rel_offset fp,-0x10 155 .cfi_rel_offset s1,-0x18 156 .cfi_rel_offset s2,-0x20 157 .cfi_rel_offset s3,-0x28 158 .cfi_rel_offset s4,-0x30 159 .cfi_rel_offset s5,-0x38 160 .cfi_rel_offset s6,-0x40 161 .cfi_rel_offset s7,-0x48 162 .cfi_rel_offset s8,-0x50 163 .cfi_rel_offset s9,-0x58 164 .cfi_rel_offset s10,-0x60 165 .cfi_rel_offset s11,-0x68 166 .cfi_rel_offset fs0,-0x70 167 .cfi_rel_offset fs1,-0x78 168 .cfi_rel_offset fs2,-0x80 169 .cfi_rel_offset fs3,-0x88 170 .cfi_rel_offset fs4,-0x90 171 .cfi_rel_offset fs5,-0x98 172 .cfi_rel_offset fs6,-0xa0 173 .cfi_rel_offset fs7,-0xa8 174 .cfi_rel_offset fs8,-0xb0 175 .cfi_rel_offset fs9,-0xb8 176 .cfi_rel_offset fs10,-0xc0 177 .cfi_rel_offset fs11,-0xc8 178 179 mv a0,s2 180 mv a1,fp 181 jalr s1 182 // .4byte 0 will cause panic. 183 // for safety just like x86_64.rs. 184 .4byte 0 185 .cfi_endproc 186 ", 187 ); 188 } 189