3 #[unstable(feature = "sgx_platform", issue = "56975")]
4 pub use fortanix_sgx_abi::*;
9 struct UsercallReturn(u64, u64);
12 fn usercall(nr: u64, p1: u64, p2: u64, _ignore: u64, p3: u64, p4: u64) -> UsercallReturn;
15 /// Perform the raw usercall operation as defined in the ABI calling convention.
18 /// The caller must ensure to pass parameters appropriate for the usercall `nr`
19 /// and to observe all requirements specified in the ABI.
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);
32 trait RegisterArgument {
33 fn from_register(Register) -> Self;
34 fn into_register(self) -> Register;
38 fn from_registers(call: &'static str, regs: (Register, Register)) -> Self;
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.
46 #[unstable(feature = "sgx_platform", issue = "56975")]
47 #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)]
48 #[allow(missing_docs, non_camel_case_types)]
52 __enclave_usercalls_invalid = 0,
56 $(enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) $(-> $r)*);)*
60 macro_rules! define_usercalls_asm {
61 ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:ty)*; )*) => {
62 macro_rules! usercalls_asm {
65 ".equ usercall_nr_LAST, 0\n",
67 ".equ usercall_nr_", stringify!($f), ", usercall_nr_LAST+1\n",
68 ".equ usercall_nr_LAST, usercall_nr_", stringify!($f), "\n"
76 macro_rules! define_ra {
77 (< $i:ident > $t:ty) => {
78 impl<$i> RegisterArgument for $t {
79 fn from_register(a: Register) -> Self {
82 fn into_register(self) -> Register {
88 impl RegisterArgument for $t {
89 fn from_register(a: Register) -> Self {
92 fn into_register(self) -> Register {
98 impl RegisterArgument for $t {
99 fn from_register(a: Register) -> Self {
102 fn into_register(self) -> Register {
109 define_ra!(Register);
112 define_ra!(u32 as i32);
114 define_ra!(u16 as i16);
116 define_ra!(u8 as i8);
118 define_ra!(usize as isize);
119 define_ra!(<T> *const T);
120 define_ra!(<T> *mut T);
122 impl RegisterArgument for bool {
123 fn from_register(a: Register) -> bool {
130 fn into_register(self) -> Register {
135 impl<T: RegisterArgument> RegisterArgument for Option<NonNull<T>> {
136 fn from_register(a: Register) -> Option<NonNull<T>> {
139 fn into_register(self) -> Register {
140 self.map_or(0 as _, NonNull::as_ptr) as _
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);
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");
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)
165 impl<T: RegisterArgument, U: RegisterArgument> ReturnValue for (T, U) {
166 fn from_registers(_call: &'static str, regs: (Register, Register)) -> Self {
168 T::from_register(regs.0),
169 U::from_register(regs.1)
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")]
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),
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")]
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),
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")]
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),
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")]
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),
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")]
238 pub unsafe fn $f() -> $r {
239 ReturnValue::from_registers(stringify!($f), do_usercall(
240 Usercalls::$f as Register,
245 (def fn $f:ident($($n:ident: $t:ty),*)) => (
246 enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) -> ());
250 invoke_with_usercalls!(define_usercalls);
251 invoke_with_usercalls!(define_usercalls_asm);