Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/fiber/src/stackswitch/riscv32imac.rs
3055 views
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
// This file is modelled after riscv64.rs. For reference be sure to review the
9
// other file.
10
11
use core::arch::naked_asm;
12
13
#[inline(never)] // FIXME(rust-lang/rust#148307)
14
pub(crate) unsafe extern "C" fn wasmtime_fiber_switch(top_of_stack: *mut u8) {
15
unsafe { wasmtime_fiber_switch_(top_of_stack) }
16
}
17
18
#[unsafe(naked)]
19
unsafe extern "C" fn wasmtime_fiber_switch_(top_of_stack: *mut u8 /* a0 */) {
20
naked_asm!(
21
"
22
// See https://github.com/rust-lang/rust/issues/80608.
23
.attribute arch, \"rv32i\" // This implementation should work for any
24
// architecture with the same registers as riscv32i, e.g. riscv32imac,
25
// but not riscv32gc.
26
27
// We're switching to arbitrary code somewhere else, so pessimistically
28
// assume that all callee-save register are clobbered. This means we need
29
// to save/restore all of them.
30
//
31
// Note that this order for saving is important since we use CFI directives
32
// below to point to where all the saved registers are.
33
sw ra, -0x4(sp)
34
sw fp, -0x8(sp) // fp is s0
35
sw s1, -0xc(sp)
36
sw s2, -0x10(sp)
37
sw s3, -0x14(sp)
38
sw s4, -0x18(sp)
39
sw s5, -0x1c(sp)
40
sw s6, -0x20(sp)
41
sw s7, -0x24(sp)
42
sw s8, -0x28(sp)
43
sw s9, -0x2c(sp)
44
sw s10, -0x30(sp)
45
sw s11, -0x34(sp)
46
addi sp, sp, -0x40 // Choose 0x40 to be 16-byte aligned
47
48
lw t0, -0x8(a0)
49
sw sp, -0x8(a0)
50
51
// Swap stacks and restore all our callee-saved registers
52
mv sp, t0
53
54
lw s11, 0xc(sp)
55
lw s10, 0x10(sp)
56
lw s9, 0x14(sp)
57
lw s8, 0x18(sp)
58
lw s7, 0x1c(sp)
59
lw s6, 0x20(sp)
60
lw s5, 0x24(sp)
61
lw s4, 0x28(sp)
62
lw s3, 0x2c(sp)
63
lw s2, 0x30(sp)
64
lw s1, 0x34(sp)
65
lw fp, 0x38(sp)
66
lw ra, 0x3c(sp)
67
addi sp, sp, 0x40
68
jr ra
69
",
70
);
71
}
72
73
pub(crate) unsafe fn wasmtime_fiber_init(
74
top_of_stack: *mut u8,
75
entry_point: extern "C" fn(*mut u8, *mut u8),
76
entry_arg0: *mut u8,
77
) {
78
#[repr(C)]
79
#[derive(Default)]
80
struct InitialStack {
81
padding: [u8; 12], // 12 bytes of padding for 16-byte alignment
82
83
s11: *mut u8,
84
s10: *mut u8,
85
s9: *mut u8,
86
s8: *mut u8,
87
s7: *mut u8,
88
s6: *mut u8,
89
s5: *mut u8,
90
s4: *mut u8,
91
s3: *mut u8,
92
s2: *mut u8,
93
s1: *mut u8,
94
fp: *mut u8,
95
96
ra: *mut u8,
97
98
// unix.rs reserved space
99
padding_2: [u8; 8], // 8 bytes of padding for 16-byte alignment
100
last_sp: *mut u8,
101
run_result: *mut u8,
102
}
103
104
unsafe {
105
let initial_stack = top_of_stack.cast::<InitialStack>().sub(1);
106
initial_stack.write(InitialStack {
107
s1: entry_point as *mut u8,
108
s2: entry_arg0,
109
fp: top_of_stack,
110
ra: wasmtime_fiber_start as *mut u8,
111
last_sp: initial_stack.cast(),
112
..InitialStack::default()
113
});
114
}
115
}
116
117
#[unsafe(naked)]
118
unsafe extern "C" fn wasmtime_fiber_start() -> ! {
119
naked_asm!(
120
"
121
.cfi_startproc simple
122
.cfi_def_cfa_offset 0
123
124
125
.cfi_escape 0x0f, /* DW_CFA_def_cfa_expression */ \
126
5, /* the byte length of this expression */ \
127
0x52, /* DW_OP_reg2 (sp) */ \
128
0x06, /* DW_OP_deref */ \
129
0x08, 0x40, /* DW_OP_const1u 0x40 */ \
130
0x22 /* DW_OP_plus */
131
132
133
.cfi_rel_offset ra, -0x4
134
.cfi_rel_offset fp, -0x8
135
.cfi_rel_offset s1, -0xc
136
.cfi_rel_offset s2, -0x10
137
.cfi_rel_offset s3, -0x14
138
.cfi_rel_offset s4, -0x18
139
.cfi_rel_offset s5, -0x1c
140
.cfi_rel_offset s6, -0x20
141
.cfi_rel_offset s7, -0x24
142
.cfi_rel_offset s8, -0x28
143
.cfi_rel_offset s9, -0x2c
144
.cfi_rel_offset s10, -0x30
145
.cfi_rel_offset s11, -0x34
146
147
mv a0, s2
148
mv a1, fp
149
jalr s1
150
// .4byte 0 will cause panic.
151
// for safety just like x86_64.rs and riscv64.rs.
152
.4byte 0
153
.cfi_endproc
154
",
155
);
156
}
157
158