...
...
32
this structure will be included as an optional part of that spec. In the
32
this structure will be included as an optional part of that spec. In the
33
meantime, a simple ACPI device along the lines of VMGENID is perfectly
33
meantime, a simple ACPI device along the lines of VMGENID is perfectly
34
sufficient and is compatible with what's being shipped in certain
34
sufficient and is compatible with what's being shipped in certain
35
commercial hypervisors.
35
commercial hypervisors.
36
36
37
Linux guest support was merged into the 6.13-rc1 kernel:
38
https://git.kernel.org/torvalds/c/205032724226
39
37
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
40
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
41
Reviewed-by: Paul Durrant <paul@xen.org>
38
---
42
---
43
v6:
44
• Rebase for DEFINE_PROP_END_OF_LIST removal and sysemu→system
45
rename.
46
47
v5:
48
• Trivial simplification to AML generation.
49
• Import vmclock-abi.h from Linux now the guest support is merged.
50
39
v4:
51
v4:
40
• Trivial checkpatch fixes and comment improvements.
52
• Trivial checkpatch fixes and comment improvements.
41
53
42
v3:
54
v3:
43
• Add comment that vmclock-abi.h will come from the Linux kernel
55
• Add comment that vmclock-abi.h will come from the Linux kernel
...
...
46
v2:
58
v2:
47
• Change esterror/maxerror fields to nanoseconds.
59
• Change esterror/maxerror fields to nanoseconds.
48
• Change to officially assigned AMZNC10C ACPI HID.
60
• Change to officially assigned AMZNC10C ACPI HID.
49
• Fix little-endian handling of fields in update.
61
• Fix little-endian handling of fields in update.
50
62
51
Guest support:
63
52
https://lore.kernel.org/all/78969a39b51ec00e85551b752767be65f6794b46.camel@infradead.org/
64
hw/acpi/Kconfig | 5 +
53
65
hw/acpi/meson.build | 1 +
54
hw/acpi/Kconfig | 5 +
66
hw/acpi/vmclock.c | 179 ++++++++++++++++++
55
hw/acpi/meson.build | 1 +
67
hw/i386/Kconfig | 1 +
56
hw/acpi/vmclock-abi.h | 186 +++++++++++++++++++++++++++++++++++++
68
hw/i386/acpi-build.c | 10 +-
57
hw/acpi/vmclock.c | 189 ++++++++++++++++++++++++++++++++++++++
69
include/hw/acpi/vmclock.h | 34 ++++
58
hw/i386/Kconfig | 1 +
70
include/standard-headers/linux/vmclock-abi.h | 182 +++++++++++++++++++
59
hw/i386/acpi-build.c | 10 +-
71
scripts/update-linux-headers.sh | 1 +
60
include/hw/acpi/vmclock.h | 34 +++++++
72
8 files changed, 412 insertions(+), 1 deletion(-)
61
7 files changed, 425 insertions(+), 1 deletion(-)
62
create mode 100644 hw/acpi/vmclock-abi.h
63
create mode 100644 hw/acpi/vmclock.c
73
create mode 100644 hw/acpi/vmclock.c
64
create mode 100644 include/hw/acpi/vmclock.h
74
create mode 100644 include/hw/acpi/vmclock.h
75
create mode 100644 include/standard-headers/linux/vmclock-abi.h
65
76
66
diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
77
diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
67
index XXXXXXX..XXXXXXX 100644
78
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/acpi/Kconfig
79
--- a/hw/acpi/Kconfig
69
+++ b/hw/acpi/Kconfig
80
+++ b/hw/acpi/Kconfig
...
...
89
acpi_ss.add(when: 'CONFIG_ACPI_VMGENID', if_true: files('vmgenid.c'))
100
acpi_ss.add(when: 'CONFIG_ACPI_VMGENID', if_true: files('vmgenid.c'))
90
+acpi_ss.add(when: 'CONFIG_ACPI_VMCLOCK', if_true: files('vmclock.c'))
101
+acpi_ss.add(when: 'CONFIG_ACPI_VMCLOCK', if_true: files('vmclock.c'))
91
acpi_ss.add(when: 'CONFIG_ACPI_HW_REDUCED', if_true: files('generic_event_device.c'))
102
acpi_ss.add(when: 'CONFIG_ACPI_HW_REDUCED', if_true: files('generic_event_device.c'))
92
acpi_ss.add(when: 'CONFIG_ACPI_HMAT', if_true: files('hmat.c'))
103
acpi_ss.add(when: 'CONFIG_ACPI_HMAT', if_true: files('hmat.c'))
93
acpi_ss.add(when: 'CONFIG_ACPI_APEI', if_true: files('ghes.c'), if_false: files('ghes-stub.c'))
104
acpi_ss.add(when: 'CONFIG_ACPI_APEI', if_true: files('ghes.c'), if_false: files('ghes-stub.c'))
94
diff --git a/hw/acpi/vmclock-abi.h b/hw/acpi/vmclock-abi.h
95
new file mode 100644
96
index XXXXXXX..XXXXXXX
97
--- /dev/null
98
+++ b/hw/acpi/vmclock-abi.h
99
@@ -XXX,XX +XXX,XX @@
100
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) */
101
+
102
+/*
103
+ * This structure provides a vDSO-style clock to VM guests, exposing the
104
+ * relationship (or lack thereof) between the CPU clock (TSC, timebase, arch
105
+ * counter, etc.) and real time. It is designed to address the problem of
106
+ * live migration, which other clock enlightenments do not.
107
+ *
108
+ * When a guest is live migrated, this affects the clock in two ways.
109
+ *
110
+ * First, even between identical hosts the actual frequency of the underlying
111
+ * counter will change within the tolerances of its specification (typically
112
+ * ±50PPM, or 4 seconds a day). This frequency also varies over time on the
113
+ * same host, but can be tracked by NTP as it generally varies slowly. With
114
+ * live migration there is a step change in the frequency, with no warning.
115
+ *
116
+ * Second, there may be a step change in the value of the counter itself, as
117
+ * its accuracy is limited by the precision of the NTP synchronization on the
118
+ * source and destination hosts.
119
+ *
120
+ * So any calibration (NTP, PTP, etc.) which the guest has done on the source
121
+ * host before migration is invalid, and needs to be redone on the new host.
122
+ *
123
+ * In its most basic mode, this structure provides only an indication to the
124
+ * guest that live migration has occurred. This allows the guest to know that
125
+ * its clock is invalid and take remedial action. For applications that need
126
+ * reliable accurate timestamps (e.g. distributed databases), the structure
127
+ * can be mapped all the way to userspace. This allows the application to see
128
+ * directly for itself that the clock is disrupted and take appropriate
129
+ * action, even when using a vDSO-style method to get the time instead of a
130
+ * system call.
131
+ *
132
+ * In its more advanced mode. this structure can also be used to expose the
133
+ * precise relationship of the CPU counter to real time, as calibrated by the
134
+ * host. This means that userspace applications can have accurate time
135
+ * immediately after live migration, rather than having to pause operations
136
+ * and wait for NTP to recover. This mode does, of course, rely on the
137
+ * counter being reliable and consistent across CPUs.
138
+ *
139
+ * Note that this must be true UTC, never with smeared leap seconds. If a
140
+ * guest wishes to construct a smeared clock, it can do so. Presenting a
141
+ * smeared clock through this interface would be problematic because it
142
+ * actually messes with the apparent counter *period*. A linear smearing
143
+ * of 1 ms per second would effectively tweak the counter period by 1000PPM
144
+ * at the start/end of the smearing period, while a sinusoidal smear would
145
+ * basically be impossible to represent.
146
+ *
147
+ * This structure is offered with the intent that it be adopted into the
148
+ * nascent virtio-rtc standard, as a virtio-rtc that does not address the live
149
+ * migration problem seems a little less than fit for purpose. For that
150
+ * reason, certain fields use precisely the same numeric definitions as in
151
+ * the virtio-rtc proposal. The structure can also be exposed through an ACPI
152
+ * device with the CID "VMCLOCK", modelled on the "VMGENID" device except for
153
+ * the fact that it uses a real _CRS to convey the address of the structure
154
+ * (which should be a full page, to allow for mapping directly to userspace).
155
+ */
156
+
157
+#ifndef __VMCLOCK_ABI_H__
158
+#define __VMCLOCK_ABI_H__
159
+
160
+#ifdef __KERNEL__
161
+#include <linux/types.h>
162
+#else
163
+#include <stdint.h>
164
+#endif
165
+
166
+struct vmclock_abi {
167
+    /* CONSTANT FIELDS */
168
+    uint32_t magic;
169
+#define VMCLOCK_MAGIC    0x4b4c4356 /* "VCLK" */
170
+    uint32_t size;        /* Size of region containing this structure */
171
+    uint16_t version;    /* 1 */
172
+    uint8_t counter_id; /* Matches VIRTIO_RTC_COUNTER_xxx except INVALID */
173
+#define VMCLOCK_COUNTER_ARM_VCNT    0
174
+#define VMCLOCK_COUNTER_X86_TSC        1
175
+#define VMCLOCK_COUNTER_INVALID        0xff
176
+    uint8_t time_type; /* Matches VIRTIO_RTC_TYPE_xxx */
177
+#define VMCLOCK_TIME_UTC            0    /* Since 1970-01-01 00:00:00z */
178
+#define VMCLOCK_TIME_TAI            1    /* Since 1970-01-01 00:00:00z */
179
+#define VMCLOCK_TIME_MONOTONIC            2    /* Since undefined epoch */
180
+#define VMCLOCK_TIME_INVALID_SMEARED        3    /* Not supported */
181
+#define VMCLOCK_TIME_INVALID_MAYBE_SMEARED    4    /* Not supported */
182
+
183
+    /* NON-CONSTANT FIELDS PROTECTED BY SEQCOUNT LOCK */
184
+    uint32_t seq_count;    /* Low bit means an update is in progress */
185
+    /*
186
+     * This field changes to another non-repeating value when the CPU
187
+     * counter is disrupted, for example on live migration. This lets
188
+     * the guest know that it should discard any calibration it has
189
+     * performed of the counter against external sources (NTP/PTP/etc.).
190
+     */
191
+    uint64_t disruption_marker;
192
+    uint64_t flags;
193
+    /* Indicates that the tai_offset_sec field is valid */
194
+#define VMCLOCK_FLAG_TAI_OFFSET_VALID        (1 << 0)
195
+    /*
196
+     * Optionally used to notify guests of pending maintenance events.
197
+     * A guest which provides latency-sensitive services may wish to
198
+     * remove itself from service if an event is coming up. Two flags
199
+     * indicate the approximate imminence of the event.
200
+     */
201
+#define VMCLOCK_FLAG_DISRUPTION_SOON        (1 << 1) /* About a day */
202
+#define VMCLOCK_FLAG_DISRUPTION_IMMINENT    (1 << 2) /* About an hour */
203
+#define VMCLOCK_FLAG_PERIOD_ESTERROR_VALID    (1 << 3)
204
+#define VMCLOCK_FLAG_PERIOD_MAXERROR_VALID    (1 << 4)
205
+#define VMCLOCK_FLAG_TIME_ESTERROR_VALID    (1 << 5)
206
+#define VMCLOCK_FLAG_TIME_MAXERROR_VALID    (1 << 6)
207
+    /*
208
+     * If the MONOTONIC flag is set then (other than leap seconds) it is
209
+     * guaranteed that the time calculated according this structure at
210
+     * any given moment shall never appear to be later than the time
211
+     * calculated via the structure at any *later* moment.
212
+     *
213
+     * In particular, a timestamp based on a counter reading taken
214
+     * immediately after setting the low bit of seq_count (and the
215
+     * associated memory barrier), using the previously-valid time and
216
+     * period fields, shall never be later than a timestamp based on
217
+     * a counter reading taken immediately before *clearing* the low
218
+     * bit again after the update, using the about-to-be-valid fields.
219
+     */
220
+#define VMCLOCK_FLAG_TIME_MONOTONIC        (1 << 7)
221
+
222
+    uint8_t pad[2];
223
+    uint8_t clock_status;
224
+#define VMCLOCK_STATUS_UNKNOWN        0
225
+#define VMCLOCK_STATUS_INITIALIZING    1
226
+#define VMCLOCK_STATUS_SYNCHRONIZED    2
227
+#define VMCLOCK_STATUS_FREERUNNING    3
228
+#define VMCLOCK_STATUS_UNRELIABLE    4
229
+
230
+    /*
231
+     * The time exposed through this device is never smeared. This field
232
+     * corresponds to the 'subtype' field in virtio-rtc, which indicates
233
+     * the smearing method. However in this case it provides a *hint* to
234
+     * the guest operating system, such that *if* the guest OS wants to
235
+     * provide its users with an alternative clock which does not follow
236
+     * UTC, it may do so in a fashion consistent with the other systems
237
+     * in the nearby environment.
238
+     */
239
+    uint8_t leap_second_smearing_hint; /* Matches VIRTIO_RTC_SUBTYPE_xxx */
240
+#define VMCLOCK_SMEARING_STRICT        0
241
+#define VMCLOCK_SMEARING_NOON_LINEAR    1
242
+#define VMCLOCK_SMEARING_UTC_SLS    2
243
+    int16_t tai_offset_sec;
244
+    uint8_t leap_indicator;
245
+    /*
246
+     * This field is based on the VIRTIO_RTC_LEAP_xxx values as defined
247
+     * in the current draft of virtio-rtc, but since smearing cannot be
248
+     * used with the shared memory device, some values are not used.
249
+     *
250
+     * The _POST_POS and _POST_NEG values allow the guest to perform
251
+     * its own smearing during the day or so after a leap second when
252
+     * such smearing may need to continue being applied for a leap
253
+     * second which is now theoretically "historical".
254
+     */
255
+#define VMCLOCK_LEAP_NONE    0x00    /* No known nearby leap second */
256
+#define VMCLOCK_LEAP_PRE_POS    0x01    /* Positive leap second at EOM */
257
+#define VMCLOCK_LEAP_PRE_NEG    0x02    /* Negative leap second at EOM */
258
+#define VMCLOCK_LEAP_POS    0x03    /* Set during 23:59:60 second */
259
+#define VMCLOCK_LEAP_POST_POS    0x04
260
+#define VMCLOCK_LEAP_POST_NEG    0x05
261
+
262
+    /* Bit shift for counter_period_frac_sec and its error rate */
263
+    uint8_t counter_period_shift;
264
+    /*
265
+     * Paired values of counter and UTC at a given point in time.
266
+     */
267
+    uint64_t counter_value;
268
+    /*
269
+     * Counter period, and error margin of same. The unit of these
270
+     * fields is 1/2^(64 + counter_period_shift) of a second.
271
+     */
272
+    uint64_t counter_period_frac_sec;
273
+    uint64_t counter_period_esterror_rate_frac_sec;
274
+    uint64_t counter_period_maxerror_rate_frac_sec;
275
+
276
+    /*
277
+     * Time according to time_type field above.
278
+     */
279
+    uint64_t time_sec;        /* Seconds since time_type epoch */
280
+    uint64_t time_frac_sec;        /* Units of 1/2^64 of a second */
281
+    uint64_t time_esterror_nanosec;
282
+    uint64_t time_maxerror_nanosec;
283
+};
284
+
285
+#endif /* __VMCLOCK_ABI_H__ */
286
diff --git a/hw/acpi/vmclock.c b/hw/acpi/vmclock.c
105
diff --git a/hw/acpi/vmclock.c b/hw/acpi/vmclock.c
287
new file mode 100644
106
new file mode 100644
288
index XXXXXXX..XXXXXXX
107
index XXXXXXX..XXXXXXX
289
--- /dev/null
108
--- /dev/null
290
+++ b/hw/acpi/vmclock.c
109
+++ b/hw/acpi/vmclock.c
...
...
309
+#include "hw/acpi/vmclock.h"
128
+#include "hw/acpi/vmclock.h"
310
+#include "hw/nvram/fw_cfg.h"
129
+#include "hw/nvram/fw_cfg.h"
311
+#include "hw/qdev-properties.h"
130
+#include "hw/qdev-properties.h"
312
+#include "hw/qdev-properties-system.h"
131
+#include "hw/qdev-properties-system.h"
313
+#include "migration/vmstate.h"
132
+#include "migration/vmstate.h"
314
+#include "sysemu/reset.h"
133
+#include "system/reset.h"
315
+
134
+
316
+/* This will come from Linux headers in the end, but we carry our own for now. */
135
+#include "standard-headers/linux/vmclock-abi.h"
317
+#include "vmclock-abi.h"
318
+
136
+
319
+void vmclock_build_acpi(VmclockState *vms, GArray *table_data,
137
+void vmclock_build_acpi(VmclockState *vms, GArray *table_data,
320
+ BIOSLinker *linker, const char *oem_id)
138
+ BIOSLinker *linker, const char *oem_id)
321
+{
139
+{
322
+ Aml *ssdt, *dev, *scope, *method, *addr, *crs;
140
+ Aml *ssdt, *dev, *scope, *crs;
323
+ AcpiTable table = { .sig = "SSDT", .rev = 1,
141
+ AcpiTable table = { .sig = "SSDT", .rev = 1,
324
+ .oem_id = oem_id, .oem_table_id = "VMCLOCK" };
142
+ .oem_id = oem_id, .oem_table_id = "VMCLOCK" };
325
+
143
+
326
+ /* Put VMCLOCK into a separate SSDT table */
144
+ /* Put VMCLOCK into a separate SSDT table */
327
+ acpi_table_begin(&table, table_data);
145
+ acpi_table_begin(&table, table_data);
...
...
332
+ aml_append(dev, aml_name_decl("_HID", aml_string("AMZNC10C")));
150
+ aml_append(dev, aml_name_decl("_HID", aml_string("AMZNC10C")));
333
+ aml_append(dev, aml_name_decl("_CID", aml_string("VMCLOCK")));
151
+ aml_append(dev, aml_name_decl("_CID", aml_string("VMCLOCK")));
334
+ aml_append(dev, aml_name_decl("_DDN", aml_string("VMCLOCK")));
152
+ aml_append(dev, aml_name_decl("_DDN", aml_string("VMCLOCK")));
335
+
153
+
336
+ /* Simple status method */
154
+ /* Simple status method */
337
+ method = aml_method("_STA", 0, AML_NOTSERIALIZED);
155
+ aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
338
+ addr = aml_local(0);
339
+ aml_append(method, aml_store(aml_int(0xf), addr));
340
+ aml_append(method, aml_return(addr));
341
+ aml_append(dev, method);
342
+
156
+
343
+ crs = aml_resource_template();
157
+ crs = aml_resource_template();
344
+ aml_append(crs, aml_qword_memory(AML_POS_DECODE,
158
+ aml_append(crs, aml_qword_memory(AML_POS_DECODE,
345
+ AML_MIN_FIXED, AML_MAX_FIXED,
159
+ AML_MIN_FIXED, AML_MAX_FIXED,
346
+ AML_CACHEABLE, AML_READ_ONLY,
160
+ AML_CACHEABLE, AML_READ_ONLY,
...
...
448
+ qemu_register_reset(vmclock_handle_reset, vms);
262
+ qemu_register_reset(vmclock_handle_reset, vms);
449
+
263
+
450
+ vmclock_update_guest(vms);
264
+ vmclock_update_guest(vms);
451
+}
265
+}
452
+
266
+
453
+static Property vmclock_device_properties[] = {
454
+ DEFINE_PROP_END_OF_LIST(),
455
+};
456
+
457
+static void vmclock_device_class_init(ObjectClass *klass, void *data)
267
+static void vmclock_device_class_init(ObjectClass *klass, void *data)
458
+{
268
+{
459
+ DeviceClass *dc = DEVICE_CLASS(klass);
269
+ DeviceClass *dc = DEVICE_CLASS(klass);
460
+
270
+
461
+ dc->vmsd = &vmstate_vmclock;
271
+ dc->vmsd = &vmstate_vmclock;
462
+ dc->realize = vmclock_realize;
272
+ dc->realize = vmclock_realize;
463
+ device_class_set_props(dc, vmclock_device_properties);
464
+ dc->hotpluggable = false;
273
+ dc->hotpluggable = false;
465
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
274
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
466
+}
275
+}
467
+
276
+
468
+static const TypeInfo vmclock_device_info = {
277
+static const TypeInfo vmclock_device_info = {
...
...
493
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
302
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
494
index XXXXXXX..XXXXXXX 100644
303
index XXXXXXX..XXXXXXX 100644
495
--- a/hw/i386/acpi-build.c
304
--- a/hw/i386/acpi-build.c
496
+++ b/hw/i386/acpi-build.c
305
+++ b/hw/i386/acpi-build.c
497
@@ -XXX,XX +XXX,XX @@
306
@@ -XXX,XX +XXX,XX @@
498
#include "sysemu/tpm.h"
307
#include "system/tpm.h"
499
#include "hw/acpi/tpm.h"
308
#include "hw/acpi/tpm.h"
500
#include "hw/acpi/vmgenid.h"
309
#include "hw/acpi/vmgenid.h"
501
+#include "hw/acpi/vmclock.h"
310
+#include "hw/acpi/vmclock.h"
502
#include "hw/acpi/erst.h"
311
#include "hw/acpi/erst.h"
503
#include "hw/acpi/piix4.h"
312
#include "hw/acpi/piix4.h"
504
#include "sysemu/tpm_backend.h"
313
#include "system/tpm_backend.h"
505
@@ -XXX,XX +XXX,XX @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
314
@@ -XXX,XX +XXX,XX @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
506
uint8_t *u;
315
uint8_t *u;
507
GArray *tables_blob = tables->table_data;
316
GArray *tables_blob = tables->table_data;
508
AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
317
AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
509
- Object *vmgenid_dev;
318
- Object *vmgenid_dev;
...
...
563
+
372
+
564
+void vmclock_build_acpi(VmclockState *vms, GArray *table_data,
373
+void vmclock_build_acpi(VmclockState *vms, GArray *table_data,
565
+ BIOSLinker *linker, const char *oem_id);
374
+ BIOSLinker *linker, const char *oem_id);
566
+
375
+
567
+#endif
376
+#endif
377
diff --git a/include/standard-headers/linux/vmclock-abi.h b/include/standard-headers/linux/vmclock-abi.h
378
new file mode 100644
379
index XXXXXXX..XXXXXXX
380
--- /dev/null
381
+++ b/include/standard-headers/linux/vmclock-abi.h
382
@@ -XXX,XX +XXX,XX @@
383
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) */
384
+
385
+/*
386
+ * This structure provides a vDSO-style clock to VM guests, exposing the
387
+ * relationship (or lack thereof) between the CPU clock (TSC, timebase, arch
388
+ * counter, etc.) and real time. It is designed to address the problem of
389
+ * live migration, which other clock enlightenments do not.
390
+ *
391
+ * When a guest is live migrated, this affects the clock in two ways.
392
+ *
393
+ * First, even between identical hosts the actual frequency of the underlying
394
+ * counter will change within the tolerances of its specification (typically
395
+ * ±50PPM, or 4 seconds a day). This frequency also varies over time on the
396
+ * same host, but can be tracked by NTP as it generally varies slowly. With
397
+ * live migration there is a step change in the frequency, with no warning.
398
+ *
399
+ * Second, there may be a step change in the value of the counter itself, as
400
+ * its accuracy is limited by the precision of the NTP synchronization on the
401
+ * source and destination hosts.
402
+ *
403
+ * So any calibration (NTP, PTP, etc.) which the guest has done on the source
404
+ * host before migration is invalid, and needs to be redone on the new host.
405
+ *
406
+ * In its most basic mode, this structure provides only an indication to the
407
+ * guest that live migration has occurred. This allows the guest to know that
408
+ * its clock is invalid and take remedial action. For applications that need
409
+ * reliable accurate timestamps (e.g. distributed databases), the structure
410
+ * can be mapped all the way to userspace. This allows the application to see
411
+ * directly for itself that the clock is disrupted and take appropriate
412
+ * action, even when using a vDSO-style method to get the time instead of a
413
+ * system call.
414
+ *
415
+ * In its more advanced mode. this structure can also be used to expose the
416
+ * precise relationship of the CPU counter to real time, as calibrated by the
417
+ * host. This means that userspace applications can have accurate time
418
+ * immediately after live migration, rather than having to pause operations
419
+ * and wait for NTP to recover. This mode does, of course, rely on the
420
+ * counter being reliable and consistent across CPUs.
421
+ *
422
+ * Note that this must be true UTC, never with smeared leap seconds. If a
423
+ * guest wishes to construct a smeared clock, it can do so. Presenting a
424
+ * smeared clock through this interface would be problematic because it
425
+ * actually messes with the apparent counter *period*. A linear smearing
426
+ * of 1 ms per second would effectively tweak the counter period by 1000PPM
427
+ * at the start/end of the smearing period, while a sinusoidal smear would
428
+ * basically be impossible to represent.
429
+ *
430
+ * This structure is offered with the intent that it be adopted into the
431
+ * nascent virtio-rtc standard, as a virtio-rtc that does not address the live
432
+ * migration problem seems a little less than fit for purpose. For that
433
+ * reason, certain fields use precisely the same numeric definitions as in
434
+ * the virtio-rtc proposal. The structure can also be exposed through an ACPI
435
+ * device with the CID "VMCLOCK", modelled on the "VMGENID" device except for
436
+ * the fact that it uses a real _CRS to convey the address of the structure
437
+ * (which should be a full page, to allow for mapping directly to userspace).
438
+ */
439
+
440
+#ifndef __VMCLOCK_ABI_H__
441
+#define __VMCLOCK_ABI_H__
442
+
443
+#include "standard-headers/linux/types.h"
444
+
445
+struct vmclock_abi {
446
+    /* CONSTANT FIELDS */
447
+    uint32_t magic;
448
+#define VMCLOCK_MAGIC    0x4b4c4356 /* "VCLK" */
449
+    uint32_t size;        /* Size of region containing this structure */
450
+    uint16_t version;    /* 1 */
451
+    uint8_t counter_id; /* Matches VIRTIO_RTC_COUNTER_xxx except INVALID */
452
+#define VMCLOCK_COUNTER_ARM_VCNT    0
453
+#define VMCLOCK_COUNTER_X86_TSC        1
454
+#define VMCLOCK_COUNTER_INVALID        0xff
455
+    uint8_t time_type; /* Matches VIRTIO_RTC_TYPE_xxx */
456
+#define VMCLOCK_TIME_UTC            0    /* Since 1970-01-01 00:00:00z */
457
+#define VMCLOCK_TIME_TAI            1    /* Since 1970-01-01 00:00:00z */
458
+#define VMCLOCK_TIME_MONOTONIC            2    /* Since undefined epoch */
459
+#define VMCLOCK_TIME_INVALID_SMEARED        3    /* Not supported */
460
+#define VMCLOCK_TIME_INVALID_MAYBE_SMEARED    4    /* Not supported */
461
+
462
+    /* NON-CONSTANT FIELDS PROTECTED BY SEQCOUNT LOCK */
463
+    uint32_t seq_count;    /* Low bit means an update is in progress */
464
+    /*
465
+     * This field changes to another non-repeating value when the CPU
466
+     * counter is disrupted, for example on live migration. This lets
467
+     * the guest know that it should discard any calibration it has
468
+     * performed of the counter against external sources (NTP/PTP/etc.).
469
+     */
470
+    uint64_t disruption_marker;
471
+    uint64_t flags;
472
+    /* Indicates that the tai_offset_sec field is valid */
473
+#define VMCLOCK_FLAG_TAI_OFFSET_VALID        (1 << 0)
474
+    /*
475
+     * Optionally used to notify guests of pending maintenance events.
476
+     * A guest which provides latency-sensitive services may wish to
477
+     * remove itself from service if an event is coming up. Two flags
478
+     * indicate the approximate imminence of the event.
479
+     */
480
+#define VMCLOCK_FLAG_DISRUPTION_SOON        (1 << 1) /* About a day */
481
+#define VMCLOCK_FLAG_DISRUPTION_IMMINENT    (1 << 2) /* About an hour */
482
+#define VMCLOCK_FLAG_PERIOD_ESTERROR_VALID    (1 << 3)
483
+#define VMCLOCK_FLAG_PERIOD_MAXERROR_VALID    (1 << 4)
484
+#define VMCLOCK_FLAG_TIME_ESTERROR_VALID    (1 << 5)
485
+#define VMCLOCK_FLAG_TIME_MAXERROR_VALID    (1 << 6)
486
+    /*
487
+     * If the MONOTONIC flag is set then (other than leap seconds) it is
488
+     * guaranteed that the time calculated according this structure at
489
+     * any given moment shall never appear to be later than the time
490
+     * calculated via the structure at any *later* moment.
491
+     *
492
+     * In particular, a timestamp based on a counter reading taken
493
+     * immediately after setting the low bit of seq_count (and the
494
+     * associated memory barrier), using the previously-valid time and
495
+     * period fields, shall never be later than a timestamp based on
496
+     * a counter reading taken immediately before *clearing* the low
497
+     * bit again after the update, using the about-to-be-valid fields.
498
+     */
499
+#define VMCLOCK_FLAG_TIME_MONOTONIC        (1 << 7)
500
+
501
+    uint8_t pad[2];
502
+    uint8_t clock_status;
503
+#define VMCLOCK_STATUS_UNKNOWN        0
504
+#define VMCLOCK_STATUS_INITIALIZING    1
505
+#define VMCLOCK_STATUS_SYNCHRONIZED    2
506
+#define VMCLOCK_STATUS_FREERUNNING    3
507
+#define VMCLOCK_STATUS_UNRELIABLE    4
508
+
509
+    /*
510
+     * The time exposed through this device is never smeared. This field
511
+     * corresponds to the 'subtype' field in virtio-rtc, which indicates
512
+     * the smearing method. However in this case it provides a *hint* to
513
+     * the guest operating system, such that *if* the guest OS wants to
514
+     * provide its users with an alternative clock which does not follow
515
+     * UTC, it may do so in a fashion consistent with the other systems
516
+     * in the nearby environment.
517
+     */
518
+    uint8_t leap_second_smearing_hint; /* Matches VIRTIO_RTC_SUBTYPE_xxx */
519
+#define VMCLOCK_SMEARING_STRICT        0
520
+#define VMCLOCK_SMEARING_NOON_LINEAR    1
521
+#define VMCLOCK_SMEARING_UTC_SLS    2
522
+    uint16_t tai_offset_sec; /* Actually two's complement signed */
523
+    uint8_t leap_indicator;
524
+    /*
525
+     * This field is based on the VIRTIO_RTC_LEAP_xxx values as defined
526
+     * in the current draft of virtio-rtc, but since smearing cannot be
527
+     * used with the shared memory device, some values are not used.
528
+     *
529
+     * The _POST_POS and _POST_NEG values allow the guest to perform
530
+     * its own smearing during the day or so after a leap second when
531
+     * such smearing may need to continue being applied for a leap
532
+     * second which is now theoretically "historical".
533
+     */
534
+#define VMCLOCK_LEAP_NONE    0x00    /* No known nearby leap second */
535
+#define VMCLOCK_LEAP_PRE_POS    0x01    /* Positive leap second at EOM */
536
+#define VMCLOCK_LEAP_PRE_NEG    0x02    /* Negative leap second at EOM */
537
+#define VMCLOCK_LEAP_POS    0x03    /* Set during 23:59:60 second */
538
+#define VMCLOCK_LEAP_POST_POS    0x04
539
+#define VMCLOCK_LEAP_POST_NEG    0x05
540
+
541
+    /* Bit shift for counter_period_frac_sec and its error rate */
542
+    uint8_t counter_period_shift;
543
+    /*
544
+     * Paired values of counter and UTC at a given point in time.
545
+     */
546
+    uint64_t counter_value;
547
+    /*
548
+     * Counter period, and error margin of same. The unit of these
549
+     * fields is 1/2^(64 + counter_period_shift) of a second.
550
+     */
551
+    uint64_t counter_period_frac_sec;
552
+    uint64_t counter_period_esterror_rate_frac_sec;
553
+    uint64_t counter_period_maxerror_rate_frac_sec;
554
+
555
+    /*
556
+     * Time according to time_type field above.
557
+     */
558
+    uint64_t time_sec;        /* Seconds since time_type epoch */
559
+    uint64_t time_frac_sec;        /* Units of 1/2^64 of a second */
560
+    uint64_t time_esterror_nanosec;
561
+    uint64_t time_maxerror_nanosec;
562
+};
563
+
564
+#endif /* __VMCLOCK_ABI_H__ */
565
diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh
566
index XXXXXXX..XXXXXXX 100755
567
--- a/scripts/update-linux-headers.sh
568
+++ b/scripts/update-linux-headers.sh
569
@@ -XXX,XX +XXX,XX @@ for i in "$hdrdir"/include/linux/*virtio*.h \
570
"$hdrdir/include/linux/kernel.h" \
571
"$hdrdir/include/linux/kvm_para.h" \
572
"$hdrdir/include/linux/vhost_types.h" \
573
+ "$hdrdir/include/linux/vmclock-abi.h" \
574
"$hdrdir/include/linux/sysinfo.h"; do
575
cp_portable "$i" "$output/include/standard-headers/linux"
576
done
568
--
577
--
569
2.44.0
578
2.47.0
570
579
571
580
diff view generated by jsdifflib