swap_stack_x64_sel4_rumprun_sysv.S 4.01 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# Copyright 2017 The Australian National University
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#     http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#include "asm_common_x64_sel4_rumprun.S.inc"

# swap_stack_to(new_sp: Address, entry: Address, old_sp_loc: Address)
#               %rdi             %rsi            %rdx
begin_func swap_to_mu_stack
          # -- on old stack --
          # C calling convention
          pushq %rbp
          movq %rsp, %rbp

          # other callee-saved registers
          pushq %rbx
          pushq %r12
          pushq %r13
          pushq %r14
          pushq %r15

          # save sp to %rbx
          movq %rsp, 0(%rdx)

          # switch to new stack
          movq %rdi, %rsp
          # save entry function in %rax
          movq %rsi, %rax

          # -- on new stack --
          # arguments (reverse order of thread.rs - runtime_load_args)
          popq %r9
          popq %r8
          popq %rcx
          popq %rdx
          popq %rsi
          popq %rdi
          movsd 0(%rsp), %xmm7
          movsd 8(%rsp), %xmm6
          movsd 16(%rsp), %xmm5
          movsd 24(%rsp), %xmm4
          movsd 32(%rsp), %xmm3
          movsd 40(%rsp), %xmm2
          movsd 48(%rsp), %xmm1
          movsd 56(%rsp), %xmm0
          add $64, %rsp
          # at this point new stack is clean (no intermediate values)

          movq %rsp, %rbp

          # push an empty pointer to stack, if entry fucntion tries to return, it causes a segfault
          pushq $0
          # push entry function and start it
          pushq %rax
          ret
end_func swap_to_mu_stack

# _swap_back_to_native_stack(sp_loc: Address)
#                            %rdi
begin_func muentry_swap_back_to_native_stack
          movq 0(%rdi), %rsp

          popq %r15
          popq %r14
          popq %r13
          popq %r12
          popq %rbx

          popq %rbp
          ret
end_func muentry_swap_back_to_native_stack

# _get_current_frame_rbp() -> Address
begin_func get_current_frame_rbp
          movq %rbp, %rax
          ret
end_func get_current_frame_rbp

# muentry_throw_exception(obj: Address)
#                         %rdi
begin_func muentry_throw_exception
         # save all callee-saved
         pushq %r15
         pushq %r14
         pushq %r13
         pushq %r12
         pushq %rbp
         pushq %rbx

         # %rsp points to %rbx, pass this as 2nd argument
         movq  %rsp, %rsi

         jmp CNAME(throw_exception_internal@PLT)
         # won't return

# _exception_restore(dest: Address, callee_saved: *const Word, rsp: Address) -> !
#                    %rdi           %rsi                       %rdx
# callee_saved: [rbx, rbp, r12, r13, r14, r15]
begin_func exception_restore
          movq 0(%rsi), %rbx
          movq 8(%rsi), %rbp
          movq 16(%rsi),%r12
          movq 24(%rsi),%r13
          movq 32(%rsi),%r14
          movq 40(%rsi),%r15

          movq %rdx, %rsp
          jmpq *%rdi
end_func exception_restore

# fake_swap_mu_thread(old_sp_loc: Address)
#                     %rdi
# (we do not actually swap stack, but we make the stack the same
# as if they are native stack that have been swapped out, so that
# when THREADEXIT (swap_back_to_native_stack) is called, we won't panic

# this function is untested!!!
begin_func fake_swap_mu_thread
    # save return address
    movq (%rsp), %rax

    pushq %rbp
    movq %rsp, %rbp

    pushq %rbx
    pushq %r12
    pushq %r13
    pushq %r14
    pushq %r15

    # save old sp to thread field
    movq %rsp, 0(%rdi)

    # return to caller, but preserve those pushed values (since THREADEXIT will pick them up)
    pushq %rax
    ret