]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/sgx/abi/usercalls/raw.rs
SGX target: convert a bunch of panics to aborts
[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         rtabort!("Usercall {}: did not expect to be re-entered", call);
135     }
136 }
137
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);
142         ()
143     }
144 }
145
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)
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                 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)
183             ))
184         }
185     );
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")]
190         #[inline(always)]
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),
197                 0,
198                 return_type_is_abort!($r)
199             ))
200         }
201     );
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")]
206         #[inline(always)]
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),
212                 0,0,
213                 return_type_is_abort!($r)
214             ))
215         }
216     );
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")]
221         #[inline(always)]
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),
226                 0,0,0,
227                 return_type_is_abort!($r)
228             ))
229         }
230     );
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")]
235         #[inline(always)]
236         pub unsafe fn $f() -> $r {
237             ReturnValue::from_registers(stringify!($f), do_usercall(
238                 rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)),
239                 0,0,0,0,
240                 return_type_is_abort!($r)
241             ))
242         }
243     );
244     (def fn $f:ident($($n:ident: $t:ty),*)) => (
245         enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) -> ());
246     );
247 }
248
249 invoke_with_usercalls!(define_usercalls);