...
...
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
51
v4:
52
• Trivial checkpatch fixes and comment improvements.
53
39
v3:
54
v3:
40
• 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
41
headers once it gets merged there.
56
headers once it gets merged there.
42
57
43
v2:
58
v2:
44
• Change esterror/maxerror fields to nanoseconds
59
• Change esterror/maxerror fields to nanoseconds.
45
• Change to officially assigned AMZNC10C ACPI HID
60
• Change to officially assigned AMZNC10C ACPI HID.
46
• Fix little-endian handling of fields in update
61
• Fix little-endian handling of fields in update.
47
hw/acpi/Kconfig | 5 +
62
48
hw/acpi/meson.build | 1 +
63
49
hw/acpi/vmclock-abi.h | 186 ++++++++++++++++++++++++++++++++++++++
64
hw/acpi/Kconfig | 5 +
50
hw/acpi/vmclock.c | 184 +++++++++++++++++++++++++++++++++++++
65
hw/acpi/meson.build | 1 +
51
hw/i386/Kconfig | 1 +
66
hw/acpi/vmclock.c | 179 ++++++++++++++++++
52
hw/i386/acpi-build.c | 10 +-
67
hw/i386/Kconfig | 1 +
53
include/hw/acpi/vmclock.h | 34 +++++++
68
hw/i386/acpi-build.c | 10 +-
54
7 files changed, 420 insertions(+), 1 deletion(-)
69
include/hw/acpi/vmclock.h | 34 ++++
55
create mode 100644 hw/acpi/vmclock-abi.h
70
include/standard-headers/linux/vmclock-abi.h | 182 +++++++++++++++++++
71
scripts/update-linux-headers.sh | 1 +
72
8 files changed, 412 insertions(+), 1 deletion(-)
56
create mode 100644 hw/acpi/vmclock.c
73
create mode 100644 hw/acpi/vmclock.c
57
create mode 100644 include/hw/acpi/vmclock.h
74
create mode 100644 include/hw/acpi/vmclock.h
58
75
create mode 100644 include/standard-headers/linux/vmclock-abi.h
59
Guest support:
60
https://lore.kernel.org/qemu-devel/410bbef9771ef8aa51704994a70d5965e367e2ce.camel@infradead.org/
61
62
76
63
diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
77
diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
64
index XXXXXXX..XXXXXXX 100644
78
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/acpi/Kconfig
79
--- a/hw/acpi/Kconfig
66
+++ b/hw/acpi/Kconfig
80
+++ b/hw/acpi/Kconfig
...
...
86
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'))
87
+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'))
88
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'))
89
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'))
90
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'))
91
diff --git a/hw/acpi/vmclock-abi.h b/hw/acpi/vmclock-abi.h
92
new file mode 100644
93
index XXXXXXX..XXXXXXX
94
--- /dev/null
95
+++ b/hw/acpi/vmclock-abi.h
96
@@ -XXX,XX +XXX,XX @@
97
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) */
98
+
99
+/*
100
+ * This structure provides a vDSO-style clock to VM guests, exposing the
101
+ * relationship (or lack thereof) between the CPU clock (TSC, timebase, arch
102
+ * counter, etc.) and real time. It is designed to address the problem of
103
+ * live migration, which other clock enlightenments do not.
104
+ *
105
+ * When a guest is live migrated, this affects the clock in two ways.
106
+ *
107
+ * First, even between identical hosts the actual frequency of the underlying
108
+ * counter will change within the tolerances of its specification (typically
109
+ * ±50PPM, or 4 seconds a day). This frequency also varies over time on the
110
+ * same host, but can be tracked by NTP as it generally varies slowly. With
111
+ * live migration there is a step change in the frequency, with no warning.
112
+ *
113
+ * Second, there may be a step change in the value of the counter itself, as
114
+ * its accuracy is limited by the precision of the NTP synchronization on the
115
+ * source and destination hosts.
116
+ *
117
+ * So any calibration (NTP, PTP, etc.) which the guest has done on the source
118
+ * host before migration is invalid, and needs to be redone on the new host.
119
+ *
120
+ * In its most basic mode, this structure provides only an indication to the
121
+ * guest that live migration has occurred. This allows the guest to know that
122
+ * its clock is invalid and take remedial action. For applications that need
123
+ * reliable accurate timestamps (e.g. distributed databases), the structure
124
+ * can be mapped all the way to userspace. This allows the application to see
125
+ * directly for itself that the clock is disrupted and take appropriate
126
+ * action, even when using a vDSO-style method to get the time instead of a
127
+ * system call.
128
+ *
129
+ * In its more advanced mode. this structure can also be used to expose the
130
+ * precise relationship of the CPU counter to real time, as calibrated by the
131
+ * host. This means that userspace applications can have accurate time
132
+ * immediately after live migration, rather than having to pause operations
133
+ * and wait for NTP to recover. This mode does, of course, rely on the
134
+ * counter being reliable and consistent across CPUs.
135
+ *
136
+ * Note that this must be true UTC, never with smeared leap seconds. If a
137
+ * guest wishes to construct a smeared clock, it can do so. Presenting a
138
+ * smeared clock through this interface would be problematic because it
139
+ * actually messes with the apparent counter *period*. A linear smearing
140
+ * of 1 ms per second would effectively tweak the counter period by 1000PPM
141
+ * at the start/end of the smearing period, while a sinusoidal smear would
142
+ * basically be impossible to represent.
143
+ *
144
+ * This structure is offered with the intent that it be adopted into the
145
+ * nascent virtio-rtc standard, as a virtio-rtc that does not address the live
146
+ * migration problem seems a little less than fit for purpose. For that
147
+ * reason, certain fields use precisely the same numeric definitions as in
148
+ * the virtio-rtc proposal. The structure can also be exposed through an ACPI
149
+ * device with the CID "VMCLOCK", modelled on the "VMGENID" device except for
150
+ * the fact that it uses a real _CRS to convey the address of the structure
151
+ * (which should be a full page, to allow for mapping directly to userspace).
152
+ */
153
+
154
+#ifndef __VMCLOCK_ABI_H__
155
+#define __VMCLOCK_ABI_H__
156
+
157
+#ifdef __KERNEL__
158
+#include <linux/types.h>
159
+#else
160
+#include <stdint.h>
161
+#endif
162
+
163
+struct vmclock_abi {
164
+    /* CONSTANT FIELDS */
165
+    uint32_t magic;
166
+#define VMCLOCK_MAGIC    0x4b4c4356 /* "VCLK" */
167
+    uint32_t size;        /* Size of region containing this structure */
168
+    uint16_t version;    /* 1 */
169
+    uint8_t counter_id; /* Matches VIRTIO_RTC_COUNTER_xxx except INVALID */
170
+#define VMCLOCK_COUNTER_ARM_VCNT    0
171
+#define VMCLOCK_COUNTER_X86_TSC        1
172
+#define VMCLOCK_COUNTER_INVALID        0xff
173
+    uint8_t time_type; /* Matches VIRTIO_RTC_TYPE_xxx */
174
+#define VMCLOCK_TIME_UTC            0    /* Since 1970-01-01 00:00:00z */
175
+#define VMCLOCK_TIME_TAI            1    /* Since 1970-01-01 00:00:00z */
176
+#define VMCLOCK_TIME_MONOTONIC            2    /* Since undefined epoch */
177
+#define VMCLOCK_TIME_INVALID_SMEARED        3    /* Not supported */
178
+#define VMCLOCK_TIME_INVALID_MAYBE_SMEARED    4    /* Not supported */
179
+
180
+    /* NON-CONSTANT FIELDS PROTECTED BY SEQCOUNT LOCK */
181
+    uint32_t seq_count;    /* Low bit means an update is in progress */
182
+    /*
183
+     * This field changes to another non-repeating value when the CPU
184
+     * counter is disrupted, for example on live migration. This lets
185
+     * the guest know that it should discard any calibration it has
186
+     * performed of the counter against external sources (NTP/PTP/etc.).
187
+     */
188
+    uint64_t disruption_marker;
189
+    uint64_t flags;
190
+    /* Indicates that the tai_offset_sec field is valid */
191
+#define VMCLOCK_FLAG_TAI_OFFSET_VALID        (1 << 0)
192
+    /*
193
+     * Optionally used to notify guests of pending maintenance events.
194
+     * A guest which provides latency-sensitive services may wish to
195
+     * remove itself from service if an event is coming up. Two flags
196
+     * indicate the approximate imminence of the event.
197
+     */
198
+#define VMCLOCK_FLAG_DISRUPTION_SOON        (1 << 1) /* About a day */
199
+#define VMCLOCK_FLAG_DISRUPTION_IMMINENT    (1 << 2) /* About an hour */
200
+#define VMCLOCK_FLAG_PERIOD_ESTERROR_VALID    (1 << 3)
201
+#define VMCLOCK_FLAG_PERIOD_MAXERROR_VALID    (1 << 4)
202
+#define VMCLOCK_FLAG_TIME_ESTERROR_VALID    (1 << 5)
203
+#define VMCLOCK_FLAG_TIME_MAXERROR_VALID    (1 << 6)
204
+    /*
205
+     * If the MONOTONIC flag is set then (other than leap seconds) it is
206
+     * guaranteed that the time calculated according this structure at
207
+     * any given moment shall never appear to be later than the time
208
+     * calculated via the structure at any *later* moment.
209
+     *
210
+     * In particular, a timestamp based on a counter reading taken
211
+     * immediately after setting the low bit of seq_count (and the
212
+     * associated memory barrier), using the previously-valid time and
213
+     * period fields, shall never be later than a timestamp based on
214
+     * a counter reading taken immediately before *clearing* the low
215
+     * bit again after the update, using the about-to-be-valid fields.
216
+     */
217
+#define VMCLOCK_FLAG_TIME_MONOTONIC        (1 << 7)
218
+
219
+    uint8_t pad[2];
220
+    uint8_t clock_status;
221
+#define VMCLOCK_STATUS_UNKNOWN        0
222
+#define VMCLOCK_STATUS_INITIALIZING    1
223
+#define VMCLOCK_STATUS_SYNCHRONIZED    2
224
+#define VMCLOCK_STATUS_FREERUNNING    3
225
+#define VMCLOCK_STATUS_UNRELIABLE    4
226
+
227
+    /*
228
+     * The time exposed through this device is never smeared. This field
229
+     * corresponds to the 'subtype' field in virtio-rtc, which indicates
230
+     * the smearing method. However in this case it provides a *hint* to
231
+     * the guest operating system, such that *if* the guest OS wants to
232
+     * provide its users with an alternative clock which does not follow
233
+     * UTC, it may do so in a fashion consistent with the other systems
234
+     * in the nearby environment.
235
+     */
236
+    uint8_t leap_second_smearing_hint; /* Matches VIRTIO_RTC_SUBTYPE_xxx */
237
+#define VMCLOCK_SMEARING_STRICT        0
238
+#define VMCLOCK_SMEARING_NOON_LINEAR    1
239
+#define VMCLOCK_SMEARING_UTC_SLS    2
240
+    int16_t tai_offset_sec;
241
+    uint8_t leap_indicator;
242
+    /*
243
+     * This field is based on the VIRTIO_RTC_LEAP_xxx values as defined
244
+     * in the current draft of virtio-rtc, but since smearing cannot be
245
+     * used with the shared memory device, some values are not used.
246
+     *
247
+     * The _POST_POS and _POST_NEG values allow the guest to perform
248
+     * its own smearing during the day or so after a leap second when
249
+     * such smearing may need to continue being applied for a leap
250
+     * second which is now theoretically "historical".
251
+     */
252
+#define VMCLOCK_LEAP_NONE    0x00    /* No known nearby leap second */
253
+#define VMCLOCK_LEAP_PRE_POS    0x01    /* Positive leap second at EOM */
254
+#define VMCLOCK_LEAP_PRE_NEG    0x02    /* Negative leap second at EOM */
255
+#define VMCLOCK_LEAP_POS    0x03    /* Set during 23:59:60 second */
256
+#define VMCLOCK_LEAP_POST_POS    0x04
257
+#define VMCLOCK_LEAP_POST_NEG    0x05
258
+
259
+    /* Bit shift for counter_period_frac_sec and its error rate */
260
+    uint8_t counter_period_shift;
261
+    /*
262
+     * Paired values of counter and UTC at a given point in time.
263
+     */
264
+    uint64_t counter_value;
265
+    /*
266
+     * Counter period, and error margin of same. The unit of these
267
+     * fields is 1/2^(64 + counter_period_shift) of a second.
268
+     */
269
+    uint64_t counter_period_frac_sec;
270
+    uint64_t counter_period_esterror_rate_frac_sec;
271
+    uint64_t counter_period_maxerror_rate_frac_sec;
272
+
273
+    /*
274
+     * Time according to time_type field above.
275
+     */
276
+    uint64_t time_sec;        /* Seconds since time_type epoch */
277
+    uint64_t time_frac_sec;        /* Units of 1/2^64 of a second */
278
+    uint64_t time_esterror_nanosec;
279
+    uint64_t time_maxerror_nanosec;
280
+};
281
+
282
+#endif /* __VMCLOCK_ABI_H__ */
283
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
284
new file mode 100644
106
new file mode 100644
285
index XXXXXXX..XXXXXXX
107
index XXXXXXX..XXXXXXX
286
--- /dev/null
108
--- /dev/null
287
+++ b/hw/acpi/vmclock.c
109
+++ b/hw/acpi/vmclock.c
...
...
306
+#include "hw/acpi/vmclock.h"
128
+#include "hw/acpi/vmclock.h"
307
+#include "hw/nvram/fw_cfg.h"
129
+#include "hw/nvram/fw_cfg.h"
308
+#include "hw/qdev-properties.h"
130
+#include "hw/qdev-properties.h"
309
+#include "hw/qdev-properties-system.h"
131
+#include "hw/qdev-properties-system.h"
310
+#include "migration/vmstate.h"
132
+#include "migration/vmstate.h"
311
+#include "sysemu/reset.h"
133
+#include "system/reset.h"
312
+
134
+
313
+/* This will come from Linux headers in the end, but we carry our own for now. */
135
+#include "standard-headers/linux/vmclock-abi.h"
314
+#include "vmclock-abi.h"
315
+
136
+
316
+void vmclock_build_acpi(VmclockState *vms, GArray *table_data,
137
+void vmclock_build_acpi(VmclockState *vms, GArray *table_data,
317
+ BIOSLinker *linker, const char *oem_id)
138
+ BIOSLinker *linker, const char *oem_id)
318
+{
139
+{
319
+ Aml *ssdt, *dev, *scope, *method, *addr, *crs;
140
+ Aml *ssdt, *dev, *scope, *crs;
320
+ AcpiTable table = { .sig = "SSDT", .rev = 1,
141
+ AcpiTable table = { .sig = "SSDT", .rev = 1,
321
+ .oem_id = oem_id, .oem_table_id = "VMCLOCK" };
142
+ .oem_id = oem_id, .oem_table_id = "VMCLOCK" };
322
+
143
+
323
+ /* Put VMCLOCK into a separate SSDT table */
144
+ /* Put VMCLOCK into a separate SSDT table */
324
+ acpi_table_begin(&table, table_data);
145
+ acpi_table_begin(&table, table_data);
...
...
329
+ aml_append(dev, aml_name_decl("_HID", aml_string("AMZNC10C")));
150
+ aml_append(dev, aml_name_decl("_HID", aml_string("AMZNC10C")));
330
+ aml_append(dev, aml_name_decl("_CID", aml_string("VMCLOCK")));
151
+ aml_append(dev, aml_name_decl("_CID", aml_string("VMCLOCK")));
331
+ aml_append(dev, aml_name_decl("_DDN", aml_string("VMCLOCK")));
152
+ aml_append(dev, aml_name_decl("_DDN", aml_string("VMCLOCK")));
332
+
153
+
333
+ /* Simple status method */
154
+ /* Simple status method */
334
+ method = aml_method("_STA", 0, AML_NOTSERIALIZED);
155
+ aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
335
+ addr = aml_local(0);
336
+ aml_append(method, aml_store(aml_int(0xf), addr));
337
+ aml_append(method, aml_return(addr));
338
+ aml_append(dev, method);
339
+
156
+
340
+ crs = aml_resource_template();
157
+ crs = aml_resource_template();
341
+ aml_append(crs, aml_qword_memory(AML_POS_DECODE,
158
+ aml_append(crs, aml_qword_memory(AML_POS_DECODE,
342
+ AML_MIN_FIXED, AML_MAX_FIXED,
159
+ AML_MIN_FIXED, AML_MAX_FIXED,
343
+ AML_CACHEABLE, AML_READ_ONLY,
160
+ AML_CACHEABLE, AML_READ_ONLY,
...
...
363
+ return;
180
+ return;
364
+ }
181
+ }
365
+
182
+
366
+ seq_count = le32_to_cpu(vms->clk->seq_count) | 1;
183
+ seq_count = le32_to_cpu(vms->clk->seq_count) | 1;
367
+ vms->clk->seq_count = cpu_to_le32(seq_count);
184
+ vms->clk->seq_count = cpu_to_le32(seq_count);
185
+ /* These barriers pair with read barriers in the guest */
368
+ smp_wmb();
186
+ smp_wmb();
369
+
187
+
370
+ disruption_marker = le64_to_cpu(vms->clk->disruption_marker);
188
+ disruption_marker = le64_to_cpu(vms->clk->disruption_marker);
371
+ disruption_marker++;
189
+ disruption_marker++;
372
+ vms->clk->disruption_marker = cpu_to_le64(disruption_marker);
190
+ vms->clk->disruption_marker = cpu_to_le64(disruption_marker);
373
+
191
+
192
+ /* These barriers pair with read barriers in the guest */
374
+ smp_wmb();
193
+ smp_wmb();
375
+ vms->clk->seq_count = cpu_to_le32(seq_count + 1);
194
+ vms->clk->seq_count = cpu_to_le32(seq_count + 1);
376
+}
195
+}
377
+
196
+
378
+/* After restoring an image, we need to update the guest memory and notify
197
+/*
379
+ * it of a potential change to VM Generation ID
198
+ * After restoring an image, we need to update the guest memory to notify
199
+ * it of clock disruption.
380
+ */
200
+ */
381
+static int vmclock_post_load(void *opaque, int version_id)
201
+static int vmclock_post_load(void *opaque, int version_id)
382
+{
202
+{
383
+ VmclockState *vms = opaque;
203
+ VmclockState *vms = opaque;
204
+
384
+ vmclock_update_guest(vms);
205
+ vmclock_update_guest(vms);
385
+ return 0;
206
+ return 0;
386
+}
207
+}
387
+
208
+
388
+static const VMStateDescription vmstate_vmclock = {
209
+static const VMStateDescription vmstate_vmclock = {
...
...
409
+
230
+
410
+static void vmclock_realize(DeviceState *dev, Error **errp)
231
+static void vmclock_realize(DeviceState *dev, Error **errp)
411
+{
232
+{
412
+ VmclockState *vms = VMCLOCK(dev);
233
+ VmclockState *vms = VMCLOCK(dev);
413
+
234
+
414
+ /* Given that this function is executing, there is at least one VMCLOCK
235
+ /*
236
+ * Given that this function is executing, there is at least one VMCLOCK
415
+ * device. Check if there are several.
237
+ * device. Check if there are several.
416
+ */
238
+ */
417
+ if (!find_vmclock_dev()) {
239
+ if (!find_vmclock_dev()) {
418
+ error_setg(errp, "at most one %s device is permitted", TYPE_VMCLOCK);
240
+ error_setg(errp, "at most one %s device is permitted", TYPE_VMCLOCK);
419
+ return;
241
+ return;
...
...
440
+ qemu_register_reset(vmclock_handle_reset, vms);
262
+ qemu_register_reset(vmclock_handle_reset, vms);
441
+
263
+
442
+ vmclock_update_guest(vms);
264
+ vmclock_update_guest(vms);
443
+}
265
+}
444
+
266
+
445
+static Property vmclock_device_properties[] = {
446
+ DEFINE_PROP_END_OF_LIST(),
447
+};
448
+
449
+static void vmclock_device_class_init(ObjectClass *klass, void *data)
267
+static void vmclock_device_class_init(ObjectClass *klass, void *data)
450
+{
268
+{
451
+ DeviceClass *dc = DEVICE_CLASS(klass);
269
+ DeviceClass *dc = DEVICE_CLASS(klass);
452
+
270
+
453
+ dc->vmsd = &vmstate_vmclock;
271
+ dc->vmsd = &vmstate_vmclock;
454
+ dc->realize = vmclock_realize;
272
+ dc->realize = vmclock_realize;
455
+ device_class_set_props(dc, vmclock_device_properties);
456
+ dc->hotpluggable = false;
273
+ dc->hotpluggable = false;
457
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
274
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
458
+}
275
+}
459
+
276
+
460
+static const TypeInfo vmclock_device_info = {
277
+static const TypeInfo vmclock_device_info = {
...
...
485
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
486
index XXXXXXX..XXXXXXX 100644
303
index XXXXXXX..XXXXXXX 100644
487
--- a/hw/i386/acpi-build.c
304
--- a/hw/i386/acpi-build.c
488
+++ b/hw/i386/acpi-build.c
305
+++ b/hw/i386/acpi-build.c
489
@@ -XXX,XX +XXX,XX @@
306
@@ -XXX,XX +XXX,XX @@
490
#include "sysemu/tpm.h"
307
#include "system/tpm.h"
491
#include "hw/acpi/tpm.h"
308
#include "hw/acpi/tpm.h"
492
#include "hw/acpi/vmgenid.h"
309
#include "hw/acpi/vmgenid.h"
493
+#include "hw/acpi/vmclock.h"
310
+#include "hw/acpi/vmclock.h"
494
#include "hw/acpi/erst.h"
311
#include "hw/acpi/erst.h"
495
#include "hw/acpi/piix4.h"
312
#include "hw/acpi/piix4.h"
496
#include "sysemu/tpm_backend.h"
313
#include "system/tpm_backend.h"
497
@@ -XXX,XX +XXX,XX @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
314
@@ -XXX,XX +XXX,XX @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
498
uint8_t *u;
315
uint8_t *u;
499
GArray *tables_blob = tables->table_data;
316
GArray *tables_blob = tables->table_data;
500
AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
317
AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
501
- Object *vmgenid_dev;
318
- Object *vmgenid_dev;
...
...
555
+
372
+
556
+void vmclock_build_acpi(VmclockState *vms, GArray *table_data,
373
+void vmclock_build_acpi(VmclockState *vms, GArray *table_data,
557
+ BIOSLinker *linker, const char *oem_id);
374
+ BIOSLinker *linker, const char *oem_id);
558
+
375
+
559
+#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
560
--
577
--
561
2.44.0
578
2.47.0
562
579
563
580
diff view generated by jsdifflib