diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 63cf6b62145..e57cb2ce5fd 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -341,9 +341,6 @@ extern crate backtrace_sys; #[cfg(test)] extern crate std as realstd; #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] -#[macro_use] -#[allow(unused_imports)] // FIXME: without `#[macro_use]`, get error: “cannot - // determine resolution for the macro `usercalls_asm`” extern crate fortanix_sgx_abi; // The standard macros that are not built-in to the compiler. diff --git a/src/libstd/sys/sgx/abi/entry.S b/src/libstd/sys/sgx/abi/entry.S index 9b46c2180d9..c03e3869aa3 100644 --- a/src/libstd/sys/sgx/abi/entry.S +++ b/src/libstd/sys/sgx/abi/entry.S @@ -69,10 +69,6 @@ IMAGE_BASE: .asciz "Re-entered aborted enclave!" .Lreentry_panic_msg_end: -.Lusercall_panic_msg: - .asciz "Invalid usercall#!" -.Lusercall_panic_msg_end: - .org .Lxsave_clear+512 .Lxsave_header: .int 0, 0 /* XSTATE_BV */ @@ -219,13 +215,21 @@ sgx_entry: orq $8,%rsp jmp panic_msg -.Lusercall_panic: - lea .Lusercall_panic_msg(%rip),%rdi - mov $.Lusercall_panic_msg_end-.Lusercall_panic_msg,%esi - orq $8,%rsp - jmp panic_msg - -.macro push_callee_saved_registers +/* This *MUST* be called with 6 parameters, otherwise register information */ +/* might leak! */ +.global usercall +usercall: + test %rcx,%rcx /* check `abort` function argument */ + jnz .Lusercall_abort /* abort is set, jump to abort code (unlikely forward conditional) */ + jmp .Lusercall_save_state /* non-aborting usercall */ +.Lusercall_abort: +/* set aborted bit */ + movb $1,.Laborted(%rip) +/* save registers in DEBUG mode, so that debugger can reconstruct the stack */ + testb $0xff,DEBUG(%rip) + jz .Lusercall_noreturn +.Lusercall_save_state: +/* save callee-saved state */ push %r15 push %r14 push %r13 @@ -235,33 +239,8 @@ sgx_entry: sub $8, %rsp fstcw 4(%rsp) stmxcsr (%rsp) -.endm - -.global usercall_exit -usercall_exit: -/* save registers in DEBUG mode, so that debugger can reconstruct the stack */ - testb $0xff,DEBUG(%rip) - jz .Lskip_save_registers - push_callee_saved_registers - movq %rsp,%gs:tcsls_panic_last_rsp -.Lskip_save_registers: -/* set aborted bit */ - movb $1,.Laborted(%rip) -/* call usercall exit(true) */ - /* NOP: mov %rsi,%rsi */ /* RSI = usercall() argument: panic */ - xor %rdx,%rdx /* RDX cleared */ - movq $usercall_nr_exit,%rdi /* RDI = usercall exit */ - jmp .Lexit - -/* This *MUST* be called with 6 parameters, otherwise register information */ -/* might leak! */ -.global usercall -usercall: - test %rdi,%rdi - jle .Lusercall_panic -/* save callee-saved state */ - push_callee_saved_registers movq %rsp,%gs:tcsls_last_rsp +.Lusercall_noreturn: /* clear general purpose register state */ /* RAX overwritten by ENCLU */ /* RBX set by sgx_exit */ @@ -281,7 +260,7 @@ usercall: jmp .Lsgx_exit .Lusercall_ret: movq $0,%gs:tcsls_last_rsp -/* restore callee-saved state, cf. push_callee_saved_registers */ +/* restore callee-saved state, cf. "save" above */ mov %r11,%rsp ldmxcsr (%rsp) fldcw 4(%rsp) diff --git a/src/libstd/sys/sgx/abi/mod.rs b/src/libstd/sys/sgx/abi/mod.rs index 5ef069aa81c..509a1990d97 100644 --- a/src/libstd/sys/sgx/abi/mod.rs +++ b/src/libstd/sys/sgx/abi/mod.rs @@ -12,7 +12,7 @@ pub mod tls; #[macro_use] pub mod usercalls; -global_asm!(concat!(usercalls_asm!(), include_str!("entry.S"))); +global_asm!(include_str!("entry.S")); #[no_mangle] unsafe extern "C" fn tcs_init(secondary: bool) { diff --git a/src/libstd/sys/sgx/abi/panic.rs b/src/libstd/sys/sgx/abi/panic.rs index d23fa9a9ec6..b2afacc70b8 100644 --- a/src/libstd/sys/sgx/abi/panic.rs +++ b/src/libstd/sys/sgx/abi/panic.rs @@ -1,4 +1,4 @@ -use super::usercalls::alloc::UserRef; +use super::usercalls::{alloc::UserRef, self}; use cmp; use io::{self, Write}; use mem; @@ -52,7 +52,5 @@ impl Write for SgxPanicOutput { #[no_mangle] pub extern "C" fn panic_msg(msg: &str) -> ! { let _ = SgxPanicOutput::new().map(|mut out| out.write(msg.as_bytes())); - unsafe { usercall_exit(true); } + usercalls::exit(true) } - -extern "C" { pub fn usercall_exit(panic: bool) -> !; } diff --git a/src/libstd/sys/sgx/abi/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs index bae044b906b..511d6e9e927 100644 --- a/src/libstd/sys/sgx/abi/usercalls/mod.rs +++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs @@ -120,7 +120,7 @@ pub unsafe fn launch_thread() -> IoResult<()> { /// Usercall `exit`. See the ABI documentation for more information. #[unstable(feature = "sgx_platform", issue = "56975")] pub fn exit(panic: bool) -> ! { - unsafe { super::panic::usercall_exit(panic) } + unsafe { raw::exit(panic) } } /// Usercall `wait`. See the ABI documentation for more information. diff --git a/src/libstd/sys/sgx/abi/usercalls/raw.rs b/src/libstd/sys/sgx/abi/usercalls/raw.rs index 004cf57602b..447f20584f8 100644 --- a/src/libstd/sys/sgx/abi/usercalls/raw.rs +++ b/src/libstd/sys/sgx/abi/usercalls/raw.rs @@ -4,12 +4,13 @@ pub use fortanix_sgx_abi::*; use ptr::NonNull; +use num::NonZeroU64; #[repr(C)] struct UsercallReturn(u64, u64); extern "C" { - fn usercall(nr: u64, p1: u64, p2: u64, _ignore: u64, p3: u64, p4: u64) -> UsercallReturn; + fn usercall(nr: NonZeroU64, p1: u64, p2: u64, abort: u64, p3: u64, p4: u64) -> UsercallReturn; } /// Performs the raw usercall operation as defined in the ABI calling convention. @@ -23,9 +24,11 @@ extern "C" { /// /// Panics if `nr` is `0`. #[unstable(feature = "sgx_platform", issue = "56975")] -pub unsafe fn do_usercall(nr: u64, p1: u64, p2: u64, p3: u64, p4: u64) -> (u64, u64) { - if nr==0 { panic!("Invalid usercall number {}",nr) } - let UsercallReturn(a, b) = usercall(nr,p1,p2,0,p3,p4); +#[inline] +pub unsafe fn do_usercall(nr: NonZeroU64, p1: u64, p2: u64, p3: u64, p4: u64, abort: bool) + -> (u64, u64) +{ + let UsercallReturn(a, b) = usercall(nr, p1, p2, abort as _, p3, p4); (a, b) } @@ -41,7 +44,6 @@ trait ReturnValue { } macro_rules! define_usercalls { - // Using `$r:tt` because `$r:ty` doesn't match ! in `clobber_diverging` ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:tt)*; )*) => { /// Usercall numbers as per the ABI. #[repr(u64)] @@ -59,22 +61,6 @@ macro_rules! define_usercalls { }; } -macro_rules! define_usercalls_asm { - ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:ty)*; )*) => { - macro_rules! usercalls_asm { - () => { - concat!( - ".equ usercall_nr_LAST, 0\n", - $( - ".equ usercall_nr_", stringify!($f), ", usercall_nr_LAST+1\n", - ".equ usercall_nr_LAST, usercall_nr_", stringify!($f), "\n" - ),* - ) - } - } - }; -} - macro_rules! define_ra { (< $i:ident > $t:ty) => { impl<$i> RegisterArgument for $t { @@ -173,74 +159,90 @@ impl ReturnValue for (T, U) { } } +macro_rules! return_type_is_abort { + (!) => { true }; + ($r:ty) => { false }; +} + +// In this macro: using `$r:tt` because `$r:ty` doesn't match ! in `return_type_is_abort` macro_rules! enclave_usercalls_internal_define_usercalls { (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, - $n3:ident: $t3:ty, $n4:ident: $t4:ty) -> $r:ty) => ( + $n3:ident: $t3:ty, $n4:ident: $t4:ty) -> $r:tt) => ( /// This is the raw function definition, see the ABI documentation for /// more information. #[unstable(feature = "sgx_platform", issue = "56975")] #[inline(always)] pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3, $n4: $t4) -> $r { ReturnValue::from_registers(stringify!($f), do_usercall( - Usercalls::$f as Register, + NonZeroU64::new(Usercalls::$f as Register) + .expect("Usercall number must be non-zero"), RegisterArgument::into_register($n1), RegisterArgument::into_register($n2), RegisterArgument::into_register($n3), RegisterArgument::into_register($n4), + return_type_is_abort!($r) )) } ); - (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:ty) => ( + (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:tt) => ( /// This is the raw function definition, see the ABI documentation for /// more information. #[unstable(feature = "sgx_platform", issue = "56975")] #[inline(always)] pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3) -> $r { ReturnValue::from_registers(stringify!($f), do_usercall( - Usercalls::$f as Register, + NonZeroU64::new(Usercalls::$f as Register) + .expect("Usercall number must be non-zero"), RegisterArgument::into_register($n1), RegisterArgument::into_register($n2), RegisterArgument::into_register($n3), - 0 + 0, + return_type_is_abort!($r) )) } ); - (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:ty) => ( + (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:tt) => ( /// This is the raw function definition, see the ABI documentation for /// more information. #[unstable(feature = "sgx_platform", issue = "56975")] #[inline(always)] pub unsafe fn $f($n1: $t1, $n2: $t2) -> $r { ReturnValue::from_registers(stringify!($f), do_usercall( - Usercalls::$f as Register, + NonZeroU64::new(Usercalls::$f as Register) + .expect("Usercall number must be non-zero"), RegisterArgument::into_register($n1), RegisterArgument::into_register($n2), - 0,0 + 0,0, + return_type_is_abort!($r) )) } ); - (def fn $f:ident($n1:ident: $t1:ty) -> $r:ty) => ( + (def fn $f:ident($n1:ident: $t1:ty) -> $r:tt) => ( /// This is the raw function definition, see the ABI documentation for /// more information. #[unstable(feature = "sgx_platform", issue = "56975")] #[inline(always)] pub unsafe fn $f($n1: $t1) -> $r { ReturnValue::from_registers(stringify!($f), do_usercall( - Usercalls::$f as Register, + NonZeroU64::new(Usercalls::$f as Register) + .expect("Usercall number must be non-zero"), RegisterArgument::into_register($n1), - 0,0,0 + 0,0,0, + return_type_is_abort!($r) )) } ); - (def fn $f:ident() -> $r:ty) => ( + (def fn $f:ident() -> $r:tt) => ( /// This is the raw function definition, see the ABI documentation for /// more information. #[unstable(feature = "sgx_platform", issue = "56975")] #[inline(always)] pub unsafe fn $f() -> $r { ReturnValue::from_registers(stringify!($f), do_usercall( - Usercalls::$f as Register, - 0,0,0,0 + NonZeroU64::new(Usercalls::$f as Register) + .expect("Usercall number must be non-zero"), + 0,0,0,0, + return_type_is_abort!($r) )) } ); @@ -250,4 +252,3 @@ macro_rules! enclave_usercalls_internal_define_usercalls { } invoke_with_usercalls!(define_usercalls); -invoke_with_usercalls!(define_usercalls_asm); diff --git a/src/libstd/sys/sgx/mod.rs b/src/libstd/sys/sgx/mod.rs index f2593c35bed..4225ecbb206 100644 --- a/src/libstd/sys/sgx/mod.rs +++ b/src/libstd/sys/sgx/mod.rs @@ -125,7 +125,7 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize { } pub unsafe fn abort_internal() -> ! { - abi::panic::usercall_exit(true) + abi::usercalls::exit(true) } pub fn hashmap_random_keys() -> (u64, u64) {