Skip to content

Commit efe7504

Browse files
author
Simon Leet
committed
Preserve Windows & Linux ABI expectations on ECALL
This changeset reconciles some of the ABI inconsistencies when calling from a Windows host process into an Linux-based enclave. This includes: - Initialize the MXCSR, RFLAGS and x87 FPU control word on ECALL to ensure that the enclave can expect the Linux x86_64 ABI-specified initial process state. - Preserve the Windows x64 ABI-specified callee-preserved registers, x87 FPU, MMX, XMM and MXCSR states before each ECALL and restore them on return or OCALL. - Update return_from_ecall to use r10 instead of callee-preserved rbx register as a temporary register.
1 parent d2f8a09 commit efe7504

File tree

5 files changed

+155
-51
lines changed

5 files changed

+155
-51
lines changed

enclave/core/sgx/enter.S

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,23 @@ oe_enter:
119119
mov %rsp, %rbp
120120

121121
.call_function:
122+
// Set the MXCSR according to the Linux x86_64 ABI
123+
mov $ABI_MXCSR_INIT, %r10
124+
push %r10
125+
ldmxcsr (%rsp)
126+
pop %r10
127+
128+
// Set the FPU Control Word according to the Linux x86_64 ABI
129+
mov $ABI_FPUCW_INIT, %r10
130+
push %r10
131+
fldcw (%rsp)
132+
pop %r10
133+
134+
// Initialize the RFLAGS prior to calling enclave functions
135+
// This only clears the DF and state flag bits since
136+
// the system flags and reserved bits are not writable here
137+
push $0
138+
popfq
122139

123140
// Get the host stack pointer.
124141
mov %gs:td_host_rsp, %r8

host/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ if (OE_SGX)
175175
sgx/windows/aesm.c
176176
sgx/windows/enter.asm
177177
sgx/windows/entersim.asm
178+
sgx/windows/host_context.asm
178179
sgx/windows/exception.c
179180
sgx/windows/xstate.c)
180181
endif()

host/sgx/windows/enter.asm

Lines changed: 53 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
include ksamd64.inc
55

66
extern __oe_dispatch_ocall:proc
7+
extern oe_save_host_context:proc
8+
extern oe_restore_host_context:proc
79

810
;;==============================================================================
911
;;
@@ -16,13 +18,14 @@ extern __oe_dispatch_ocall:proc
1618
;; [OUT] uint64_t* arg4,
1719
;; [OUT] oe_enclave_t* enclave);
1820
;;
19-
;; Registers:
21+
;; Parameters passed on register and stack:
2022
;; RCX - tcs: thread control structure (extended)
2123
;; RDX - aep: asynchronous execution procedure
2224
;; R8 - arg1
2325
;; R9 - arg2
2426
;; [RBP+48] - arg3
2527
;; [RBP+56] - arg4
28+
;; [RBP+64] - enclave
2629
;;
2730
;; These registers may be destroyed across function calls:
2831
;; RAX, RCX, RDX, R8, R9, R10, R11
@@ -33,7 +36,11 @@ extern __oe_dispatch_ocall:proc
3336
;;==============================================================================
3437

3538
ENCLU_EENTER EQU 2
36-
PARAMS_SPACE EQU 128
39+
40+
ARG3_PARAM EQU [rbp+48]
41+
ARG4_PARAM EQU [rbp+56]
42+
ENCLAVE_PARAM EQU [rbp+64]
43+
3744
TCS EQU [rbp-8]
3845
AEP EQU [rbp-16]
3946
ARG1 EQU [rbp-24]
@@ -44,52 +51,53 @@ ENCLAVE EQU [rbp-56]
4451
ARG1OUT EQU [rbp-64]
4552
ARG2OUT EQU [rbp-72]
4653
STACKPTR EQU [rbp-80]
47-
MXCSR EQU [rbp-88]
54+
HOST_CONTEXT EQU [rbp-88]
55+
56+
;; Reserve parameter space based on:
57+
;; + 88 bytes for 11*8-byte parameters TCS to HOST_CONTEXT
58+
;; HOST_CONTEXT points to the start of the context data consisting of:
59+
;; + 64 bytes for 8*8-byte callee-preserved registers
60+
;; + 512-byte OE_CONTEXT_FLOAT memory image used in fxsave/fxrstor
61+
;; + 8 bytes so that the stack remains 16-byte aligned.
62+
PARAMS_SPACE EQU 672
4863

4964
NESTED_ENTRY oe_enter, _TEXT$00
5065
END_PROLOGUE
5166

5267
;; Setup stack frame:
53-
push rbp
68+
push rbp ;; Stack is 16-byte aligned at this point
5469
mov rbp, rsp
5570

5671
;; Save parameters on stack for later reference:
5772
;; TCS := [RBP-8] <- RCX
5873
;; AEP := [RBP-16] <- RDX
5974
;; ARG1 := [RBP-24] <- R8
6075
;; ARG2 := [RBP-32] <- R9
61-
;; ARG3 := [RBP-40] <- [RBP+48]
62-
;; ARG4 := [RBP-48] <- [RBP+56]
63-
;; ENCLAVE := [RBP-56] <- [RBP+64]
64-
;; MXCSR := [RBP-88]
76+
;; ARG3 := [RBP-40] <- ARG3_PARAM := [RBP+48]
77+
;; ARG4 := [RBP-48] <- ARG4_PARAM := [RBP+56]
78+
;; ENCLAVE := [RBP-56] <- ENCLAVE_PARAM := [RBP+64]
79+
;; HOST_CONTEXT := [RBP-88]
6580
sub rsp, PARAMS_SPACE
6681
mov TCS, rcx
6782
mov AEP, rdx
6883
mov ARG1, r8
6984
mov ARG2, r9
70-
mov rax, [rbp+48]
85+
mov rax, ARG3_PARAM
7186
mov ARG3, rax
72-
mov rax, [rbp+56]
87+
mov rax, ARG4_PARAM
7388
mov ARG4, rax
74-
mov rax, [rbp+64]
89+
mov rax, ENCLAVE_PARAM
7590
mov ENCLAVE, rax
7691

77-
;;Save the current context
78-
79-
;;Save the SSE status and control flags
80-
stmxcsr MXCSR
81-
82-
;; Save registers:
83-
push rbx
84-
push rdi
85-
push rsi
86-
push r12
87-
push r13
88-
push r14
89-
push r15
92+
;; Set the save location for the host context on the host stack
93+
mov HOST_CONTEXT, rsp
9094

9195
execute_eenter:
92-
96+
97+
;; Save the current host context
98+
mov rcx, HOST_CONTEXT
99+
call oe_save_host_context
100+
93101
;; Save the stack pointer so enclave can use the stack.
94102
mov STACKPTR, rsp
95103

@@ -103,10 +111,11 @@ execute_eenter:
103111

104112
mov ARG1OUT, rdi
105113
mov ARG2OUT, rsi
106-
107-
;; Restore the saved MXCSR
108-
ldmxcsr MXCSR
109-
114+
115+
;; Restore the saved host context
116+
mov rcx, HOST_CONTEXT
117+
call oe_restore_host_context
118+
110119
dispatch_ocall:
111120
;; RAX = __oe_dispatch_ocall(
112121
;; RCX=arg1
@@ -115,7 +124,10 @@ dispatch_ocall:
115124
;; R9=arg2_out
116125
;; [RSP+32]=TCS,
117126
;; [RSP+40]=ENCLAVE);
118-
sub rsp, 56
127+
;;
128+
;; Stack should already be 16-byte aligned, so only need
129+
;; shadow space (32 bytes) plus stack params size (16 bytes)
130+
sub rsp, 48
119131
mov rcx, ARG1OUT
120132
mov rdx, ARG2OUT
121133
lea r8, qword ptr ARG1OUT
@@ -125,9 +137,9 @@ dispatch_ocall:
125137
mov rax, qword ptr ENCLAVE
126138
mov qword ptr [rsp+40], rax
127139
call __oe_dispatch_ocall ;; RAX contains return value
128-
add rsp, 56
140+
add rsp, 48
129141

130-
;; Restore the stack pointer:
142+
;; Restore the stack pointer
131143
mov rsp, STACKPTR
132144

133145
;; If this was not an OCALL, then return from ECALL.
@@ -149,29 +161,19 @@ return_from_ecall:
149161
lfence
150162

151163
;; Set ARG3 (out)
152-
mov rbx, ARG1OUT
153-
mov rax, qword ptr [rbp+48]
154-
mov qword ptr [rax], rbx
164+
mov r10, ARG1OUT
165+
mov rax, qword ptr ARG3_PARAM
166+
mov qword ptr [rax], r10
155167

156168
;; Set ARG4 (out)
157-
mov rbx, ARG2OUT
158-
mov rax, qword ptr [rbp+56]
159-
mov qword ptr [rax], rbx
160-
161-
;; Restore registers:
162-
pop r15
163-
pop r14
164-
pop r13
165-
pop r12
166-
pop rsi
167-
pop rdi
168-
pop rbx
169-
169+
mov r10, ARG2OUT
170+
mov rax, qword ptr ARG4_PARAM
171+
mov qword ptr [rax], r10
170172

171-
;; Return parameters space:
172-
add rsp, PARAMS_SPACE
173+
;; Return parameters space and restore the stack pointer
174+
mov rsp, rbp
173175

174-
;; Restore stack frame:
176+
;; Restore stack frame
175177
pop rbp
176178

177179
BEGIN_EPILOGUE

host/sgx/windows/host_context.asm

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
;; Copyright (c) Microsoft Corporation. All rights reserved.
2+
;; Licensed under the MIT License.
3+
4+
OE_CONTEXT_FLAGS EQU 00
5+
OE_CONTEXT_RBX EQU 08
6+
OE_CONTEXT_RDI EQU 16
7+
OE_CONTEXT_RSI EQU 24
8+
OE_CONTEXT_R12 EQU 32
9+
OE_CONTEXT_R13 EQU 40
10+
OE_CONTEXT_R14 EQU 48
11+
OE_CONTEXT_R15 EQU 56
12+
OE_CONTEXT_FLOAT EQU 64
13+
14+
.CODE
15+
16+
PUBLIC oe_save_host_context
17+
oe_save_host_context PROC
18+
;; Subroutine prologue
19+
push rbp
20+
mov rbp, rsp
21+
22+
;; Save the flags to stack.
23+
pushf
24+
mov rax, [rsp]
25+
mov [rcx+OE_CONTEXT_FLAGS], rax
26+
popf
27+
28+
;; Save general registers.
29+
mov [rcx+OE_CONTEXT_RBX], rbx
30+
mov [rcx+OE_CONTEXT_RDI], rdi
31+
mov [rcx+OE_CONTEXT_RSI], rsi
32+
mov [rcx+OE_CONTEXT_R12], r12
33+
mov [rcx+OE_CONTEXT_R13], r13
34+
mov [rcx+OE_CONTEXT_R14], r14
35+
mov [rcx+OE_CONTEXT_R15], r15
36+
37+
;; Save x87 FPU, MMX and SSE state (includes MXCSR and XMM registers).
38+
fxsave [rcx+OE_CONTEXT_FLOAT]
39+
40+
;; Subroutine epilogue
41+
mov rsp, rbp
42+
pop rbp
43+
ret
44+
45+
oe_save_host_context ENDP
46+
47+
PUBLIC oe_restore_host_context
48+
oe_restore_host_context PROC
49+
50+
;; Subroutine prologue
51+
push rbp
52+
mov rbp, rsp
53+
54+
;; Restore the flags to stack.
55+
push [rcx+OE_CONTEXT_FLAGS]
56+
popfq
57+
58+
;; Restore general registers.
59+
mov rbx, [rcx+OE_CONTEXT_RBX]
60+
mov rdi, [rcx+OE_CONTEXT_RDI]
61+
mov rsi, [rcx+OE_CONTEXT_RSI]
62+
mov r12, [rcx+OE_CONTEXT_R12]
63+
mov r13, [rcx+OE_CONTEXT_R13]
64+
mov r14, [rcx+OE_CONTEXT_R14]
65+
mov r15, [rcx+OE_CONTEXT_R15]
66+
67+
;; Restore x87 FPU, MMX and SSE state (includes MXCSR and XMM registers).
68+
fxrstor [rcx+OE_CONTEXT_FLOAT]
69+
70+
;; Subroutine epilogue
71+
mov rsp, rbp
72+
pop rbp
73+
ret
74+
75+
oe_restore_host_context ENDP
76+
77+
END
78+

include/openenclave/internal/constants_x64.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,10 @@
7171
// AMD64 ABI needs a 128 bytes red zone.
7272
#define ABI_REDZONE_BYTE_SIZE 0x80
7373

74+
// MXCSR initialization value for Linux x86_64 ABI in enclave
75+
#define ABI_MXCSR_INIT 0x1F80
76+
77+
// x87 FPU control word initialization value for Linux x86_64 ABI in enclave
78+
#define ABI_FPUCW_INIT 0x037F
79+
7480
#endif /* _OE_INTERNAL_CONSTANTS_X64_H */

0 commit comments

Comments
 (0)