11use crate :: cmp;
22use crate :: io:: { Error as IoError , ErrorKind , IoSlice , IoSliceMut , Result as IoResult } ;
33use crate :: random:: { DefaultRandomSource , Random } ;
4+ use crate :: sync:: OnceLock ;
45use crate :: time:: { Duration , Instant } ;
6+ use crate :: ops:: Add ;
7+ use insecure_time:: { Freq , Tsc , TscBuilder , LearningFreqTscBuilder , NativeTime , NoRdtscTscBuilder } ;
58
69pub ( crate ) mod alloc;
710#[ macro_use]
@@ -10,6 +13,7 @@ pub(crate) mod raw;
1013mod tests;
1114
1215use self :: raw:: * ;
16+ use self :: alloc:: UserRef ;
1317
1418/// Usercall `read`. See the ABI documentation for more information.
1519///
@@ -249,11 +253,79 @@ pub fn send(event_set: u64, tcs: Option<Tcs>) -> IoResult<()> {
249253 unsafe { raw:: send ( event_set, tcs) . from_sgx_result ( ) }
250254}
251255
256+ #[ derive( Copy , Clone , PartialOrd , PartialEq ) ]
257+ struct SgxTime ( u64 ) ;
258+
259+ impl SgxTime {
260+ const NANOS_PER_SEC : u32 = 1_000_000_000 ;
261+
262+ pub fn as_duration ( & self ) -> Duration {
263+ Duration :: new ( self . 0 / Self :: NANOS_PER_SEC as u64 , ( self . 0 % Self :: NANOS_PER_SEC as u64 ) as _ )
264+ }
265+ }
266+
267+ impl Add < Duration > for SgxTime {
268+ type Output = SgxTime ;
269+
270+ fn add ( self , other : Duration ) -> Self :: Output {
271+ let t = self . 0 + other. as_secs ( ) * Self :: NANOS_PER_SEC as u64 + other. subsec_nanos ( ) as u64 ;
272+ SgxTime ( t)
273+ }
274+ }
275+
276+ impl NativeTime for SgxTime {
277+ fn minimum ( ) -> SgxTime {
278+ SgxTime ( 0 )
279+ }
280+
281+ fn abs_diff ( & self , other : & Self ) -> Duration {
282+ Duration :: from_nanos ( self . 0 . abs_diff ( other. 0 ) )
283+ }
284+
285+ fn now ( ) -> Self {
286+ let ( t, _info) = unsafe { raw:: insecure_time ( ) } ;
287+ SgxTime ( t)
288+ }
289+ }
290+
252291/// Usercall `insecure_time`. See the ABI documentation for more information.
253292#[ unstable( feature = "sgx_platform" , issue = "56975" ) ]
254293pub fn insecure_time ( ) -> Duration {
255- let t = unsafe { raw:: insecure_time ( ) } ;
256- Duration :: new ( t / 1_000_000_000 , ( t % 1_000_000_000 ) as _ )
294+ static TSC : OnceLock < Tsc < SgxTime > > = OnceLock :: new ( ) ;
295+
296+ let tsc = TSC . get_or_init ( || {
297+ let ( _t, info) = unsafe { raw:: insecure_time ( ) } ;
298+ let freq = if !info. is_null ( ) {
299+ let info = unsafe { UserRef :: < InsecureTimeInfo > :: from_ptr ( info) . to_enclave ( ) } ;
300+ if info. frequency != 0 {
301+ Some ( Freq :: from_u64 ( info. frequency ) )
302+ } else {
303+ // Enclave runner passed in info, but the host didn't report frequency. In
304+ // the current implementation of the runner, that can't happen, but we may need
305+ // something like that in the future when we pass in additional info. Just being
306+ // very defensive here.
307+ None
308+ }
309+ } else {
310+ // Old enclave runner that doesn't pass in information
311+ None
312+ } ;
313+
314+ if let Some ( freq) = freq {
315+ LearningFreqTscBuilder :: new ( )
316+ . set_initial_frequency ( freq)
317+ . set_frequency_learning_period ( Duration :: from_secs ( 1 ) )
318+ . set_max_acceptable_drift ( Duration :: from_millis ( 1 ) )
319+ . set_max_sync_interval ( Duration :: from_secs ( 60 ) )
320+ . set_monotonic_time ( )
321+ . build ( )
322+ } else {
323+ NoRdtscTscBuilder :: new ( )
324+ . set_monotonic_time ( )
325+ . build ( )
326+ }
327+ } ) ;
328+ tsc. now ( ) . as_duration ( )
257329}
258330
259331/// Usercall `alloc`. See the ABI documentation for more information.
0 commit comments