Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/fiber/src/stackswitch/arm.rs
3054 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
// Also at this time this file is heavily based off the x86_64 file, so you'll
9
// probably want to read that one as well.
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 /* r0 */) {
20
naked_asm!(
21
"
22
// Save callee-saved registers
23
push {{r4-r11,lr}}
24
25
// Swap stacks, recording our current stack pointer
26
ldr r4, [r0, #-0x08]
27
str sp, [r0, #-0x08]
28
mov sp, r4
29
30
// Restore and return
31
pop {{r4-r11,lr}}
32
bx lr
33
",
34
);
35
}
36
37
pub(crate) unsafe fn wasmtime_fiber_init(
38
top_of_stack: *mut u8,
39
entry_point: extern "C" fn(*mut u8, *mut u8),
40
entry_arg0: *mut u8,
41
) {
42
#[repr(C)]
43
#[derive(Default)]
44
struct InitialStack {
45
r4: *mut u8,
46
r5: *mut u8,
47
r6: *mut u8,
48
r7: *mut u8,
49
r8: *mut u8,
50
r9: *mut u8,
51
r10: *mut u8,
52
r11: *mut u8,
53
lr: *mut u8,
54
55
// unix.rs reserved space
56
last_sp: *mut u8,
57
run_result: *mut u8,
58
}
59
60
unsafe {
61
let initial_stack = top_of_stack.cast::<InitialStack>().sub(1);
62
initial_stack.write(InitialStack {
63
r9: entry_arg0,
64
r10: entry_point as *mut u8,
65
r11: top_of_stack,
66
lr: wasmtime_fiber_start as *mut u8,
67
last_sp: initial_stack.cast(),
68
..InitialStack::default()
69
});
70
}
71
}
72
73
#[unsafe(naked)]
74
unsafe extern "C" fn wasmtime_fiber_start() -> ! {
75
naked_asm!(
76
"
77
.cfi_startproc simple
78
.cfi_def_cfa_offset 0
79
// See the x86_64 file for more commentary on what these CFI directives
80
// are doing. Like over there note that the relative offsets to
81
// registers here match the frame layout in `wasmtime_fiber_switch`.
82
//
83
// TODO: this is only lightly tested. This gets backtraces in gdb but
84
// not at runtime. Perhaps the libgcc at runtime was too old? Doesn't
85
// support something here? Unclear. Will need investigation if someone
86
// ends up needing this and it still doesn't work.
87
.cfi_escape 0x0f, /* DW_CFA_def_cfa_expression */ \
88
5, /* the byte length of this expression */ \
89
0x7d, 0x00, /* DW_OP_breg14(%sp) + 0 */ \
90
0x06, /* DW_OP_deref */ \
91
0x23, 0x24 /* DW_OP_plus_uconst 0x24 */
92
93
.cfi_rel_offset lr, -0x04
94
.cfi_rel_offset r11, -0x08
95
.cfi_rel_offset r10, -0x0c
96
.cfi_rel_offset r9, -0x10
97
.cfi_rel_offset r8, -0x14
98
.cfi_rel_offset r7, -0x18
99
.cfi_rel_offset r6, -0x1c
100
.cfi_rel_offset r5, -0x20
101
.cfi_rel_offset r4, -0x24
102
103
mov r1, r11
104
mov r0, r9
105
blx r10
106
.cfi_endproc
107
",
108
);
109
}
110
111