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 panic!("Usercall {}: did not expect to be re-entered", call);
138 impl ReturnValue for () {
139 fn from_registers(call: &'static str, regs: (Register, Register)) -> Self {
140 assert_eq!(regs.0, 0, "Usercall {}: expected {} return value to be 0", call, "1st");
141 assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd");
146 impl<T: RegisterArgument> ReturnValue for T {
147 fn from_registers(call: &'static str, regs: (Register, Register)) -> Self {
148 assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd");
149 T::from_register(regs.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 NonZeroU64::new(Usercalls::$f as Register)
178 .expect("Usercall number must be non-zero"),
179 RegisterArgument::into_register($n1),
180 RegisterArgument::into_register($n2),
181 RegisterArgument::into_register($n3),
182 RegisterArgument::into_register($n4),
183 return_type_is_abort!($r)
187 (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:tt) => (
188 /// This is the raw function definition, see the ABI documentation for
189 /// more information.
190 #[unstable(feature = "sgx_platform", issue = "56975")]
192 pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3) -> $r {
193 ReturnValue::from_registers(stringify!($f), do_usercall(
194 NonZeroU64::new(Usercalls::$f as Register)
195 .expect("Usercall number must be non-zero"),
196 RegisterArgument::into_register($n1),
197 RegisterArgument::into_register($n2),
198 RegisterArgument::into_register($n3),
200 return_type_is_abort!($r)
204 (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:tt) => (
205 /// This is the raw function definition, see the ABI documentation for
206 /// more information.
207 #[unstable(feature = "sgx_platform", issue = "56975")]
209 pub unsafe fn $f($n1: $t1, $n2: $t2) -> $r {
210 ReturnValue::from_registers(stringify!($f), do_usercall(
211 NonZeroU64::new(Usercalls::$f as Register)
212 .expect("Usercall number must be non-zero"),
213 RegisterArgument::into_register($n1),
214 RegisterArgument::into_register($n2),
216 return_type_is_abort!($r)
220 (def fn $f:ident($n1:ident: $t1:ty) -> $r:tt) => (
221 /// This is the raw function definition, see the ABI documentation for
222 /// more information.
223 #[unstable(feature = "sgx_platform", issue = "56975")]
225 pub unsafe fn $f($n1: $t1) -> $r {
226 ReturnValue::from_registers(stringify!($f), do_usercall(
227 NonZeroU64::new(Usercalls::$f as Register)
228 .expect("Usercall number must be non-zero"),
229 RegisterArgument::into_register($n1),
231 return_type_is_abort!($r)
235 (def fn $f:ident() -> $r:tt) => (
236 /// This is the raw function definition, see the ABI documentation for
237 /// more information.
238 #[unstable(feature = "sgx_platform", issue = "56975")]
240 pub unsafe fn $f() -> $r {
241 ReturnValue::from_registers(stringify!($f), do_usercall(
242 NonZeroU64::new(Usercalls::$f as Register)
243 .expect("Usercall number must be non-zero"),
245 return_type_is_abort!($r)
249 (def fn $f:ident($($n:ident: $t:ty),*)) => (
250 enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) -> ());
254 invoke_with_usercalls!(define_usercalls);