vmcore/
reference_time.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Types for hypervisor reference time sources.
5
6#![forbid(unsafe_code)]
7
8use inspect::Inspect;
9use std::convert::Infallible;
10use std::sync::Arc;
11use vm_resource::CanResolveTo;
12use vm_resource::PlatformResource;
13use vm_resource::ResolveResource;
14use vm_resource::ResourceKind;
15
16/// Trait for getting the reference time.
17pub trait GetReferenceTime: Send + Sync {
18    /// Returns the current time.
19    fn now(&self) -> ReferenceTimeResult;
20}
21
22/// The result of a call to [`GetReferenceTime::now()`].
23pub struct ReferenceTimeResult {
24    /// The reference time in 100ns units.
25    pub ref_time: u64,
26    /// Optionally, the system time (in UTC, without leap seconds) at the time
27    /// `ref_time` was snapped.
28    ///
29    /// This is returned if the time source is able to cheaply provide a value
30    /// synchronized with `ref_time`. Otherwise, it is `None`.
31    pub system_time: Option<jiff::Timestamp>,
32}
33
34/// A resource kind for accessing the partition's reference time.
35///
36/// Only the platform resource makes sense for this resource kind,
37/// since there is only one reference time for a partition.
38pub enum ReferenceTimeSourceKind {}
39
40impl ResourceKind for ReferenceTimeSourceKind {
41    const NAME: &'static str = "ref_time";
42}
43
44impl CanResolveTo<ReferenceTimeSource> for ReferenceTimeSourceKind {
45    type Input<'a> = ();
46}
47
48/// A time source that can be used to get the current VM reference time in 100ns
49/// units.
50#[derive(Clone)]
51pub struct ReferenceTimeSource(Arc<dyn GetReferenceTime>);
52
53impl ReferenceTimeSource {
54    /// Creates a new reference time source.
55    pub fn new<T: GetReferenceTime + 'static>(time_source: T) -> Self {
56        Self(Arc::new(time_source))
57    }
58
59    /// Returns the current time.
60    pub fn now(&self) -> ReferenceTimeResult {
61        self.0.now()
62    }
63}
64
65impl Inspect for ReferenceTimeSource {
66    fn inspect(&self, req: inspect::Request<'_>) {
67        let now = self.now();
68        req.respond()
69            .field("ref_time", now.ref_time)
70            .field("system_time", now.system_time.map(inspect::AsDisplay));
71    }
72}
73
74impl From<Arc<dyn GetReferenceTime>> for ReferenceTimeSource {
75    fn from(value: Arc<dyn GetReferenceTime>) -> Self {
76        Self(value)
77    }
78}
79
80impl ResolveResource<ReferenceTimeSourceKind, PlatformResource> for ReferenceTimeSource {
81    type Output = ReferenceTimeSource;
82    type Error = Infallible;
83
84    fn resolve(
85        &self,
86        PlatformResource: PlatformResource,
87        (): (),
88    ) -> Result<Self::Output, Self::Error> {
89        Ok(self.clone())
90    }
91}