]> www.infradead.org Git - users/dwmw2/vmclock.git/commitdiff
Update to struct v3
authorDavid Woodhouse <dwmw@amazon.co.uk>
Mon, 8 Jul 2024 06:56:14 +0000 (06:56 +0000)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Mon, 8 Jul 2024 06:56:14 +0000 (06:56 +0000)
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
vmclock-abi.h

index 4172ec31dcad478538d7b72b3de0e74eb84f4258..84f0e37a8a060fceba512267e0811de5f7c93e7f 100644 (file)
@@ -10,7 +10,7 @@
  *
  * First, even between identical hosts the actual frequency of the underlying
  * counter will change within the tolerances of its specification (typically
- * ±50PPM, or 4 seconds a day). The frequency also varies over time on the
+ * ±50PPM, or 4 seconds a day). This frequency also varies over time on the
  * same host, but can be tracked by NTP as it generally varies slowly. With
  * live migration there is a step change in the frequency, with no warning.
  *
  * of 1 ms per second would effectively tweak the counter period by 1000PPM
  * at the start/end of the smearing period, while a sinusoidal smear would
  * basically be impossible to represent.
+ *
+ * This structure is offered with the intent that it be adopted into the
+ * nascent virtio-rtc standard, as a virtio-rtc that does not address the live
+ * migration problem seems a little less than fit for purpose. For that
+ * reason, certain fields use precisely the same numeric definitions as in
+ * the virtio-rtc proposal. The structure can also be exposed through an ACPI
+ * device with the CID "VMCLOCK", modelled on the "VMGENID" device except for
+ * the fact that it uses a real _CRS to convey the address of the structure
+ * (which should be a full page, to allow for mapping directly to userspace).
  */
 
 #ifndef __VMCLOCK_ABI_H__
 #endif
 
 struct vmclock_abi {
+       /* CONSTANT FIELDS */
        uint32_t magic;
 #define VMCLOCK_MAGIC  0x4b4c4356 /* "VCLK" */
-       uint16_t size;          /* Size of page containing this structure */
+       uint32_t size;          /* Size of region containing this structure */
        uint16_t version;       /* 1 */
-
-       /* Sequence lock. Low bit means an update is in progress. */
-       uint32_t seq_count;
-
-       uint32_t flags;
+       uint8_t counter_id; /* Matches VIRTIO_RTC_COUNTER_xxx except INVALID */
+#define VMCLOCK_COUNTER_ARM_VCNT       0
+#define VMCLOCK_COUNTER_X86_TSC                1
+#define VMCLOCK_COUNTER_INVALID                0xff
+       uint8_t time_type; /* Matches VIRTIO_RTC_TYPE_xxx */
+#define VMCLOCK_TIME_UTC                       0       /* Since 1970-01-01 00:00:00z */
+#define VMCLOCK_TIME_TAI                       1       /* Since 1970-01-01 00:00:00z */
+#define VMCLOCK_TIME_MONOTONIC                 2       /* Since undefined epoch */
+#define VMCLOCK_TIME_INVALID_SMEARED           3       /* Not supported */
+#define VMCLOCK_TIME_INVALID_MAYBE_SMEARED     4       /* Not supported */
+
+       /* NON-CONSTANT FIELDS PROTECTED BY SEQCOUNT LOCK */
+       uint32_t seq_count;     /* Low bit means an update is in progress */
+       /*
+        * This field changes to another non-repeating value when the CPU
+        * counter is disrupted, for example on live migration. This lets
+        * the guest know that it should discard any calibration it has
+        * performed of the counter against external sources (NTP/PTP/etc.).
+        */
+       uint64_t disruption_marker;
+       uint64_t flags;
        /* Indicates that the tai_offset_sec field is valid */
 #define VMCLOCK_FLAG_TAI_OFFSET_VALID          (1 << 0)
        /*
         * Optionally used to notify guests of pending maintenance events.
-        * A guest may wish to remove itself from service if an event is
-        * coming up. Two flags indicate the rough imminence of the event.
+        * A guest which provides latency-sensitive services may wish to
+        * remove itself from service if an event is coming up. Two flags
+        * indicate the approximate imminence of the event.
         */
 #define VMCLOCK_FLAG_DISRUPTION_SOON           (1 << 1) /* About a day */
 #define VMCLOCK_FLAG_DISRUPTION_IMMINENT       (1 << 2) /* About an hour */
-       /* Indicates that the utc_time_maxerror_picosec field is valid */
-#define VMCLOCK_FLAG_UTC_MAXERROR_VALID                (1 << 3)
-       /* Indicates counter_period_error_rate_frac_sec is valid */
-#define VMCLOCK_FLAG_PERIOD_ERROR_VALID                (1 << 4)
-
+#define VMCLOCK_FLAG_PERIOD_ESTERROR_VALID     (1 << 3)
+#define VMCLOCK_FLAG_PERIOD_MAXERROR_VALID     (1 << 4)
+#define VMCLOCK_FLAG_TIME_ESTERROR_VALID       (1 << 5)
+#define VMCLOCK_FLAG_TIME_MAXERROR_VALID       (1 << 6)
        /*
-        * This field changes to another non-repeating value when the CPU
-        * counter is disrupted, for example on live migration. This lets
-        * the guest know that it should discard any calibration it has
-        * performed of the counter against external sources (NTP/PTP/etc.).
+        * Even regardless of leap seconds, the time presented through this
+        * mechanism may not be strictly monotonic. If the counter slows down
+        * and the host adapts to this discovery, the time calculated from
+        * the value of the counter immediately after an update to this
+        * structure, may appear to be *earlier* than a calculation just
+        * before the update (while the counter was believed to be running
+        * faster than it now is). A guest operating system will typically
+        * *skew* its own system clock back towards the reference clock
+        * exposed here, rather than following this clock directly. If,
+        * however, this structure is being populated from such a system
+        * clock which is already handled in such a fashion and the results
+        * *are* guaranteed to be monotonic, such monotonicity can be
+        * advertised by setting this bit.
         */
-       uint64_t disruption_marker;
+#define VMCLOCK_FLAG_TIME_MONOTONIC            (1 << 7)
 
+       uint8_t pad[2];
        uint8_t clock_status;
 #define VMCLOCK_STATUS_UNKNOWN         0
 #define VMCLOCK_STATUS_INITIALIZING    1
@@ -94,84 +130,58 @@ struct vmclock_abi {
 #define VMCLOCK_STATUS_FREERUNNING     3
 #define VMCLOCK_STATUS_UNRELIABLE      4
 
-       uint8_t counter_id; /* VIRTIO_RTC_COUNTER_xxx */
-#define VMCLOCK_COUNTER_ARM_VCNT       0
-#define VMCLOCK_COUNTER_X86_TSC                1
-#define VMCLOCK_COUNTER_X86_ART                2
-#define VMCLOCK_COUNTER_INVALID                0xff
-
        /*
-        * By providing the offset from UTC to TAI, the guest can know both
-        * UTC and TAI reliably, whichever is indicated in the time_type
-        * field. Valid if VMCLOCK_FLAG_TAI_OFFSET_VALID is set in flags.
+        * The time exposed through this device is never smeared. This field
+        * corresponds to the 'subtype' field in virtio-rtc, which indicates
+        * the smearing method. However in this case it provides a *hint* to
+        * the guest operating system, such that *if* the guest OS wants to
+        * provide its users with an alternative clock which does not follow
+        * the POSIX CLOCK_REALTIME standard, it may do so in a fashion
+        * consistent with the other systems in the nearby environment.
         */
+       uint8_t leap_second_smearing_hint; /* Matches VIRTIO_RTC_SUBTYPE_xxx */
+#define VMCLOCK_SMEARING_STRICT                0
+#define VMCLOCK_SMEARING_NOON_LINEAR   1
+#define VMCLOCK_SMEARING_UTC_SLS       2
        int16_t tai_offset_sec;
-
-       /*
-        * The time exposed through this device is never smeaared; if it
-        * claims to be VMCLOCK_TIME_UTC then it MUST be UTC. This field
-        * provides a hint to the guest operating system, such that *if*
-        * the guest OS wants to provide its users with an alternative
-        * clock which does not follow the POSIX CLOCK_REALTIME standard,
-        * it may do so in a fashion consistent with the other systems
-        * in the nearby environment.
-        */
-       uint8_t leap_second_smearing_hint; /* Not quite VIRTIO_RTC_SUBTYPE_xxx */
-       /* Provide true UTC to users, unsmeared. */;
-#define VMCLOCK_SMEARING_NONE                  0
-       /*
-        * https://aws.amazon.com/blogs/aws/look-before-you-leap-the-coming-leap-second-and-aws/
-        * https://developers.google.com/time/smear
-        *
-        * From noon on the day before to noon on the day after, smear the
-        * clock by a linear 1/86400s per second.
-       */
-#define VMCLOCK_SMEARING_NOON_LINEAR           2
-       /*
-        * draft-kuhn-leapsecond-00
-        * For the 1000s leading up to the leap second, smear the clock by
-        * clock by a linear 1ms per second.
-        */
-#define VMCLOCK_SMEARING_UTC_SLS               4
-
+       uint8_t leap_indicator; /* Based on VIRTIO_RTC_LEAP_xxx */
+#define VMCLOCK_LEAP_NONE      0       /* No known nearby leap second */
+#define VMCLOCK_LEAP_PRE_POS   1       /* Leap second + at end of month */
+#define VMCLOCK_LEAP_PRE_NEG   2       /* Leap second - at end of month */
+#define VMCLOCK_LEAP_POS       3       /* Set during 23:59:60 second */
+#define VMCLOCK_LEAP_NEG       4       /* Not used in VMCLOCK */
        /*
-        * What time is exposed in the time_sec/time_frac_sec fields?
+        * These values are not (yet) in virtio-rtc. They indicate that a
+        * leap second *has* occurred at the start of the month. This allows
+        * a guest to generate a smeared clock from the accurate clock which
+        * this device provides, as smearing may need to continue for up to a
+        * period of time *after* the point of the leap second itself. Must
+        * be cleared by the 15th day of the month.
         */
-       uint8_t time_type; /* VIRTIO_RTC_TYPE_xxx */
-#define VMCLOCK_TIME_UTC               0       /* Since 1970-01-01 00:00:00z */
-#define VMCLOCK_TIME_TAI               1       /* Since 1970-01-01 00:00:00z */
-#define VMCLOCK_TIME_MONOTONIC         2       /* Since undefined epoch */
-#define VMCLOCK_TIME_SMEARED_INVALID   3       /* UTC but with smeared leap seconds */
+#define VMCLOCK_LEAP_POST_POS  5
+#define VMCLOCK_LEAP_POST_NEG  6
 
        /* Bit shift for counter_period_frac_sec and its error rate */
        uint8_t counter_period_shift;
-
-       /*
-        * Unlike in NTP, this can indicate a leap second in the past. This
-        * is needed to allow guests to derive an imprecise clock with
-        * smeared leap seconds for themselves, as some modes of smearing
-        * need the adjustments to continue even after the moment at which
-        * the leap second should have occurred.
-        */
-       int8_t leapsecond_direction;
-       uint64_t leapsecond_tai_sec; /* Since 1970-01-01 00:00:00z */
-
        /*
         * Paired values of counter and UTC at a given point in time.
         */
        uint64_t counter_value;
-       uint64_t time_sec;
-       uint64_t time_frac_sec;
-
        /*
         * Counter frequency, and error margin. The unit of these fields is
         * seconds >> (64 + counter_period_shift)
         */
        uint64_t counter_period_frac_sec;
-       uint64_t counter_period_error_rate_frac_sec;
+       uint64_t counter_period_esterror_rate_frac_sec;
+       uint64_t counter_period_maxerror_rate_frac_sec;
 
-       /* Error margin of UTC reading above (± picoseconds) */
-       uint64_t utc_time_maxerror_picosec;
+       /*
+        * Time according to time_type field above.
+        */
+       uint64_t time_sec;              /* Seconds since time_type epoch */
+       uint64_t time_frac_sec;         /* (seconds >> 64) */
+       uint64_t time_esterror_picosec; /* (± picoseconds) */
+       uint64_t time_maxerror_picosec; /* (± picoseconds) */
 };
 
 #endif /*  __VMCLOCK_ABI_H__ */