hyperv_ic_protocol/
timesync.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Protocol definitions for the timesync IC.
5
6use crate::Version;
7use bitfield_struct::bitfield;
8use zerocopy::FromBytes;
9use zerocopy::Immutable;
10use zerocopy::IntoBytes;
11use zerocopy::KnownLayout;
12use zerocopy::little_endian::U64 as U64LE;
13
14/// The interface ID for the timesync IC.
15pub const INTERFACE_ID: guid::Guid = guid::guid!("9527e630-d0ae-497b-adce-e80ab0175caf");
16/// The instance ID for the timesync IC.
17pub const INSTANCE_ID: guid::Guid = guid::guid!("2dd1ce17-079e-403c-b352-a1921ee207ee");
18
19/// Version 1.0.
20pub const TIMESYNC_VERSION_1: Version = Version::new(1, 0);
21/// Version 3.0.
22pub const TIMESYNC_VERSION_3: Version = Version::new(3, 0);
23/// Version 4.0. Introduced a new message format.
24pub const TIMESYNC_VERSION_4: Version = Version::new(4, 0);
25
26/// The epoch used for [`TimesyncMessage::parent_time`] and
27/// [`TimesyncMessageV4::parent_time`]. Jan 1, 1601, 00:00:00 UTC.
28pub const EPOCH: jiff::Timestamp = jiff::Timestamp::constant(-11644473600, 0);
29
30/// Timesync messages used before version 4.0.
31#[repr(C)]
32#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
33pub struct TimesyncMessage {
34    /// The wall clock time measured in the parent, in UTC (without leap
35    /// seconds), measured in 100ns units since 1 Jan 1601.
36    pub parent_time: U64LE,
37    /// Unused.
38    pub child_time: U64LE,
39    /// The measured round trip time by the parent.
40    pub round_trip_time: U64LE,
41    /// Flags indicating the message's purpose.
42    pub flags: TimesyncFlags,
43    /// Reserved.
44    pub reserved: [u8; 3],
45}
46
47/// Timesync messages used in version 4.0 and later.
48#[repr(C)]
49#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
50pub struct TimesyncMessageV4 {
51    /// The wall clock time measured in the parent, in UTC (without leap
52    /// seconds), measured in 100ns units since 1 Jan 1601.
53    pub parent_time: U64LE,
54    /// The VM reference time of the child, at the time the parent measured the
55    /// wall clock time.
56    pub vm_reference_time: u64,
57    /// Flags indicating the message's purpose.
58    pub flags: TimesyncFlags,
59    /// The NTP leap indicator.
60    pub leap_indicator: u8,
61    /// The NTP stratum.
62    pub stratum: u8,
63    /// Reserved.
64    pub reserved: [u8; 5],
65}
66
67/// Flags for timesync messages.
68#[bitfield(u8)]
69#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
70pub struct TimesyncFlags {
71    /// This is a sync message.
72    pub sync: bool,
73    /// This is a sample message.
74    pub sample: bool,
75    #[bits(6)]
76    _rsvd: u8,
77}
78
79#[cfg(test)]
80mod tests {
81    #[test]
82    fn verify_epoch() {
83        let epoch = jiff::civil::date(1601, 1, 1)
84            .at(0, 0, 0, 0)
85            .to_zoned(jiff::tz::TimeZone::UTC)
86            .unwrap()
87            .timestamp();
88
89        assert_eq!(
90            epoch,
91            super::EPOCH,
92            "{} {}",
93            epoch.as_second(),
94            epoch.subsec_nanosecond()
95        );
96    }
97}