Skip to content

Commit 3dc6b5e

Browse files
authored
Add fiber implementation for riscv32imac (#12506)
* Add fiber implementation for riscv32imac * Adjusted formatting around commas * Added padding infront of `last_sp`
1 parent 40215f2 commit 3dc6b5e

File tree

3 files changed

+247
-87
lines changed

3 files changed

+247
-87
lines changed

crates/fiber/src/stackswitch.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ cfg_if::cfg_if! {
2929
mod riscv64;
3030
pub(crate) use supported::*;
3131
pub(crate) use riscv64::*;
32+
} else if #[cfg(all(target_arch = "riscv32", not(target_feature = "f"), not(target_feature = "v")))] {
33+
mod riscv32imac;
34+
pub(crate) use supported::*;
35+
pub(crate) use riscv32imac::*;
3236
} else {
3337
// No support for this platform. Don't fail compilation though and
3438
// instead defer the error to happen at runtime when a fiber is created.
@@ -38,7 +42,7 @@ cfg_if::cfg_if! {
3842
}
3943
}
4044

41-
/// A helper module to get reeported above in each case that we actually have
45+
/// A helper module to get reexported above in each case that we actually have
4246
/// stack-switching routines available in inline asm. The fall-through case
4347
/// though reexports the `unsupported` module instead.
4448
#[allow(
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
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+
}

crates/fiber/src/stackswitch/riscv64.rs

Lines changed: 86 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -25,65 +25,65 @@ unsafe extern "C" fn wasmtime_fiber_switch_(top_of_stack: *mut u8 /* a0 */) {
2525
//
2626
// Note that this order for saving is important since we use CFI directives
2727
// 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)
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)
5757
5858
// 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
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
8787
jr ra
8888
",
8989
);
@@ -146,38 +146,38 @@ unsafe extern "C" fn wasmtime_fiber_start() -> ! {
146146
5, /* the byte length of this expression */ \
147147
0x52, /* DW_OP_reg2 (sp) */ \
148148
0x06, /* DW_OP_deref */ \
149-
0x08, 0xd0 , /* DW_OP_const1u 0xc8 */ \
149+
0x08, 0xd0, /* DW_OP_const1u 0xc8 */ \
150150
0x22 /* DW_OP_plus */
151151
152152
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
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
181181
jalr s1
182182
// .4byte 0 will cause panic.
183183
// for safety just like x86_64.rs.

0 commit comments

Comments
 (0)