@@ -109,7 +109,12 @@ macro_rules! define_rust_probestack {
109
109
//
110
110
// The ABI here is that the stack frame size is located in `%rax`. Upon
111
111
// return we're not supposed to modify `%rsp` or `%rax`.
112
- #[ cfg( target_arch = "x86_64" ) ]
112
+ //
113
+ // Any changes to this function should be replicated to the SGX version below.
114
+ #[ cfg( all(
115
+ target_arch = "x86_64" ,
116
+ not( all( target_env = "sgx" , target_vendor = "fortanix" ) )
117
+ ) ) ]
113
118
global_asm ! ( define_rust_probestack!(
114
119
"
115
120
.cfi_startproc
@@ -163,6 +168,69 @@ global_asm!(define_rust_probestack!(
163
168
"
164
169
) ) ;
165
170
171
+ // This function is the same as above, except that some instructions are
172
+ // [manually patched for LVI].
173
+ //
174
+ // [manually patched for LVI]: https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection#specialinstructions
175
+ #[ cfg( all(
176
+ target_arch = "x86_64" ,
177
+ all( target_env = "sgx" , target_vendor = "fortanix" )
178
+ ) ) ]
179
+ global_asm ! ( define_rust_probestack!(
180
+ "
181
+ .cfi_startproc
182
+ pushq %rbp
183
+ .cfi_adjust_cfa_offset 8
184
+ .cfi_offset %rbp, -16
185
+ movq %rsp, %rbp
186
+ .cfi_def_cfa_register %rbp
187
+
188
+ mov %rax,%r11 // duplicate %rax as we're clobbering %r11
189
+
190
+ // Main loop, taken in one page increments. We're decrementing rsp by
191
+ // a page each time until there's less than a page remaining. We're
192
+ // guaranteed that this function isn't called unless there's more than a
193
+ // page needed.
194
+ //
195
+ // Note that we're also testing against `8(%rsp)` to account for the 8
196
+ // bytes pushed on the stack orginally with our return address. Using
197
+ // `8(%rsp)` simulates us testing the stack pointer in the caller's
198
+ // context.
199
+
200
+ // It's usually called when %rax >= 0x1000, but that's not always true.
201
+ // Dynamic stack allocation, which is needed to implement unsized
202
+ // rvalues, triggers stackprobe even if %rax < 0x1000.
203
+ // Thus we have to check %r11 first to avoid segfault.
204
+ cmp $0x1000,%r11
205
+ jna 3f
206
+ 2:
207
+ sub $0x1000,%rsp
208
+ test %rsp,8(%rsp)
209
+ sub $0x1000,%r11
210
+ cmp $0x1000,%r11
211
+ ja 2b
212
+
213
+ 3:
214
+ // Finish up the last remaining stack space requested, getting the last
215
+ // bits out of r11
216
+ sub %r11,%rsp
217
+ test %rsp,8(%rsp)
218
+
219
+ // Restore the stack pointer to what it previously was when entering
220
+ // this function. The caller will readjust the stack pointer after we
221
+ // return.
222
+ add %rax,%rsp
223
+
224
+ leave
225
+ .cfi_def_cfa_register %rsp
226
+ .cfi_adjust_cfa_offset -8
227
+ pop %r11
228
+ lfence
229
+ jmp *%r11
230
+ .cfi_endproc
231
+ "
232
+ ) ) ;
233
+
166
234
#[ cfg( target_arch = "x86" ) ]
167
235
// This is the same as x86_64 above, only translated for 32-bit sizes. Note
168
236
// that on Unix we're expected to restore everything as it was, this
0 commit comments