std/sys/pal/sgx/abi/usercalls/
raw.rs1#![allow(unused)]
2
3#[unstable(feature = "sgx_platform", issue = "56975")]
4pub use fortanix_sgx_abi::*;
5
6use crate::num::NonZero;
7use crate::ptr::NonNull;
8
9#[repr(C)]
10struct UsercallReturn(u64, u64);
11
12unsafe extern "C" {
13 fn usercall(nr: NonZero<u64>, p1: u64, p2: u64, abort: u64, p3: u64, p4: u64)
14 -> UsercallReturn;
15}
16
17#[unstable(feature = "sgx_platform", issue = "56975")]
28#[inline]
29pub unsafe fn do_usercall(
30 nr: NonZero<u64>,
31 p1: u64,
32 p2: u64,
33 p3: u64,
34 p4: u64,
35 abort: bool,
36) -> (u64, u64) {
37 let UsercallReturn(a, b) = unsafe { usercall(nr, p1, p2, abort as _, p3, p4) };
38 (a, b)
39}
40
41#[unstable(feature = "sgx_platform", issue = "56975")]
43pub type Register = u64;
44
45#[unstable(feature = "sgx_platform", issue = "56975")]
47pub trait RegisterArgument {
48 fn from_register(_: Register) -> Self;
50 fn into_register(self) -> Register;
52}
53
54#[unstable(feature = "sgx_platform", issue = "56975")]
56pub trait ReturnValue {
57 fn from_registers(call: &'static str, regs: (Register, Register)) -> Self;
59}
60
61macro_rules! define_usercalls {
62 ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:tt)*; )*) => {
63 #[repr(u64)]
65 #[unstable(feature = "sgx_platform", issue = "56975")]
66 #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
67 #[allow(missing_docs, non_camel_case_types)]
68 #[non_exhaustive]
69 pub enum Usercalls {
70 #[doc(hidden)]
71 __enclave_usercalls_invalid = 0,
72 $($f,)*
73 }
74
75 $(enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) $(-> $r)*);)*
76 };
77}
78
79macro_rules! define_ra {
80 (< $i:ident > $t:ty) => {
81 #[unstable(feature = "sgx_platform", issue = "56975")]
82 impl<$i> RegisterArgument for $t {
83 fn from_register(a: Register) -> Self {
84 a as _
85 }
86 fn into_register(self) -> Register {
87 self as _
88 }
89 }
90 };
91 ($i:ty as $t:ty) => {
92 #[unstable(feature = "sgx_platform", issue = "56975")]
93 impl RegisterArgument for $t {
94 fn from_register(a: Register) -> Self {
95 a as $i as _
96 }
97 fn into_register(self) -> Register {
98 self as $i as _
99 }
100 }
101 };
102 ($t:ty) => {
103 #[unstable(feature = "sgx_platform", issue = "56975")]
104 impl RegisterArgument for $t {
105 fn from_register(a: Register) -> Self {
106 a as _
107 }
108 fn into_register(self) -> Register {
109 self as _
110 }
111 }
112 };
113}
114
115define_ra!(Register);
116define_ra!(i64);
117define_ra!(u32);
118define_ra!(u32 as i32);
119define_ra!(u16);
120define_ra!(u16 as i16);
121define_ra!(u8);
122define_ra!(u8 as i8);
123define_ra!(usize);
124define_ra!(usize as isize);
125define_ra!(<T> *const T);
126define_ra!(<T> *mut T);
127
128#[unstable(feature = "sgx_platform", issue = "56975")]
129impl RegisterArgument for bool {
130 fn from_register(a: Register) -> bool {
131 if a != 0 { true } else { false }
132 }
133 fn into_register(self) -> Register {
134 self as _
135 }
136}
137
138#[unstable(feature = "sgx_platform", issue = "56975")]
139impl<T: RegisterArgument> RegisterArgument for Option<NonNull<T>> {
140 fn from_register(a: Register) -> Option<NonNull<T>> {
141 NonNull::new(a as _)
142 }
143 fn into_register(self) -> Register {
144 self.map_or(0 as _, NonNull::as_ptr) as _
145 }
146}
147
148#[unstable(feature = "sgx_platform", issue = "56975")]
149impl ReturnValue for ! {
150 fn from_registers(call: &'static str, _regs: (Register, Register)) -> Self {
151 rtabort!("Usercall {call}: did not expect to be re-entered");
152 }
153}
154
155#[unstable(feature = "sgx_platform", issue = "56975")]
156impl ReturnValue for () {
157 fn from_registers(call: &'static str, usercall_retval: (Register, Register)) -> Self {
158 rtassert!(usercall_retval.0 == 0);
159 rtassert!(usercall_retval.1 == 0);
160 ()
161 }
162}
163
164#[unstable(feature = "sgx_platform", issue = "56975")]
165impl<T: RegisterArgument> ReturnValue for T {
166 fn from_registers(call: &'static str, usercall_retval: (Register, Register)) -> Self {
167 rtassert!(usercall_retval.1 == 0);
168 T::from_register(usercall_retval.0)
169 }
170}
171
172#[unstable(feature = "sgx_platform", issue = "56975")]
173impl<T: RegisterArgument, U: RegisterArgument> ReturnValue for (T, U) {
174 fn from_registers(_call: &'static str, regs: (Register, Register)) -> Self {
175 (T::from_register(regs.0), U::from_register(regs.1))
176 }
177}
178
179macro_rules! return_type_is_abort {
180 (!) => {
181 true
182 };
183 ($r:ty) => {
184 false
185 };
186}
187
188macro_rules! enclave_usercalls_internal_define_usercalls {
190 (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty,
191 $n3:ident: $t3:ty, $n4:ident: $t4:ty) -> $r:tt) => (
192 #[unstable(feature = "sgx_platform", issue = "56975")]
195 #[inline(always)]
196 pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3, $n4: $t4) -> $r {
197 ReturnValue::from_registers(stringify!($f), unsafe { do_usercall(
198 rtunwrap!(Some, NonZero::new(Usercalls::$f as Register)),
199 RegisterArgument::into_register($n1),
200 RegisterArgument::into_register($n2),
201 RegisterArgument::into_register($n3),
202 RegisterArgument::into_register($n4),
203 return_type_is_abort!($r)
204 ) })
205 }
206 );
207 (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:tt) => (
208 #[unstable(feature = "sgx_platform", issue = "56975")]
211 #[inline(always)]
212 pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3) -> $r {
213 ReturnValue::from_registers(stringify!($f), unsafe { do_usercall(
214 rtunwrap!(Some, NonZero::new(Usercalls::$f as Register)),
215 RegisterArgument::into_register($n1),
216 RegisterArgument::into_register($n2),
217 RegisterArgument::into_register($n3),
218 0,
219 return_type_is_abort!($r)
220 ) })
221 }
222 );
223 (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:tt) => (
224 #[unstable(feature = "sgx_platform", issue = "56975")]
227 #[inline(always)]
228 pub unsafe fn $f($n1: $t1, $n2: $t2) -> $r {
229 ReturnValue::from_registers(stringify!($f), unsafe { do_usercall(
230 rtunwrap!(Some, NonZero::new(Usercalls::$f as Register)),
231 RegisterArgument::into_register($n1),
232 RegisterArgument::into_register($n2),
233 0,0,
234 return_type_is_abort!($r)
235 ) })
236 }
237 );
238 (def fn $f:ident($n1:ident: $t1:ty) -> $r:tt) => (
239 #[unstable(feature = "sgx_platform", issue = "56975")]
242 #[inline(always)]
243 pub unsafe fn $f($n1: $t1) -> $r {
244 ReturnValue::from_registers(stringify!($f), unsafe { do_usercall(
245 rtunwrap!(Some, NonZero::new(Usercalls::$f as Register)),
246 RegisterArgument::into_register($n1),
247 0,0,0,
248 return_type_is_abort!($r)
249 ) })
250 }
251 );
252 (def fn $f:ident() -> $r:tt) => (
253 #[unstable(feature = "sgx_platform", issue = "56975")]
256 #[inline(always)]
257 pub unsafe fn $f() -> $r {
258 ReturnValue::from_registers(stringify!($f), unsafe { do_usercall(
259 rtunwrap!(Some, NonZero::new(Usercalls::$f as Register)),
260 0,0,0,0,
261 return_type_is_abort!($r)
262 ) })
263 }
264 );
265 (def fn $f:ident($($n:ident: $t:ty),*)) => (
266 enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) -> ());
267 );
268}
269
270invoke_with_usercalls!(define_usercalls);