The final published version of the VMClock specification adds support for an extra vm_generation_counter field which allows hypervisors to differentiate between live migration and snapshot loading events. During the latter, apart from adjusting clocks, guests might want to take further actions such as resetting network devices, updating UUIDs, reseeding entropy pools, etc.
VM generation counter itself is stored in the guest memory region and exposed to guest userspace, so we don't need to serialize it within vmstate_vmclock as well. Signed-off-by: Babis Chalios <[email protected]> --- hw/acpi/vmclock.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/hw/acpi/vmclock.c b/hw/acpi/vmclock.c index c582c0c1f8..47cbba4496 100644 --- a/hw/acpi/vmclock.c +++ b/hw/acpi/vmclock.c @@ -20,6 +20,7 @@ #include "hw/qdev-properties.h" #include "hw/qdev-properties-system.h" #include "migration/vmstate.h" +#include "migration/misc.h" #include "system/reset.h" #include "standard-headers/linux/vmclock-abi.h" @@ -64,6 +65,7 @@ void vmclock_build_acpi(VmclockState *vms, GArray *table_data, static void vmclock_update_guest(VmclockState *vms) { uint64_t disruption_marker; + uint64_t vm_generation_counter; uint32_t seq_count; if (!vms->clk) { @@ -79,6 +81,16 @@ static void vmclock_update_guest(VmclockState *vms) disruption_marker++; vms->clk->disruption_marker = cpu_to_le64(disruption_marker); + /* + * We only increase the vm_generation_counter when loading from a snapshot, + * not during live migration + */ + if (!migration_is_running()) { + vm_generation_counter = le64_to_cpu(vms->clk->vm_generation_counter); + vm_generation_counter++; + vms->clk->vm_generation_counter = cpu_to_le64(vm_generation_counter); + } + /* These barriers pair with read barriers in the guest */ smp_wmb(); vms->clk->seq_count = cpu_to_le32(seq_count + 1); @@ -144,6 +156,7 @@ static void vmclock_realize(DeviceState *dev, Error **errp) vms->clk->magic = cpu_to_le32(VMCLOCK_MAGIC); vms->clk->size = cpu_to_le16(VMCLOCK_SIZE); vms->clk->version = cpu_to_le16(1); + vms->clk->flags = cpu_to_le64(VMCLOCK_FLAG_VM_GEN_COUNTER_PRESENT); /* These are all zero and thus default, but be explicit */ vms->clk->clock_status = VMCLOCK_STATUS_UNKNOWN; -- 2.34.1
