3 #[unstable(feature = "sgx_platform", issue = "56975")]
4 pub use fortanix_sgx_abi::*;
6 use crate::ptr::NonNull;
7 use crate::num::NonZeroU64;
10 struct UsercallReturn(u64, u64);
13 fn usercall(nr: NonZeroU64, p1: u64, p2: u64, abort: u64, p3: u64, p4: u64) -> UsercallReturn;
16 /// Performs the raw usercall operation as defined in the ABI calling convention.
20 /// The caller must ensure to pass parameters appropriate for the usercall `nr`
21 /// and to observe all requirements specified in the ABI.
25 /// Panics if `nr` is `0`.
26 #[unstable(feature = "sgx_platform", issue = "56975")]
28 pub unsafe fn do_usercall(nr: NonZeroU64, p1: u64, p2: u64, p3: u64, p4: u64, abort: bool)
31 let UsercallReturn(a, b) = usercall(nr, p1, p2, abort as _, p3, p4);
37 trait RegisterArgument {
38 fn from_register(_: Register) -> Self;
39 fn into_register(self) -> Register;
43 fn from_registers(call: &'static str, regs: (Register, Register)) -> Self;
46 macro_rules! define_usercalls {
47 ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:tt)*; )*) => {
48 /// Usercall numbers as per the ABI.
50 #[unstable(feature = "sgx_platform", issue = "56975")]
51 #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
52 #[allow(missing_docs, non_camel_case_types)]
56 __enclave_usercalls_invalid = 0,
60 $(enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) $(-> $r)*);)*
64 macro_rules! define_ra {
65 (< $i:ident > $t:ty) => {
66 impl<$i> RegisterArgument for $t {
67 fn from_register(a: Register) -> Self {
70 fn into_register(self) -> Register {
76 impl RegisterArgument for $t {
77 fn from_register(a: Register) -> Self {
80 fn into_register(self) -> Register {
86 impl RegisterArgument for $t {
87 fn from_register(a: Register) -> Self {
90 fn into_register(self) -> Register {
100 define_ra!(u32 as i32);
102 define_ra!(u16 as i16);
104 define_ra!(u8 as i8);
106 define_ra!(usize as isize);
107 define_ra!(<T> *const T);
108 define_ra!(<T> *mut T);
110 impl RegisterArgument for bool {
111 fn from_register(a: Register) -> bool {
118 fn into_register(self) -> Register {
123 impl<T: RegisterArgument> RegisterArgument for Option<NonNull<T>> {
124 fn from_register(a: Register) -> Option<NonNull<T>> {
127 fn into_register(self) -> Register {
128 self.map_or(0 as _, NonNull::as_ptr) as _
132 impl ReturnValue for ! {
133 fn from_registers(call: &'static str, _regs: (Register, Register)) -> Self {
134 rtabort!("Usercall {}: did not expect to be re-entered", call);
138 impl ReturnValue for () {
139 fn from_registers(call: &'static str, usercall_retval: (Register, Register)) -> Self {
140 rtassert!(usercall_retval.0 == 0);
141 rtassert!(usercall_retval.1 == 0);
146 impl<T: RegisterArgument> ReturnValue for T {
147 fn from_registers(call: &'static str, usercall_retval: (Register, Register)) -> Self {
148 rtassert!(usercall_retval.1 == 0);
149 T::from_register(usercall_retval.0)
153 impl<T: RegisterArgument, U: RegisterArgument> ReturnValue for (T, U) {
154 fn from_registers(_call: &'static str, regs: (Register, Register)) -> Self {
156 T::from_register(regs.0),
157 U::from_register(regs.1)
162 macro_rules! return_type_is_abort {
164 ($r:ty) => { false };
167 // In this macro: using `$r:tt` because `$r:ty` doesn't match ! in `return_type_is_abort`
168 macro_rules! enclave_usercalls_internal_define_usercalls {
169 (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty,
170 $n3:ident: $t3:ty, $n4:ident: $t4:ty) -> $r:tt) => (
171 /// This is the raw function definition, see the ABI documentation for
172 /// more information.
173 #[unstable(feature = "sgx_platform", issue = "56975")]
175 pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3, $n4: $t4) -> $r {
176 ReturnValue::from_registers(stringify!($f), do_usercall(
177 rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
178 RegisterArgument::into_register($n1),
179 RegisterArgument::into_register($n2),
180 RegisterArgument::into_register($n3),
181 RegisterArgument::into_register($n4),
182 return_type_is_abort!($r)
186 (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:tt) => (
187 /// This is the raw function definition, see the ABI documentation for
188 /// more information.
189 #[unstable(feature = "sgx_platform", issue = "56975")]
191 pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3) -> $r {
192 ReturnValue::from_registers(stringify!($f), do_usercall(
193 rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
194 RegisterArgument::into_register($n1),
195 RegisterArgument::into_register($n2),
196 RegisterArgument::into_register($n3),
198 return_type_is_abort!($r)
202 (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:tt) => (
203 /// This is the raw function definition, see the ABI documentation for
204 /// more information.
205 #[unstable(feature = "sgx_platform", issue = "56975")]
207 pub unsafe fn $f($n1: $t1, $n2: $t2) -> $r {
208 ReturnValue::from_registers(stringify!($f), do_usercall(
209 rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
210 RegisterArgument::into_register($n1),
211 RegisterArgument::into_register($n2),
213 return_type_is_abort!($r)
217 (def fn $f:ident($n1:ident: $t1:ty) -> $r:tt) => (
218 /// This is the raw function definition, see the ABI documentation for
219 /// more information.
220 #[unstable(feature = "sgx_platform", issue = "56975")]
222 pub unsafe fn $f($n1: $t1) -> $r {
223 ReturnValue::from_registers(stringify!($f), do_usercall(
224 rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
225 RegisterArgument::into_register($n1),
227 return_type_is_abort!($r)
231 (def fn $f:ident() -> $r:tt) => (
232 /// This is the raw function definition, see the ABI documentation for
233 /// more information.
234 #[unstable(feature = "sgx_platform", issue = "56975")]
236 pub unsafe fn $f() -> $r {
237 ReturnValue::from_registers(stringify!($f), do_usercall(
238 rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
240 return_type_is_abort!($r)
244 (def fn $f:ident($($n:ident: $t:ty),*)) => (
245 enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) -> ());
249 invoke_with_usercalls!(define_usercalls);