]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/sgx/abi/usercalls/raw.rs
Don't default on std crate when manipulating browser history
[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 ptr::NonNull;
7
8 #[repr(C)]
9 struct UsercallReturn(u64, u64);
10
11 extern "C" {
12     fn usercall(nr: u64, p1: u64, p2: u64, _ignore: u64, p3: u64, p4: u64) -> UsercallReturn;
13 }
14
15 /// Perform the raw usercall operation as defined in the ABI calling convention.
16 ///
17 /// # Safety
18 /// The caller must ensure to pass parameters appropriate for the usercall `nr`
19 /// and to observe all requirements specified in the ABI.
20 ///
21 /// # Panics
22 /// Panics if `nr` is 0.
23 #[unstable(feature = "sgx_platform", issue = "56975")]
24 pub unsafe fn do_usercall(nr: u64, p1: u64, p2: u64, p3: u64, p4: u64) -> (u64, u64) {
25     if nr==0 { panic!("Invalid usercall number {}",nr) }
26     let UsercallReturn(a, b) = usercall(nr,p1,p2,0,p3,p4);
27     (a, b)
28 }
29
30 type Register = u64;
31
32 trait RegisterArgument {
33     fn from_register(Register) -> Self;
34     fn into_register(self) -> Register;
35 }
36
37 trait ReturnValue {
38     fn from_registers(call: &'static str, regs: (Register, Register)) -> Self;
39 }
40
41 macro_rules! define_usercalls {
42     // Using `$r:tt` because `$r:ty` doesn't match ! in `clobber_diverging`
43     ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:tt)*; )*) => {
44         /// Usercall numbers as per the ABI.
45         #[repr(u64)]
46         #[unstable(feature = "sgx_platform", issue = "56975")]
47         #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
48         #[allow(missing_docs, non_camel_case_types)]
49         #[non_exhaustive]
50         pub enum Usercalls {
51             #[doc(hidden)]
52             __enclave_usercalls_invalid = 0,
53             $($f,)*
54         }
55
56         $(enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) $(-> $r)*);)*
57     };
58 }
59
60 macro_rules! define_usercalls_asm {
61     ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:ty)*; )*) => {
62         macro_rules! usercalls_asm {
63             () => {
64                 concat!(
65                     ".equ usercall_nr_LAST, 0\n",
66                     $(
67                     ".equ usercall_nr_", stringify!($f), ", usercall_nr_LAST+1\n",
68                     ".equ usercall_nr_LAST, usercall_nr_", stringify!($f), "\n"
69                     ),*
70                 )
71             }
72         }
73     };
74 }
75
76 macro_rules! define_ra {
77     (< $i:ident > $t:ty) => {
78         impl<$i> RegisterArgument for $t {
79             fn from_register(a: Register) -> Self {
80                 a as _
81             }
82             fn into_register(self) -> Register {
83                 self as _
84             }
85         }
86     };
87     ($i:ty as $t:ty) => {
88         impl RegisterArgument for $t {
89             fn from_register(a: Register) -> Self {
90                 a as $i as _
91             }
92             fn into_register(self) -> Register {
93                 self as $i as _
94             }
95         }
96     };
97     ($t:ty) => {
98         impl RegisterArgument for $t {
99             fn from_register(a: Register) -> Self {
100                 a as _
101             }
102             fn into_register(self) -> Register {
103                 self as _
104             }
105         }
106     };
107 }
108
109 define_ra!(Register);
110 define_ra!(i64);
111 define_ra!(u32);
112 define_ra!(u32 as i32);
113 define_ra!(u16);
114 define_ra!(u16 as i16);
115 define_ra!(u8);
116 define_ra!(u8 as i8);
117 define_ra!(usize);
118 define_ra!(usize as isize);
119 define_ra!(<T> *const T);
120 define_ra!(<T> *mut T);
121
122 impl RegisterArgument for bool {
123     fn from_register(a: Register) -> bool {
124         if a != 0 {
125             true
126         } else {
127             false
128         }
129     }
130     fn into_register(self) -> Register {
131         self as _
132     }
133 }
134
135 impl<T: RegisterArgument> RegisterArgument for Option<NonNull<T>> {
136     fn from_register(a: Register) -> Option<NonNull<T>> {
137         NonNull::new(a as _)
138     }
139     fn into_register(self) -> Register {
140         self.map_or(0 as _, NonNull::as_ptr) as _
141     }
142 }
143
144 impl ReturnValue for ! {
145     fn from_registers(call: &'static str, _regs: (Register, Register)) -> Self {
146         panic!("Usercall {}: did not expect to be re-entered", call);
147     }
148 }
149
150 impl ReturnValue for () {
151     fn from_registers(call: &'static str, regs: (Register, Register)) -> Self {
152         assert_eq!(regs.0, 0, "Usercall {}: expected {} return value to be 0", call, "1st");
153         assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd");
154         ()
155     }
156 }
157
158 impl<T: RegisterArgument> ReturnValue for T {
159     fn from_registers(call: &'static str, regs: (Register, Register)) -> Self {
160         assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd");
161         T::from_register(regs.0)
162     }
163 }
164
165 impl<T: RegisterArgument, U: RegisterArgument> ReturnValue for (T, U) {
166     fn from_registers(_call: &'static str, regs: (Register, Register)) -> Self {
167         (
168             T::from_register(regs.0),
169             U::from_register(regs.1)
170         )
171     }
172 }
173
174 macro_rules! enclave_usercalls_internal_define_usercalls {
175     (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty,
176                      $n3:ident: $t3:ty, $n4:ident: $t4:ty) -> $r:ty) => (
177         /// This is the raw function definition, see the ABI documentation for
178         /// more information.
179         #[unstable(feature = "sgx_platform", issue = "56975")]
180         #[inline(always)]
181         pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3, $n4: $t4) -> $r {
182             ReturnValue::from_registers(stringify!($f), do_usercall(
183                 Usercalls::$f as Register,
184                 RegisterArgument::into_register($n1),
185                 RegisterArgument::into_register($n2),
186                 RegisterArgument::into_register($n3),
187                 RegisterArgument::into_register($n4),
188             ))
189         }
190     );
191     (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:ty) => (
192         /// This is the raw function definition, see the ABI documentation for
193         /// more information.
194         #[unstable(feature = "sgx_platform", issue = "56975")]
195         #[inline(always)]
196         pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3) -> $r {
197             ReturnValue::from_registers(stringify!($f), do_usercall(
198                 Usercalls::$f as Register,
199                 RegisterArgument::into_register($n1),
200                 RegisterArgument::into_register($n2),
201                 RegisterArgument::into_register($n3),
202                 0
203             ))
204         }
205     );
206     (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:ty) => (
207         /// This is the raw function definition, see the ABI documentation for
208         /// more information.
209         #[unstable(feature = "sgx_platform", issue = "56975")]
210         #[inline(always)]
211         pub unsafe fn $f($n1: $t1, $n2: $t2) -> $r {
212             ReturnValue::from_registers(stringify!($f), do_usercall(
213                 Usercalls::$f as Register,
214                 RegisterArgument::into_register($n1),
215                 RegisterArgument::into_register($n2),
216                 0,0
217             ))
218         }
219     );
220     (def fn $f:ident($n1:ident: $t1:ty) -> $r:ty) => (
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                 Usercalls::$f as Register,
228                 RegisterArgument::into_register($n1),
229                 0,0,0
230             ))
231         }
232     );
233     (def fn $f:ident() -> $r:ty) => (
234         /// This is the raw function definition, see the ABI documentation for
235         /// more information.
236         #[unstable(feature = "sgx_platform", issue = "56975")]
237         #[inline(always)]
238         pub unsafe fn $f() -> $r {
239             ReturnValue::from_registers(stringify!($f), do_usercall(
240                 Usercalls::$f as Register,
241                 0,0,0,0
242             ))
243         }
244     );
245     (def fn $f:ident($($n:ident: $t:ty),*)) => (
246         enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) -> ());
247     );
248 }
249
250 invoke_with_usercalls!(define_usercalls);
251 invoke_with_usercalls!(define_usercalls_asm);