1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 use fortanix_sgx_abi::*;
18 struct UsercallReturn(u64, u64);
21 fn usercall(nr: u64, p1: u64, p2: u64, _ignore: u64, p3: u64, p4: u64) -> UsercallReturn;
24 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)*; )*) => {
45 #[allow(non_camel_case_types)]
47 __enclave_usercalls_invalid,
51 $(enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) $(-> $r)*);)*
55 macro_rules! define_usercalls_asm {
56 ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:ty)*; )*) => {
57 macro_rules! usercalls_asm {
60 ".equ usercall_nr_LAST, 0\n",
62 ".equ usercall_nr_", stringify!($f), ", usercall_nr_LAST+1\n",
63 ".equ usercall_nr_LAST, usercall_nr_", stringify!($f), "\n"
71 macro_rules! define_ra {
72 (< $i:ident > $t:ty) => {
73 impl<$i> RegisterArgument for $t {
74 fn from_register(a: Register) -> Self {
77 fn into_register(self) -> Register {
83 impl RegisterArgument for $t {
84 fn from_register(a: Register) -> Self {
87 fn into_register(self) -> Register {
93 impl RegisterArgument for $t {
94 fn from_register(a: Register) -> Self {
97 fn into_register(self) -> Register {
104 define_ra!(Register);
107 define_ra!(u32 as i32);
109 define_ra!(u16 as i16);
111 define_ra!(u8 as i8);
113 define_ra!(usize as isize);
114 define_ra!(<T> *const T);
115 define_ra!(<T> *mut T);
117 impl RegisterArgument for bool {
118 fn from_register(a: Register) -> bool {
125 fn into_register(self) -> Register {
130 impl<T: RegisterArgument> RegisterArgument for Option<NonNull<T>> {
131 fn from_register(a: Register) -> Option<NonNull<T>> {
134 fn into_register(self) -> Register {
135 self.map_or(0 as _, NonNull::as_ptr) as _
139 impl ReturnValue for ! {
140 fn from_registers(call: &'static str, _regs: (Register, Register)) -> Self {
141 panic!("Usercall {}: did not expect to be re-entered", call);
145 impl ReturnValue for () {
146 fn from_registers(call: &'static str, regs: (Register, Register)) -> Self {
147 assert_eq!(regs.0, 0, "Usercall {}: expected {} return value to be 0", call, "1st");
148 assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd");
153 impl<T: RegisterArgument> ReturnValue for T {
154 fn from_registers(call: &'static str, regs: (Register, Register)) -> Self {
155 assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd");
156 T::from_register(regs.0)
160 impl<T: RegisterArgument, U: RegisterArgument> ReturnValue for (T, U) {
161 fn from_registers(_call: &'static str, regs: (Register, Register)) -> Self {
163 T::from_register(regs.0),
164 U::from_register(regs.1)
169 macro_rules! enclave_usercalls_internal_define_usercalls {
170 (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty,
171 $n3:ident: $t3:ty, $n4:ident: $t4:ty) -> $r:ty) => (
173 pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3, $n4: $t4) -> $r {
174 ReturnValue::from_registers(stringify!($f), do_usercall(
175 Usercalls::$f as Register,
176 RegisterArgument::into_register($n1),
177 RegisterArgument::into_register($n2),
178 RegisterArgument::into_register($n3),
179 RegisterArgument::into_register($n4),
183 (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:ty) => (
185 pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3) -> $r {
186 ReturnValue::from_registers(stringify!($f), do_usercall(
187 Usercalls::$f as Register,
188 RegisterArgument::into_register($n1),
189 RegisterArgument::into_register($n2),
190 RegisterArgument::into_register($n3),
195 (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:ty) => (
197 pub unsafe fn $f($n1: $t1, $n2: $t2) -> $r {
198 ReturnValue::from_registers(stringify!($f), do_usercall(
199 Usercalls::$f as Register,
200 RegisterArgument::into_register($n1),
201 RegisterArgument::into_register($n2),
206 (def fn $f:ident($n1:ident: $t1:ty) -> $r:ty) => (
208 pub unsafe fn $f($n1: $t1) -> $r {
209 ReturnValue::from_registers(stringify!($f), do_usercall(
210 Usercalls::$f as Register,
211 RegisterArgument::into_register($n1),
216 (def fn $f:ident() -> $r:ty) => (
218 pub unsafe fn $f() -> $r {
219 ReturnValue::from_registers(stringify!($f), do_usercall(
220 Usercalls::$f as Register,
225 (def fn $f:ident($($n:ident: $t:ty),*)) => (
226 enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) -> ());
230 invoke_with_usercalls!(define_usercalls);
231 invoke_with_usercalls!(define_usercalls_asm);