]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/sgx/abi/usercalls/mod.rs
Rollup merge of #56986 - alexcrichton:move-jemalloc, r=Mark-Simulacrum
[rust.git] / src / libstd / sys / sgx / abi / usercalls / mod.rs
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.
4 //
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.
10
11 use io::{Error as IoError, Result as IoResult};
12 use time::Duration;
13
14 pub(crate) mod alloc;
15 #[macro_use]
16 pub(crate) mod raw;
17
18 use self::raw::*;
19
20 /// Usercall `read`. See the ABI documentation for more information.
21 #[unstable(feature = "sgx_platform", issue = "56975")]
22 pub fn read(fd: Fd, buf: &mut [u8]) -> IoResult<usize> {
23     unsafe {
24         let mut userbuf = alloc::User::<[u8]>::uninitialized(buf.len());
25         let len = raw::read(fd, userbuf.as_mut_ptr(), userbuf.len()).from_sgx_result()?;
26         userbuf[..len].copy_to_enclave(&mut buf[..len]);
27         Ok(len)
28     }
29 }
30
31 /// Usercall `read_alloc`. See the ABI documentation for more information.
32 #[unstable(feature = "sgx_platform", issue = "56975")]
33 pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
34     unsafe {
35         let mut userbuf = alloc::User::<ByteBuffer>::uninitialized();
36         raw::read_alloc(fd, userbuf.as_raw_mut_ptr()).from_sgx_result()?;
37         Ok(userbuf.copy_user_buffer())
38     }
39 }
40
41 /// Usercall `write`. See the ABI documentation for more information.
42 #[unstable(feature = "sgx_platform", issue = "56975")]
43 pub fn write(fd: Fd, buf: &[u8]) -> IoResult<usize> {
44     unsafe {
45         let userbuf = alloc::User::new_from_enclave(buf);
46         raw::write(fd, userbuf.as_ptr(), userbuf.len()).from_sgx_result()
47     }
48 }
49
50 /// Usercall `flush`. See the ABI documentation for more information.
51 #[unstable(feature = "sgx_platform", issue = "56975")]
52 pub fn flush(fd: Fd) -> IoResult<()> {
53     unsafe { raw::flush(fd).from_sgx_result() }
54 }
55
56 /// Usercall `close`. See the ABI documentation for more information.
57 #[unstable(feature = "sgx_platform", issue = "56975")]
58 pub fn close(fd: Fd) {
59     unsafe { raw::close(fd) }
60 }
61
62 fn string_from_bytebuffer(buf: &alloc::UserRef<ByteBuffer>, usercall: &str, arg: &str) -> String {
63     String::from_utf8(buf.copy_user_buffer())
64         .unwrap_or_else(|_| panic!("Usercall {}: expected {} to be valid UTF-8", usercall, arg))
65 }
66
67 /// Usercall `bind_stream`. See the ABI documentation for more information.
68 #[unstable(feature = "sgx_platform", issue = "56975")]
69 pub fn bind_stream(addr: &str) -> IoResult<(Fd, String)> {
70     unsafe {
71         let addr_user = alloc::User::new_from_enclave(addr.as_bytes());
72         let mut local = alloc::User::<ByteBuffer>::uninitialized();
73         let fd = raw::bind_stream(
74             addr_user.as_ptr(),
75             addr_user.len(),
76             local.as_raw_mut_ptr()
77         ).from_sgx_result()?;
78         let local = string_from_bytebuffer(&local, "bind_stream", "local_addr");
79         Ok((fd, local))
80     }
81 }
82
83 /// Usercall `accept_stream`. See the ABI documentation for more information.
84 #[unstable(feature = "sgx_platform", issue = "56975")]
85 pub fn accept_stream(fd: Fd) -> IoResult<(Fd, String, String)> {
86     unsafe {
87         let mut bufs = alloc::User::<[ByteBuffer; 2]>::uninitialized();
88         let mut buf_it = alloc::UserRef::iter_mut(&mut *bufs); // FIXME: can this be done
89                                                                // without forcing coercion?
90         let (local, peer) = (buf_it.next().unwrap(), buf_it.next().unwrap());
91         let fd = raw::accept_stream(
92             fd,
93             local.as_raw_mut_ptr(),
94             peer.as_raw_mut_ptr()
95         ).from_sgx_result()?;
96         let local = string_from_bytebuffer(&local, "accept_stream", "local_addr");
97         let peer = string_from_bytebuffer(&peer, "accept_stream", "peer_addr");
98         Ok((fd, local, peer))
99     }
100 }
101
102 /// Usercall `connect_stream`. See the ABI documentation for more information.
103 #[unstable(feature = "sgx_platform", issue = "56975")]
104 pub fn connect_stream(addr: &str) -> IoResult<(Fd, String, String)> {
105     unsafe {
106         let addr_user = alloc::User::new_from_enclave(addr.as_bytes());
107         let mut bufs = alloc::User::<[ByteBuffer; 2]>::uninitialized();
108         let mut buf_it = alloc::UserRef::iter_mut(&mut *bufs); // FIXME: can this be done
109                                                                // without forcing coercion?
110         let (local, peer) = (buf_it.next().unwrap(), buf_it.next().unwrap());
111         let fd = raw::connect_stream(
112             addr_user.as_ptr(),
113             addr_user.len(),
114             local.as_raw_mut_ptr(),
115             peer.as_raw_mut_ptr()
116         ).from_sgx_result()?;
117         let local = string_from_bytebuffer(&local, "connect_stream", "local_addr");
118         let peer = string_from_bytebuffer(&peer, "connect_stream", "peer_addr");
119         Ok((fd, local, peer))
120     }
121 }
122
123 /// Usercall `launch_thread`. See the ABI documentation for more information.
124 #[unstable(feature = "sgx_platform", issue = "56975")]
125 pub unsafe fn launch_thread() -> IoResult<()> {
126     raw::launch_thread().from_sgx_result()
127 }
128
129 /// Usercall `exit`. See the ABI documentation for more information.
130 #[unstable(feature = "sgx_platform", issue = "56975")]
131 pub fn exit(panic: bool) -> ! {
132     unsafe { raw::exit(panic) }
133 }
134
135 /// Usercall `wait`. See the ABI documentation for more information.
136 #[unstable(feature = "sgx_platform", issue = "56975")]
137 pub fn wait(event_mask: u64, timeout: u64) -> IoResult<u64> {
138     unsafe { raw::wait(event_mask, timeout).from_sgx_result() }
139 }
140
141 /// Usercall `send`. See the ABI documentation for more information.
142 #[unstable(feature = "sgx_platform", issue = "56975")]
143 pub fn send(event_set: u64, tcs: Option<Tcs>) -> IoResult<()> {
144     unsafe { raw::send(event_set, tcs).from_sgx_result() }
145 }
146
147 /// Usercall `insecure_time`. See the ABI documentation for more information.
148 #[unstable(feature = "sgx_platform", issue = "56975")]
149 pub fn insecure_time() -> Duration {
150     let t = unsafe { raw::insecure_time() };
151     Duration::new(t / 1_000_000_000, (t % 1_000_000_000) as _)
152 }
153
154 /// Usercall `alloc`. See the ABI documentation for more information.
155 #[unstable(feature = "sgx_platform", issue = "56975")]
156 pub fn alloc(size: usize, alignment: usize) -> IoResult<*mut u8> {
157     unsafe { raw::alloc(size, alignment).from_sgx_result() }
158 }
159
160 #[unstable(feature = "sgx_platform", issue = "56975")]
161 #[doc(inline)]
162 pub use self::raw::free;
163
164 fn check_os_error(err: Result) -> i32 {
165     // FIXME: not sure how to make sure all variants of Error are covered
166     if err == Error::NotFound as _ ||
167        err == Error::PermissionDenied as _ ||
168        err == Error::ConnectionRefused as _ ||
169        err == Error::ConnectionReset as _ ||
170        err == Error::ConnectionAborted as _ ||
171        err == Error::NotConnected as _ ||
172        err == Error::AddrInUse as _ ||
173        err == Error::AddrNotAvailable as _ ||
174        err == Error::BrokenPipe as _ ||
175        err == Error::AlreadyExists as _ ||
176        err == Error::WouldBlock as _ ||
177        err == Error::InvalidInput as _ ||
178        err == Error::InvalidData as _ ||
179        err == Error::TimedOut as _ ||
180        err == Error::WriteZero as _ ||
181        err == Error::Interrupted as _ ||
182        err == Error::Other as _ ||
183        err == Error::UnexpectedEof as _ ||
184        ((Error::UserRangeStart as _)..=(Error::UserRangeEnd as _)).contains(&err)
185     {
186         err
187     } else {
188         panic!("Usercall: returned invalid error value {}", err)
189     }
190 }
191
192 trait FromSgxResult {
193     type Return;
194
195     fn from_sgx_result(self) -> IoResult<Self::Return>;
196 }
197
198 impl<T> FromSgxResult for (Result, T) {
199     type Return = T;
200
201     fn from_sgx_result(self) -> IoResult<Self::Return> {
202         if self.0 == RESULT_SUCCESS {
203             Ok(self.1)
204         } else {
205             Err(IoError::from_raw_os_error(check_os_error(self.0)))
206         }
207     }
208 }
209
210 impl FromSgxResult for Result {
211     type Return = ();
212
213     fn from_sgx_result(self) -> IoResult<Self::Return> {
214         if self == RESULT_SUCCESS {
215             Ok(())
216         } else {
217             Err(IoError::from_raw_os_error(check_os_error(self)))
218         }
219     }
220 }