Extend VMClock device to send an ACPI notification every time the
seqcount changes to a new even value. Use GPE E08 event, which now
becomes part of the guest ABI.

Signed-off-by: Babis Chalios <[email protected]>
---
 hw/acpi/vmclock.c                    | 17 +++++++++++++++--
 include/hw/acpi/acpi_dev_interface.h |  1 +
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/hw/acpi/vmclock.c b/hw/acpi/vmclock.c
index 47cbba4496..f6f242cb66 100644
--- a/hw/acpi/vmclock.c
+++ b/hw/acpi/vmclock.c
@@ -28,7 +28,7 @@
 void vmclock_build_acpi(VmclockState *vms, GArray *table_data,
                         BIOSLinker *linker, const char *oem_id)
 {
-    Aml *ssdt, *dev, *scope, *crs;
+    Aml *ssdt, *dev, *scope, *crs, *method;
     AcpiTable table = { .sig = "SSDT", .rev = 1,
                         .oem_id = oem_id, .oem_table_id = "VMCLOCK" };
 
@@ -57,6 +57,11 @@ void vmclock_build_acpi(VmclockState *vms, GArray 
*table_data,
     aml_append(scope, dev);
     aml_append(ssdt, scope);
 
+    /* Attach an ACPI notify */
+    method = aml_method("\\_GPE._E08", 0, AML_NOTSERIALIZED);
+    aml_append(method, aml_notify(aml_name("\\_SB.VCLK"), aml_int(0x80)));
+    aml_append(ssdt, method);
+
     g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len);
     acpi_table_end(linker, &table);
     free_aml_allocator();
@@ -67,6 +72,10 @@ static void vmclock_update_guest(VmclockState *vms)
     uint64_t disruption_marker;
     uint64_t vm_generation_counter;
     uint32_t seq_count;
+    Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, NULL);
+    if (!obj) {
+        return;
+    }
 
     if (!vms->clk) {
         return;
@@ -94,6 +103,9 @@ static void vmclock_update_guest(VmclockState *vms)
     /* These barriers pair with read barriers in the guest */
     smp_wmb();
     vms->clk->seq_count = cpu_to_le32(seq_count + 1);
+
+    /* Send _GPE.E08 event */
+    acpi_send_event(DEVICE(obj), ACPI_VMCLOCK_CHANGE_STATUS);
 }
 
 /*
@@ -156,7 +168,8 @@ 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);
+    vms->clk->flags = cpu_to_le64(VMCLOCK_FLAG_VM_GEN_COUNTER_PRESENT |
+                                  VMCLOCK_FLAG_NOTIFICATION_PRESENT);
 
     /* These are all zero and thus default, but be explicit */
     vms->clk->clock_status = VMCLOCK_STATUS_UNKNOWN;
diff --git a/include/hw/acpi/acpi_dev_interface.h 
b/include/hw/acpi/acpi_dev_interface.h
index 8294f8f0cc..f51f6065f9 100644
--- a/include/hw/acpi/acpi_dev_interface.h
+++ b/include/hw/acpi/acpi_dev_interface.h
@@ -14,6 +14,7 @@ typedef enum {
     ACPI_VMGENID_CHANGE_STATUS = 32,
     ACPI_POWER_DOWN_STATUS = 64,
     ACPI_GENERIC_ERROR = 128,
+    ACPI_VMCLOCK_CHANGE_STATUS = 256,
 } AcpiEventStatusBits;
 
 #define TYPE_ACPI_DEVICE_IF "acpi-device-interface"
-- 
2.34.1


Reply via email to