Skip to content

Commit 27437f9

Browse files
committed
use ELF-TLS on SGX
1 parent f34356e commit 27437f9

File tree

10 files changed

+134
-328
lines changed

10 files changed

+134
-328
lines changed

compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::borrow::Cow;
22

3-
use super::{cvs, Cc, LinkerFlavor, Lld, Target, TargetOptions};
3+
use super::{cvs, Cc, LinkerFlavor, Lld, Target, TargetOptions, TlsModel};
44

55
pub fn target() -> Target {
66
let pre_link_args = TargetOptions::link_args(
@@ -53,6 +53,9 @@ pub fn target() -> Target {
5353
"EH_FRM_LEN",
5454
"TEXT_BASE",
5555
"TEXT_SIZE",
56+
"TLS_INIT_BASE",
57+
"TLS_INIT_SIZE",
58+
"TLS_OFFSET",
5659
];
5760
let opts = TargetOptions {
5861
os: "unknown".into(),
@@ -69,6 +72,8 @@ pub fn target() -> Target {
6972
pre_link_args,
7073
override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(Cow::from).collect()),
7174
relax_elf_relocations: true,
75+
has_thread_local: true,
76+
tls_model: TlsModel::LocalExec,
7277
..Default::default()
7378
};
7479
Target {

library/std/src/sys/sgx/abi/entry.S

+53-58
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ IMAGE_BASE:
6868
globvar EH_FRM_OFFSET 8
6969
/* The size in bytes of enclacve .eh_frame section */
7070
globvar EH_FRM_LEN 8
71+
/* The base address (relative to enclave start) of the TLS initialization image */
72+
globvar TLS_INIT_BASE 8
73+
/* The size in bytes of the TLS initialization image */
74+
globvar TLS_INIT_SIZE 8
75+
/* The TLS module offset of this enclave (see the ELF-TLS specification for more details) */
76+
globvar TLS_OFFSET 8
7177

7278
.org .Lxsave_clear+512
7379
.Lxsave_header:
@@ -80,32 +86,32 @@ IMAGE_BASE:
8086
.byte 0
8187

8288
/* TCS local storage section */
83-
.equ tcsls_tos, 0x00 /* initialized by loader to *offset* from image base to TOS */
84-
.equ tcsls_flags, 0x08 /* initialized by loader */
89+
.equ tcsls_tp, 0x00 /* initialized by loader to *offset* from image base to this field */
90+
.equ tcsls_tos, 0x08 /* initialized by loader to *offset* from image base to TOS */
91+
.equ tcsls_flags, 0x10 /* initialized by loader */
8592
.equ tcsls_flag_secondary, 0 /* initialized by loader; 0 = standard TCS, 1 = secondary TCS */
8693
.equ tcsls_flag_init_once, 1 /* initialized by loader to 0 */
8794
/* 14 unused bits */
88-
.equ tcsls_user_fcw, 0x0a
89-
.equ tcsls_user_mxcsr, 0x0c
90-
.equ tcsls_last_rsp, 0x10 /* initialized by loader to 0 */
91-
.equ tcsls_panic_last_rsp, 0x18 /* initialized by loader to 0 */
92-
.equ tcsls_debug_panic_buf_ptr, 0x20 /* initialized by loader to 0 */
93-
.equ tcsls_user_rsp, 0x28
94-
.equ tcsls_user_retip, 0x30
95-
.equ tcsls_user_rbp, 0x38
96-
.equ tcsls_user_r12, 0x40
97-
.equ tcsls_user_r13, 0x48
98-
.equ tcsls_user_r14, 0x50
99-
.equ tcsls_user_r15, 0x58
100-
.equ tcsls_tls_ptr, 0x60
95+
.equ tcsls_user_fcw, 0x12
96+
.equ tcsls_user_mxcsr, 0x14
97+
.equ tcsls_last_rsp, 0x18 /* initialized by loader to 0 */
98+
.equ tcsls_panic_last_rsp, 0x20 /* initialized by loader to 0 */
99+
.equ tcsls_debug_panic_buf_ptr, 0x28 /* initialized by loader to 0 */
100+
.equ tcsls_user_rsp, 0x30
101+
.equ tcsls_user_retip, 0x38
102+
.equ tcsls_user_rbp, 0x40
103+
.equ tcsls_user_r12, 0x48
104+
.equ tcsls_user_r13, 0x50
105+
.equ tcsls_user_r14, 0x58
106+
.equ tcsls_user_r15, 0x60
101107
.equ tcsls_tcs_addr, 0x68
102108

103109
.macro load_tcsls_flag_secondary_bool reg:req comments:vararg
104110
.ifne tcsls_flag_secondary /* to convert to a bool, must be the first bit */
105111
.abort
106112
.endif
107113
mov $(1<<tcsls_flag_secondary),%e\reg
108-
and %gs:tcsls_flags,%\reg
114+
and %fs:tcsls_flags,%\reg
109115
.endm
110116

111117
/* We place the ELF entry point in a separate section so it can be removed by
@@ -157,21 +163,21 @@ elf_entry:
157163
.type sgx_entry,function
158164
sgx_entry:
159165
/* save user registers */
160-
mov %rcx,%gs:tcsls_user_retip
161-
mov %rsp,%gs:tcsls_user_rsp
162-
mov %rbp,%gs:tcsls_user_rbp
163-
mov %r12,%gs:tcsls_user_r12
164-
mov %r13,%gs:tcsls_user_r13
165-
mov %r14,%gs:tcsls_user_r14
166-
mov %r15,%gs:tcsls_user_r15
167-
mov %rbx,%gs:tcsls_tcs_addr
168-
stmxcsr %gs:tcsls_user_mxcsr
169-
fnstcw %gs:tcsls_user_fcw
166+
mov %rcx,%fs:tcsls_user_retip
167+
mov %rsp,%fs:tcsls_user_rsp
168+
mov %rbp,%fs:tcsls_user_rbp
169+
mov %r12,%fs:tcsls_user_r12
170+
mov %r13,%fs:tcsls_user_r13
171+
mov %r14,%fs:tcsls_user_r14
172+
mov %r15,%fs:tcsls_user_r15
173+
mov %rbx,%fs:tcsls_tcs_addr
174+
stmxcsr %fs:tcsls_user_mxcsr
175+
fnstcw %fs:tcsls_user_fcw
170176

171177
/* check for debug buffer pointer */
172178
testb $0xff,DEBUG(%rip)
173179
jz .Lskip_debug_init
174-
mov %r10,%gs:tcsls_debug_panic_buf_ptr
180+
mov %r10,%fs:tcsls_debug_panic_buf_ptr
175181
.Lskip_debug_init:
176182
/* reset cpu state */
177183
mov %rdx, %r10
@@ -181,20 +187,23 @@ sgx_entry:
181187
mov %r10, %rdx
182188

183189
/* check if returning from usercall */
184-
mov %gs:tcsls_last_rsp,%r11
190+
mov %fs:tcsls_last_rsp,%r11
185191
test %r11,%r11
186192
jnz .Lusercall_ret
187193
/* setup stack */
188-
mov %gs:tcsls_tos,%rsp /* initially, RSP is not set to the correct value */
194+
mov %fs:tcsls_tos,%rsp /* initially, RSP is not set to the correct value */
189195
/* here. This is fixed below under "adjust stack". */
190196
/* check for thread init */
191-
bts $tcsls_flag_init_once,%gs:tcsls_flags
197+
bts $tcsls_flag_init_once,%fs:tcsls_flags
192198
jc .Lskip_init
193199
/* adjust stack */
194200
lea IMAGE_BASE(%rip),%rax
195201
add %rax,%rsp
196-
mov %rsp,%gs:tcsls_tos
202+
mov %rsp,%fs:tcsls_tos
197203
entry_sanitize_final
204+
/* adjust thread pointer */
205+
lea IMAGE_BASE(%rip),%rax
206+
add %rax,%fs:0
198207
/* call tcs_init */
199208
/* store caller-saved registers in callee-saved registers */
200209
mov %rdi,%rbx
@@ -246,15 +255,15 @@ sgx_entry:
246255
pushq $0
247256
popfq
248257
/* restore user registers */
249-
mov %gs:tcsls_user_r12,%r12
250-
mov %gs:tcsls_user_r13,%r13
251-
mov %gs:tcsls_user_r14,%r14
252-
mov %gs:tcsls_user_r15,%r15
253-
mov %gs:tcsls_user_retip,%rbx
254-
mov %gs:tcsls_user_rsp,%rsp
255-
mov %gs:tcsls_user_rbp,%rbp
256-
fldcw %gs:tcsls_user_fcw
257-
ldmxcsr %gs:tcsls_user_mxcsr
258+
mov %fs:tcsls_user_r12,%r12
259+
mov %fs:tcsls_user_r13,%r13
260+
mov %fs:tcsls_user_r14,%r14
261+
mov %fs:tcsls_user_r15,%r15
262+
mov %fs:tcsls_user_retip,%rbx
263+
mov %fs:tcsls_user_rsp,%rsp
264+
mov %fs:tcsls_user_rbp,%rbp
265+
fldcw %fs:tcsls_user_fcw
266+
ldmxcsr %fs:tcsls_user_mxcsr
258267
/* exit enclave */
259268
mov $0x4,%eax /* EEXIT */
260269
enclu
@@ -288,7 +297,7 @@ usercall:
288297
sub $8, %rsp
289298
fstcw 4(%rsp)
290299
stmxcsr (%rsp)
291-
movq %rsp,%gs:tcsls_last_rsp
300+
movq %rsp,%fs:tcsls_last_rsp
292301
.Lusercall_noreturn:
293302
/* clear general purpose register state */
294303
/* RAX overwritten by ENCLU */
@@ -308,7 +317,7 @@ usercall:
308317
/* exit */
309318
jmp .Lsgx_exit
310319
.Lusercall_ret:
311-
movq $0,%gs:tcsls_last_rsp
320+
movq $0,%fs:tcsls_last_rsp
312321
/* restore callee-saved state, cf. "save" above */
313322
mov %r11,%rsp
314323
ldmxcsr (%rsp)
@@ -344,29 +353,15 @@ extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64
344353

345354
.global get_tcs_addr
346355
get_tcs_addr:
347-
mov %gs:tcsls_tcs_addr,%rax
348-
pop %r11
349-
lfence
350-
jmp *%r11
351-
352-
.global get_tls_ptr
353-
get_tls_ptr:
354-
mov %gs:tcsls_tls_ptr,%rax
355-
pop %r11
356-
lfence
357-
jmp *%r11
358-
359-
.global set_tls_ptr
360-
set_tls_ptr:
361-
mov %rdi,%gs:tcsls_tls_ptr
356+
mov %fs:tcsls_tcs_addr,%rax
362357
pop %r11
363358
lfence
364359
jmp *%r11
365360

366361
.global take_debug_panic_buf_ptr
367362
take_debug_panic_buf_ptr:
368363
xor %rax,%rax
369-
xchg %gs:tcsls_debug_panic_buf_ptr,%rax
364+
xchg %fs:tcsls_debug_panic_buf_ptr,%rax
370365
pop %r11
371366
lfence
372367
jmp *%r11

library/std/src/sys/sgx/abi/mod.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,11 @@ unsafe extern "C" fn tcs_init(secondary: bool) {
6262
#[no_mangle]
6363
extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> EntryReturn {
6464
// FIXME: how to support TLS in library mode?
65-
let tls = Box::new(tls::Tls::new());
66-
let tls_guard = unsafe { tls.activate() };
65+
let tls = unsafe { tls::Tls::init() };
6766

6867
if secondary {
6968
let join_notifier = super::thread::Thread::entry();
70-
drop(tls_guard);
69+
drop(tls);
7170
drop(join_notifier);
7271

7372
EntryReturn(0, 0)

library/std/src/sys/sgx/abi/tls.rs

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use super::mem;
2+
use crate::arch::asm;
3+
4+
extern "C" {
5+
static TLS_INIT_BASE: u64;
6+
static TLS_INIT_SIZE: usize;
7+
static TLS_OFFSET: usize;
8+
}
9+
10+
pub struct Tls {}
11+
12+
impl Tls {
13+
/// Initialize the thread local storage to a fresh state.
14+
///
15+
/// # Safety
16+
/// * may only be called once per thread
17+
/// * must be dropped before thread exit
18+
/// * must be called before any `#[thread_local]` variable is used
19+
pub unsafe fn init() -> Tls {
20+
// The thread pointer points to the end of the TLS section. It is stored
21+
// both in the `fs` segment base address (initialized by the loader) and
22+
// at the address it itself points to (initialized during TCS
23+
// initialization).
24+
let tp: *mut u8;
25+
unsafe {
26+
asm!("mov fs:0, {}", out(reg) tp, options(preserves_flags, readonly));
27+
}
28+
29+
// Initialize the TLS data.
30+
unsafe {
31+
let init_base = mem::rel_ptr_mut(TLS_INIT_BASE);
32+
// The first `TLS_INIT_SIZE` bytes of the TLS section hold non-trivial
33+
// data that needs to be copied from the initialization image.
34+
tp.sub(TLS_OFFSET).copy_from_nonoverlapping(init_base, TLS_INIT_SIZE);
35+
// All remaining bytes are initialized to zero.
36+
tp.sub(TLS_OFFSET).add(TLS_INIT_SIZE).write_bytes(0, TLS_OFFSET - TLS_INIT_SIZE);
37+
}
38+
39+
Tls {}
40+
}
41+
}
42+
43+
impl Drop for Tls {
44+
fn drop(&mut self) {
45+
unsafe {
46+
crate::sys::thread_local_dtor::run_dtors();
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)