]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/sgx/abi/usercalls/raw.rs
ad0b6d7b3d8ecb65e5f95476a5042b7bf7ba500a
[rust.git] / src / libstd / sys / sgx / abi / usercalls / raw.rs
1 #![allow(unused)]
2
3 #[unstable(feature = "sgx_platform", issue = "56975")]
4 pub use fortanix_sgx_abi::*;
5
6 use crate::ptr::NonNull;
7 use crate::num::NonZeroU64;
8
9 #[repr(C)]
10 struct UsercallReturn(u64, u64);
11
12 extern "C" {
13     fn usercall(nr: NonZeroU64, p1: u64, p2: u64, abort: u64, p3: u64, p4: u64) -> UsercallReturn;
14 }
15
16 /// Performs the raw usercall operation as defined in the ABI calling convention.
17 ///
18 /// # Safety
19 ///
20 /// The caller must ensure to pass parameters appropriate for the usercall `nr`
21 /// and to observe all requirements specified in the ABI.
22 ///
23 /// # Panics
24 ///
25 /// Panics if `nr` is `0`.
26 #[unstable(feature = "sgx_platform", issue = "56975")]
27 #[inline]
28 pub unsafe fn do_usercall(nr: NonZeroU64, p1: u64, p2: u64, p3: u64, p4: u64, abort: bool)
29     -> (u64, u64)
30 {
31     let UsercallReturn(a, b) = usercall(nr, p1, p2, abort as _, p3, p4);
32     (a, b)
33 }
34
35 type Register = u64;
36
37 trait RegisterArgument {
38     fn from_register(_: Register) -> Self;
39     fn into_register(self) -> Register;
40 }
41
42 trait ReturnValue {
43     fn from_registers(call: &'static str, regs: (Register, Register)) -> Self;
44 }
45
46 macro_rules! define_usercalls {
47     ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:tt)*; )*) => {
48         /// Usercall numbers as per the ABI.
49         #[repr(u64)]
50         #[unstable(feature = "sgx_platform", issue = "56975")]
51         #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
52         #[allow(missing_docs, non_camel_case_types)]
53         #[non_exhaustive]
54         pub enum Usercalls {
55             #[doc(hidden)]
56             __enclave_usercalls_invalid = 0,
57             $($f,)*
58         }
59
60         $(enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) $(-> $r)*);)*
61     };
62 }
63
64 macro_rules! define_ra {
65     (< $i:ident > $t:ty) => {
66         impl<$i> RegisterArgument for $t {
67             fn from_register(a: Register) -> Self {
68                 a as _
69             }
70             fn into_register(self) -> Register {
71                 self as _
72             }
73         }
74     };
75     ($i:ty as $t:ty) => {
76         impl RegisterArgument for $t {
77             fn from_register(a: Register) -> Self {
78                 a as $i as _
79             }
80             fn into_register(self) -> Register {
81                 self as $i as _
82             }
83         }
84     };
85     ($t:ty) => {
86         impl RegisterArgument for $t {
87             fn from_register(a: Register) -> Self {
88                 a as _
89             }
90             fn into_register(self) -> Register {
91                 self as _
92             }
93         }
94     };
95 }
96
97 define_ra!(Register);
98 define_ra!(i64);
99 define_ra!(u32);
100 define_ra!(u32 as i32);
101 define_ra!(u16);
102 define_ra!(u16 as i16);
103 define_ra!(u8);
104 define_ra!(u8 as i8);
105 define_ra!(usize);
106 define_ra!(usize as isize);
107 define_ra!(<T> *const T);
108 define_ra!(<T> *mut T);
109
110 impl RegisterArgument for bool {
111     fn from_register(a: Register) -> bool {
112         if a != 0 {
113             true
114         } else {
115             false
116         }
117     }
118     fn into_register(self) -> Register {
119         self as _
120     }
121 }
122
123 impl<T: RegisterArgument> RegisterArgument for Option<NonNull<T>> {
124     fn from_register(a: Register) -> Option<NonNull<T>> {
125         NonNull::new(a as _)
126     }
127     fn into_register(self) -> Register {
128         self.map_or(0 as _, NonNull::as_ptr) as _
129     }
130 }
131
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);
135     }
136 }
137
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");
142         ()
143     }
144 }
145
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)
150     }
151 }
152
153 impl<T: RegisterArgument, U: RegisterArgument> ReturnValue for (T, U) {
154     fn from_registers(_call: &'static str, regs: (Register, Register)) -> Self {
155         (
156             T::from_register(regs.0),
157             U::from_register(regs.1)
158         )
159     }
160 }
161
162 macro_rules! return_type_is_abort {
163     (!) => { true };
164     ($r:ty) => { false };
165 }
166
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")]
174         #[inline(always)]
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)
184             ))
185         }
186     );
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")]
191         #[inline(always)]
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),
199                 0,
200                 return_type_is_abort!($r)
201             ))
202         }
203     );
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")]
208         #[inline(always)]
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),
215                 0,0,
216                 return_type_is_abort!($r)
217             ))
218         }
219     );
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")]
224         #[inline(always)]
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),
230                 0,0,0,
231                 return_type_is_abort!($r)
232             ))
233         }
234     );
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")]
239         #[inline(always)]
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"),
244                 0,0,0,0,
245                 return_type_is_abort!($r)
246             ))
247         }
248     );
249     (def fn $f:ident($($n:ident: $t:ty),*)) => (
250         enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) -> ());
251     );
252 }
253
254 invoke_with_usercalls!(define_usercalls);