qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH V12 0/3] Virtual Machine Generation ID
@ 2015-02-10 15:02 Gal Hammer
  2015-02-10 15:02 ` [Qemu-devel] [PATCH V12 1/3] docs: vm generation id device's description Gal Hammer
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Gal Hammer @ 2015-02-10 15:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gal Hammer

Hi,

Resending patches after a bug was found in the call to the
bios_linker_loader_add_pointer function.

Please note that this patch set doesn't include the *.hex.generated
files and the binary ACPI tables (make check will fail).

Thanks,

    Gal.

V12 - Fixed bios_linker_loader_add_pointer call parameters. Offset
      should be relative to the table.

V11 - Add required missing files.

V10 - Fixed typos in docs and a few clarification.

V9 - Add a unit test.
   - Rebased to version 2.2.
   - Removed hex.generated the binary files from patch.

V8 - Add a device's description file.
   - GUID is stored in fw cfg file and the guest writes the
     physical address to the device (reduces vmexits).

V7 - Move the device's description back to the static SSDT table.
   - The GUID is store in a "hard coded" physical address and not
     in the ACPI table itself.
   - ACPI notification is triggered when the GUID is changed.

V6 - include the pre-compiled ASL file
   - remove an empty line at end of files.

V5 - Move device's description to SSDT table (dynamic).

V4 - Fix a typo in error message string.
   - Move device's description from DSDT back to SSDT table.

V3 - Remove "-uuid" command line parameter.
   - Move device's description from SSDT to DSDT table.
   - Add new "vmgenid" sysbus device.

Gal Hammer (3):
  docs: vm generation id device's description
  i386: Add a Virtual Machine Generation ID device
  tests: add a unit test for the vmgenid device.

 default-configs/i386-softmmu.mak     |   1 +
 default-configs/x86_64-softmmu.mak   |   1 +
 docs/specs/vmgenid.txt               |  38 ++++++++++
 hw/acpi/core.c                       |   8 +++
 hw/acpi/ich9.c                       |   8 +++
 hw/acpi/piix4.c                      |   8 +++
 hw/i386/acpi-build.c                 |  25 +++++++
 hw/i386/acpi-dsdt.dsl                |   4 +-
 hw/i386/pc.c                         |   8 +++
 hw/i386/q35-acpi-dsdt.dsl            |   5 +-
 hw/i386/ssdt-misc.dsl                |  43 ++++++++++++
 hw/isa/lpc_ich9.c                    |   1 +
 hw/misc/Makefile.objs                |   1 +
 hw/misc/vmgenid.c                    | 131 +++++++++++++++++++++++++++++++++++
 include/hw/acpi/acpi.h               |   2 +
 include/hw/acpi/acpi_dev_interface.h |   4 ++
 include/hw/acpi/ich9.h               |   2 +
 include/hw/i386/pc.h                 |   3 +
 include/hw/misc/vmgenid.h            |  21 ++++++
 tests/Makefile                       |   2 +
 tests/vmgenid-test.c                 |  48 +++++++++++++
 21 files changed, 362 insertions(+), 2 deletions(-)
 create mode 100644 docs/specs/vmgenid.txt
 create mode 100644 hw/misc/vmgenid.c
 create mode 100644 include/hw/misc/vmgenid.h
 create mode 100644 tests/vmgenid-test.c

-- 
2.1.0

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH V12 1/3] docs: vm generation id device's description
  2015-02-10 15:02 [Qemu-devel] [PATCH V12 0/3] Virtual Machine Generation ID Gal Hammer
@ 2015-02-10 15:02 ` Gal Hammer
  2015-02-10 15:02 ` [Qemu-devel] [PATCH V12 2/3] i386: Add a Virtual Machine Generation ID device Gal Hammer
  2015-02-10 15:02 ` [Qemu-devel] [PATCH V12 3/3] tests: add a unit test for the vmgenid device Gal Hammer
  2 siblings, 0 replies; 4+ messages in thread
From: Gal Hammer @ 2015-02-10 15:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gal Hammer

Signed-off-by: Gal Hammer <ghammer@redhat.com>

---
 docs/specs/vmgenid.txt | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 docs/specs/vmgenid.txt

diff --git a/docs/specs/vmgenid.txt b/docs/specs/vmgenid.txt
new file mode 100644
index 0000000..656d598
--- /dev/null
+++ b/docs/specs/vmgenid.txt
@@ -0,0 +1,38 @@
+VIRTUAL MACHINE GENERATION ID
+=============================
+
+Copyright (C) 2014 Red Hat, Inc.
+
+This work is licensed under the terms of the GNU GPL, version 2 or later.
+See the COPYING file in the top-level directory.
+
+===
+
+The VM generation ID (vmgenid) device is an emulated device which
+exposes a 128-bit, cryptographically random, integer value identifier.
+This allows management applications (e.g. libvirt) to notify the guest
+operating system when the virtual machine is executed with a different
+configuration (e.g. snapshot execution or creation from a template).
+
+This is specified on the web at: http://go.microsoft.com/fwlink/?LinkId=260709
+
+---
+
+The vmgenid device is a sysbus device with the following ACPI ID:
+"QEMU0002".
+
+The device adds a "vmgenid.uuid" property, which can be modified using
+the -global command line argument or the QMP interface.
+
+The device uses a fixed memory resource: 0xfedf0000-0xfedf0003. The
+guest is expected to write the physical address of the GUID's buffer
+to that memory resource. This allows the device to modify the GUID if
+requested by the management application. Current device's implementation
+supports a 32-bit address.
+
+According to the specification, any change to the GUID executes an
+ACPI notification. The vmgenid device triggers the GPE._E00 which
+executes the ACPI Notify operation.
+
+Although not specified in Microsoft's document, it is assumed that the
+device is expected to use the little-endian system.
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH V12 2/3] i386: Add a Virtual Machine Generation ID device
  2015-02-10 15:02 [Qemu-devel] [PATCH V12 0/3] Virtual Machine Generation ID Gal Hammer
  2015-02-10 15:02 ` [Qemu-devel] [PATCH V12 1/3] docs: vm generation id device's description Gal Hammer
@ 2015-02-10 15:02 ` Gal Hammer
  2015-02-10 15:02 ` [Qemu-devel] [PATCH V12 3/3] tests: add a unit test for the vmgenid device Gal Hammer
  2 siblings, 0 replies; 4+ messages in thread
From: Gal Hammer @ 2015-02-10 15:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gal Hammer

Based on Microsoft's sepecifications (paper can be dowloaded from
http://go.microsoft.com/fwlink/?LinkId=260709), add a device
description to the SSDT ACPI table and its implementation.

The GUID is set using a global "vmgenid.uuid" parameter.

Signed-off-by: Gal Hammer <ghammer@redhat.com>

---
 default-configs/i386-softmmu.mak     |   1 +
 default-configs/x86_64-softmmu.mak   |   1 +
 hw/acpi/core.c                       |   8 +++
 hw/acpi/ich9.c                       |   8 +++
 hw/acpi/piix4.c                      |   8 +++
 hw/i386/acpi-build.c                 |  25 +++++++
 hw/i386/acpi-dsdt.dsl                |   4 +-
 hw/i386/pc.c                         |   8 +++
 hw/i386/q35-acpi-dsdt.dsl            |   5 +-
 hw/i386/ssdt-misc.dsl                |  43 ++++++++++++
 hw/isa/lpc_ich9.c                    |   1 +
 hw/misc/Makefile.objs                |   1 +
 hw/misc/vmgenid.c                    | 131 +++++++++++++++++++++++++++++++++++
 include/hw/acpi/acpi.h               |   2 +
 include/hw/acpi/acpi_dev_interface.h |   4 ++
 include/hw/acpi/ich9.h               |   2 +
 include/hw/i386/pc.h                 |   3 +
 include/hw/misc/vmgenid.h            |  21 ++++++
 18 files changed, 274 insertions(+), 2 deletions(-)
 create mode 100644 hw/misc/vmgenid.c
 create mode 100644 include/hw/misc/vmgenid.h

diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 8e08841..bd33c75 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -45,3 +45,4 @@ CONFIG_IOAPIC=y
 CONFIG_ICC_BUS=y
 CONFIG_PVPANIC=y
 CONFIG_MEM_HOTPLUG=y
+CONFIG_VMGENID=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 66557ac..006fc7c 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -45,3 +45,4 @@ CONFIG_IOAPIC=y
 CONFIG_ICC_BUS=y
 CONFIG_PVPANIC=y
 CONFIG_MEM_HOTPLUG=y
+CONFIG_VMGENID=y
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index 51913d6..d4597c6 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -28,6 +28,8 @@
 #include "qapi-visit.h"
 #include "qapi-event.h"
 
+#define ACPI_VM_GENERATION_ID_CHANGED_STATUS 1
+
 struct acpi_table_header {
     uint16_t _length;         /* our length, not actual part of the hdr */
                               /* allows easier parsing for fw_cfg clients */
@@ -683,3 +685,9 @@ void acpi_update_sci(ACPIREGS *regs, qemu_irq irq)
                        (regs->pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) &&
                        !(pm1a_sts & ACPI_BITMASK_TIMER_STATUS));
 }
+
+void acpi_vm_generation_id_changed(ACPIREGS *acpi_regs, qemu_irq irq)
+{
+    acpi_regs->gpe.sts[0] |= ACPI_VM_GENERATION_ID_CHANGED_STATUS;
+    acpi_update_sci(acpi_regs, irq);
+}
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 884dab3..dee2b8c 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -403,3 +403,11 @@ void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
 
     acpi_memory_ospm_status(&s->pm.acpi_memory_hotplug, list);
 }
+
+void ich9_vm_generation_id_changed(AcpiDeviceIf *adev)
+{
+    ICH9LPCState *s = ICH9_LPC_DEVICE(adev);
+    ICH9LPCPMRegs *pm = &s->pm;
+
+    acpi_vm_generation_id_changed(&pm->acpi_regs, pm->irq);
+}
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 184e7e4..61f917d 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -574,6 +574,13 @@ static void piix4_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
     acpi_memory_ospm_status(&s->acpi_memory_hotplug, list);
 }
 
+static void piix4_vm_generation_id_changed(AcpiDeviceIf *adev)
+{
+    PIIX4PMState *s = PIIX4_PM(adev);
+
+    acpi_vm_generation_id_changed(&s->ar, s->irq);
+}
+
 static Property piix4_pm_properties[] = {
     DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
     DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
@@ -611,6 +618,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data)
     hc->plug = piix4_device_plug_cb;
     hc->unplug_request = piix4_device_unplug_request_cb;
     adevc->ospm_status = piix4_ospm_status;
+    adevc->vm_generation_id_changed = piix4_vm_generation_id_changed;
 }
 
 static const TypeInfo piix4_pm_info = {
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 4944249..5947447 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -260,6 +260,7 @@ static void acpi_get_pci_info(PcPciInfo *info)
 #define ACPI_BUILD_TABLE_FILE "etc/acpi/tables"
 #define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp"
 #define ACPI_BUILD_TPMLOG_FILE "etc/tpm/log"
+#define ACPI_BUILD_VMGENID_FILE "etc/vm-generation-id"
 
 static void
 build_header(GArray *linker, GArray *table_data,
@@ -1076,6 +1077,7 @@ build_ssdt(GArray *table_data, GArray *linker,
 {
     MachineState *machine = MACHINE(qdev_get_machine());
     uint32_t nr_mem = machine->ram_slots;
+    uint32_t vm_gid_physical_address;
     unsigned acpi_cpus = guest_info->apic_id_limit;
     int ssdt_start = table_data->len;
     uint8_t *ssdt_ptr;
@@ -1104,6 +1106,21 @@ build_ssdt(GArray *table_data, GArray *linker,
     ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml),
                       ssdt_isa_pest[0], 16, misc->pvpanic_port);
 
+    if (vm_generation_id_set()) {
+        vm_gid_physical_address = ssdt_start + ssdt_acpi_vm_gid_addr[0];
+        bios_linker_loader_alloc(linker, ACPI_BUILD_VMGENID_FILE, 0x1000, true);
+        bios_linker_loader_add_pointer(linker, ACPI_BUILD_VMGENID_FILE,
+                                       ACPI_BUILD_TABLE_FILE,
+                                       table_data,
+                                       table_data->data,
+                                       sizeof(uint32_t));
+    } else {
+        vm_gid_physical_address = 0;
+    }
+
+    ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml),
+                      ssdt_acpi_vm_gid_addr[0], 32, vm_gid_physical_address);
+
     ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml),
                       ssdt_mctrl_nr_slots[0], 32, nr_mem);
 
@@ -1498,6 +1515,7 @@ struct AcpiBuildTables {
     GArray *table_data;
     GArray *rsdp;
     GArray *tcpalog;
+    GArray *vmgenid;
     GArray *linker;
 } AcpiBuildTables;
 
@@ -1506,6 +1524,7 @@ static inline void acpi_build_tables_init(AcpiBuildTables *tables)
     tables->rsdp = g_array_new(false, true /* clear */, 1);
     tables->table_data = g_array_new(false, true /* clear */, 1);
     tables->tcpalog = g_array_new(false, true /* clear */, 1);
+    tables->vmgenid = g_array_new(false, true /* clear */, 1);
     tables->linker = bios_linker_loader_init();
 }
 
@@ -1516,6 +1535,7 @@ static inline void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
     g_array_free(tables->rsdp, mfre);
     g_array_free(tables->table_data, true);
     g_array_free(tables->tcpalog, mfre);
+    g_array_free(tables->vmgenid, mfre);
 }
 
 typedef
@@ -1804,6 +1824,11 @@ void acpi_setup(PcGuestInfo *guest_info)
     fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
                     tables.tcpalog->data, acpi_data_len(tables.tcpalog));
 
+    /* Add a 4K-bytes fw cfg file which stores the VM generation id. */
+    g_array_set_size(tables.vmgenid, 0x1000);
+    fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_VMGENID_FILE,
+                    tables.vmgenid->data, tables.vmgenid->len);
+
     /*
      * RSDP is small so it's easy to keep it immutable, no need to
      * bother with ROM blobs.
diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
index a611e07..5a72820 100644
--- a/hw/i386/acpi-dsdt.dsl
+++ b/hw/i386/acpi-dsdt.dsl
@@ -306,7 +306,9 @@ DefinitionBlock (
     Scope(\_GPE) {
         Name(_HID, "ACPI0006")
 
-        Method(_L00) {
+        External(\_SB.VMGI, DeviceObj)
+        Method(_E00) {
+            Notify(\_SB.VMGI, 0x80)
         }
         Method(_E01) {
             // PCI hotplug event
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index c7af6aa..a61d6b0 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -59,6 +59,7 @@
 #include "hw/pci/pci_host.h"
 #include "acpi-build.h"
 #include "hw/mem/pc-dimm.h"
+#include "hw/misc/vmgenid.h"
 #include "trace.h"
 #include "qapi/visitor.h"
 #include "qapi-visit.h"
@@ -1357,6 +1358,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
     int i;
     DriveInfo *fd[MAX_FD];
     DeviceState *hpet = NULL;
+    DeviceState *vmgenid;
     int pit_isa_irq = 0;
     qemu_irq pit_alt_irq = NULL;
     qemu_irq rtc_irq = NULL;
@@ -1455,6 +1457,12 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
         fd[i] = drive_get(IF_FLOPPY, 0, i);
     }
     *floppy = fdctrl_init_isa(isa_bus, fd);
+
+    vmgenid = qdev_try_create(NULL, VMGENID_DEVICE);
+    if (vmgenid) {
+        qdev_init_nofail(vmgenid);
+        sysbus_mmio_map(SYS_BUS_DEVICE(vmgenid), 0, VMGENID_BASE_ADDRESS);
+    }
 }
 
 void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus)
diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
index e1cee5d..acc6e8d 100644
--- a/hw/i386/q35-acpi-dsdt.dsl
+++ b/hw/i386/q35-acpi-dsdt.dsl
@@ -414,7 +414,10 @@ DefinitionBlock (
     Scope(\_GPE) {
         Name(_HID, "ACPI0006")
 
-        Method(_L00) {
+        External(\_SB.VMGI, DeviceObj)
+        Method(_E00)
+        {
+            Notify(\_SB.VMGI, 0x80)
         }
         Method(_L01) {
         }
diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
index 1e3baae..9c7de2c 100644
--- a/hw/i386/ssdt-misc.dsl
+++ b/hw/i386/ssdt-misc.dsl
@@ -13,6 +13,7 @@
  * with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "hw/acpi/pc-hotplug.h"
+#include "hw/misc/vmgenid.h"
 
 ACPI_EXTRACT_ALL_CODE ssdp_misc_aml
 
@@ -119,4 +120,46 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
             }
         }
     }
+
+    Scope(\_SB) {
+        Device(VMGI) {
+            Name(_HID, "QEMU0002")
+            Name(_CID, "VM_Gen_Counter")
+            Name(_DDN, "VM_Gen_Counter")
+
+            ACPI_EXTRACT_NAME_DWORD_CONST ssdt_acpi_vm_gid_addr
+            Name(VGIA, 0x12345678)
+
+            OperationRegion(OPRG, SystemMemory,
+                VMGENID_BASE_ADDRESS, VMGENID_BASE_ADDR_LEN)
+            Field(OPRG, DWordAcc, NoLock, Preserve) {
+                PHYA, 32
+            }
+
+            Name(_CRS, ResourceTemplate() {
+                Memory32Fixed(ReadOnly,
+                    VMGENID_BASE_ADDRESS, VMGENID_BASE_ADDR_LEN)
+            })
+
+            Method(_INI, 0, NotSerialized) {
+                 Store(VGIA, PHYA)
+            }
+
+            Method(_STA, 0, NotSerialized) {
+                Store(VGIA, Local0)
+                If (LEqual(Local0, Zero)) {
+                    Return (0x00)
+                } Else {
+                    Return (0x0F)
+                }
+            }
+
+            Method(ADDR, 0, Serialized) {
+                Store(Package(2) { }, Local0)
+                Store(VGIA, Index(Local0, 0))
+                Store(0x0000, Index(Local0, 1))
+                return (Local0)
+            }
+        }
+    }
 }
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index 530b074..3a012fa 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -678,6 +678,7 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data)
     hc->plug = ich9_device_plug_cb;
     hc->unplug_request = ich9_device_unplug_request_cb;
     adevc->ospm_status = ich9_pm_ospm_status;
+    adevc->vm_generation_id_changed = ich9_vm_generation_id_changed;
 }
 
 static const TypeInfo ich9_lpc_info = {
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 029a56f..e047aea 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -41,3 +41,4 @@ obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 
 obj-$(CONFIG_PVPANIC) += pvpanic.o
 obj-$(CONFIG_EDU) += edu.o
+obj-$(CONFIG_VMGENID) += vmgenid.o
diff --git a/hw/misc/vmgenid.c b/hw/misc/vmgenid.c
new file mode 100644
index 0000000..ff09243
--- /dev/null
+++ b/hw/misc/vmgenid.c
@@ -0,0 +1,131 @@
+/*
+ *  Virtual Machine Generation ID Device
+ *
+ *  Copyright (C) 2014 Red Hat Inc.
+ *
+ *  Authors: Gal Hammer <ghammer@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "hw/i386/pc.h"
+#include "hw/sysbus.h"
+#include "hw/misc/vmgenid.h"
+#include "hw/acpi/acpi_dev_interface.h"
+
+#define PROPERTY_UUID "uuid"
+
+#define VMGENID(obj) OBJECT_CHECK(VmGenIdState, (obj), VMGENID_DEVICE)
+
+typedef struct VmGenIdState {
+    SysBusDevice parent_obj;
+    MemoryRegion iomem;
+    hwaddr guid_physical_addr;
+    uint8_t guid[16];
+    bool guid_set;
+} VmGenIdState;
+
+bool vm_generation_id_set(void)
+{
+    Object *obj = object_resolve_path_type("", VMGENID_DEVICE, NULL);
+    VmGenIdState *s = VMGENID(obj);
+
+    if (!obj) {
+        return false;
+    }
+    return s->guid_set;
+}
+
+static void vmgenid_update_guest(VmGenIdState *s)
+{
+    Object *acpi_obj;
+
+    if (s->guid_physical_addr) {
+        cpu_physical_memory_write(s->guid_physical_addr, &s->guid,
+                                  sizeof(s->guid));
+
+        acpi_obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, NULL);
+        if (acpi_obj) {
+            AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(acpi_obj);
+            AcpiDeviceIf *adev = ACPI_DEVICE_IF(acpi_obj);
+
+            adevc->vm_generation_id_changed(adev);
+        }
+    }
+}
+
+static uint64_t vmgenid_ram_read(void *opaque, hwaddr addr,
+                                 unsigned size)
+{
+    VmGenIdState *s = VMGENID(opaque);
+
+    return s->guid_physical_addr;
+}
+
+static void vmgenid_ram_write(void *opaque, hwaddr addr, uint64_t value,
+                              unsigned size)
+{
+    VmGenIdState *s = VMGENID(opaque);
+
+    s->guid_physical_addr = value;
+    vmgenid_update_guest(s);
+}
+
+static const MemoryRegionOps vmgenid_ram_ops = {
+    .read = vmgenid_ram_read,
+    .write = vmgenid_ram_write,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void vmgenid_set_uuid(Object *obj, const char *value, Error **errp)
+{
+    VmGenIdState *s = VMGENID(obj);
+
+    if (qemu_uuid_parse(value, s->guid) < 0) {
+        error_setg(errp, "Fail to parse UUID string.");
+        return;
+    }
+
+    s->guid_set = true;
+    vmgenid_update_guest(s);
+}
+
+static void vmgenid_init(Object *obj)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    VmGenIdState *s = VMGENID(obj);
+
+    memory_region_init_io(&s->iomem, obj, &vmgenid_ram_ops, s, "vgid",
+                          VMGENID_BASE_ADDR_LEN);
+    sysbus_init_mmio(sbd, &s->iomem);
+
+    object_property_add_str(obj, PROPERTY_UUID, NULL, vmgenid_set_uuid, NULL);
+}
+
+static void vmgenid_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+}
+
+static const TypeInfo vmgenid_device_info = {
+    .name          = VMGENID_DEVICE,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(VmGenIdState),
+    .instance_init = vmgenid_init,
+    .class_init    = vmgenid_class_init,
+};
+
+static void vmgenid_register_types(void)
+{
+    type_register_static(&vmgenid_device_info);
+}
+
+type_init(vmgenid_register_types)
diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h
index 1f678b4..9373b4d 100644
--- a/include/hw/acpi/acpi.h
+++ b/include/hw/acpi/acpi.h
@@ -185,4 +185,6 @@ unsigned acpi_table_len(void *current);
 void acpi_table_add(const QemuOpts *opts, Error **errp);
 void acpi_table_add_builtin(const QemuOpts *opts, Error **errp);
 
+void acpi_vm_generation_id_changed(ACPIREGS *acpi_regs, qemu_irq irq);
+
 #endif /* !QEMU_HW_ACPI_H */
diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h
index f245f8d..757ce60 100644
--- a/include/hw/acpi/acpi_dev_interface.h
+++ b/include/hw/acpi/acpi_dev_interface.h
@@ -28,6 +28,9 @@ typedef struct AcpiDeviceIf {
  * ospm_status: returns status of ACPI device objects, reported
  *              via _OST method if device supports it.
  *
+ * vm_generation_id_changed: notify the guest that it generation
+ *                           id was changed.
+ *
  * Interface is designed for providing unified interface
  * to generic ACPI functionality that could be used without
  * knowledge about internals of actual device that implements
@@ -39,5 +42,6 @@ typedef struct AcpiDeviceIfClass {
 
     /* <public> */
     void (*ospm_status)(AcpiDeviceIf *adev, ACPIOSTInfoList ***list);
+    void (*vm_generation_id_changed)(AcpiDeviceIf *adev);
 } AcpiDeviceIfClass;
 #endif
diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
index 12d7a7a..fab2c0f 100644
--- a/include/hw/acpi/ich9.h
+++ b/include/hw/acpi/ich9.h
@@ -65,4 +65,6 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp);
 void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp);
 
 void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list);
+
+void ich9_vm_generation_id_changed(AcpiDeviceIf *adev);
 #endif /* HW_ACPI_ICH9_H */
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 69d9cf8..7e7668b 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -298,6 +298,9 @@ void pc_system_firmware_init(MemoryRegion *rom_memory,
 /* pvpanic.c */
 uint16_t pvpanic_port(void);
 
+/* vmgenid.c */
+bool vm_generation_id_set(void);
+
 /* e820 types */
 #define E820_RAM        1
 #define E820_RESERVED   2
diff --git a/include/hw/misc/vmgenid.h b/include/hw/misc/vmgenid.h
new file mode 100644
index 0000000..7b9a2b2
--- /dev/null
+++ b/include/hw/misc/vmgenid.h
@@ -0,0 +1,21 @@
+/*
+ *  Virtual Machine Generation ID Device
+ *
+ *  Copyright (C) 2014 Red Hat Inc.
+ *
+ *  Authors: Gal Hammer <ghammer@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef HW_MISC_VMGENID_H
+#define HW_MISC_VMGENID_H
+
+#define VMGENID_DEVICE "vmgenid"
+
+#define VMGENID_BASE_ADDRESS    0xfedf0000
+#define VMGENID_BASE_ADDR_LEN   4
+
+#endif
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH V12 3/3] tests: add a unit test for the vmgenid device.
  2015-02-10 15:02 [Qemu-devel] [PATCH V12 0/3] Virtual Machine Generation ID Gal Hammer
  2015-02-10 15:02 ` [Qemu-devel] [PATCH V12 1/3] docs: vm generation id device's description Gal Hammer
  2015-02-10 15:02 ` [Qemu-devel] [PATCH V12 2/3] i386: Add a Virtual Machine Generation ID device Gal Hammer
@ 2015-02-10 15:02 ` Gal Hammer
  2 siblings, 0 replies; 4+ messages in thread
From: Gal Hammer @ 2015-02-10 15:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gal Hammer

Signed-off-by: Gal Hammer <ghammer@redhat.com>

---
 tests/Makefile       |  2 ++
 tests/vmgenid-test.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)
 create mode 100644 tests/vmgenid-test.c

diff --git a/tests/Makefile b/tests/Makefile
index d5df168..6b600c3 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -70,6 +70,7 @@ check-unit-y += tests/test-qemu-opts$(EXESUF)
 gcov-files-test-qemu-opts-y = qom/test-qemu-opts.c
 check-unit-y += tests/test-write-threshold$(EXESUF)
 gcov-files-test-write-threshold-y = block/write-threshold.c
+check-qtest-i386-y += tests/vmgenid-test$(EXESUF)
 
 check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 
@@ -363,6 +364,7 @@ tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o qemu-timer.o
 tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
 tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o libqemuutil.a libqemustub.a
 tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o $(block-obj-y) libqemuutil.a libqemustub.a
+tests/vmgenid-test$(EXESUF): tests/vmgenid-test.o
 
 ifeq ($(CONFIG_POSIX),y)
 LIBS += -lutil
diff --git a/tests/vmgenid-test.c b/tests/vmgenid-test.c
new file mode 100644
index 0000000..d9c3e29
--- /dev/null
+++ b/tests/vmgenid-test.c
@@ -0,0 +1,48 @@
+/*
+ * QTest testcase for VM Generation ID
+ *
+ * Copyright (c) 2014 Red Hat, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <string.h>
+#include "libqtest.h"
+
+static void vmgenid_test(void)
+{
+    static const uint8_t expected[16] = {
+        0x32, 0x4e, 0x6e, 0xaf, 0xd1, 0xd1, 0x4b, 0xf6,
+        0xbf, 0x41, 0xb9, 0xbb, 0x6c, 0x91, 0xfb, 0x87
+    };
+    uint8_t guid[16];
+    uint32_t i;
+
+    // Emulate the ACPI _INI method (tells the device where the physical
+    // memory was "allocated".
+    writel(0xfedf0000, 0x0001f000);
+   
+    // Skip the ACPI ADDR method and read the GUID directly from memory.
+    for (i = 0; i < 16; i++) {
+        guid[i] = readb(0x0001f000 + i);
+    } 
+
+    g_assert_cmpuint(sizeof(guid), ==, sizeof(expected));
+    g_assert(memcmp(guid, expected, sizeof(guid)) == 0);
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+
+    g_test_init(&argc, &argv, NULL);
+    qtest_add_func("/vmgenid/vmgenid", vmgenid_test);
+
+    qtest_start("-global vmgenid.uuid=324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87");
+    ret = g_test_run();
+
+    qtest_end();
+
+    return ret;
+}
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-02-10 15:11 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-10 15:02 [Qemu-devel] [PATCH V12 0/3] Virtual Machine Generation ID Gal Hammer
2015-02-10 15:02 ` [Qemu-devel] [PATCH V12 1/3] docs: vm generation id device's description Gal Hammer
2015-02-10 15:02 ` [Qemu-devel] [PATCH V12 2/3] i386: Add a Virtual Machine Generation ID device Gal Hammer
2015-02-10 15:02 ` [Qemu-devel] [PATCH V12 3/3] tests: add a unit test for the vmgenid device Gal Hammer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).