[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2/3] i386: Add a Virtual Machine Generation ID devic
From: |
Gal Hammer |
Subject: |
[Qemu-devel] [PATCH 2/3] i386: Add a Virtual Machine Generation ID device |
Date: |
Sun, 16 Nov 2014 12:15:58 +0200 |
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 <address@hidden>
---
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 | 26 +++++++
hw/i386/acpi-dsdt.dsl | 4 +-
hw/i386/acpi-dsdt.hex.generated | 6 +-
hw/i386/pc.c | 8 +++
hw/i386/q35-acpi-dsdt.dsl | 5 +-
hw/i386/q35-acpi-dsdt.hex.generated | 8 +--
hw/i386/ssdt-misc.dsl | 43 ++++++++++++
hw/i386/ssdt-misc.hex.generated | 8 +--
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 ++++++
21 files changed, 286 insertions(+), 13 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 ea991a3..12a9387 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -307,3 +307,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 481a16c..41b6eb6 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 4003b6b..0cfa598 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -250,6 +250,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,
@@ -1061,6 +1062,8 @@ 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;
+ uint32_t vm_gid_offset = 0;
unsigned acpi_cpus = guest_info->apic_id_limit;
int ssdt_start = table_data->len;
uint8_t *ssdt_ptr;
@@ -1089,6 +1092,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, 8, true);
+ bios_linker_loader_add_pointer(linker, ACPI_BUILD_VMGENID_FILE,
+ ACPI_BUILD_TABLE_FILE,
+ table_data,
+ &vm_gid_offset,
+ sizeof(vm_gid_offset));
+ } 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);
@@ -1488,6 +1506,7 @@ struct AcpiBuildTables {
GArray *table_data;
GArray *rsdp;
GArray *tcpalog;
+ GArray *vmgenid;
GArray *linker;
} AcpiBuildTables;
@@ -1496,6 +1515,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();
}
@@ -1506,6 +1526,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
@@ -1784,6 +1805,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 128-bit fw cfg file which stores the VM generation id. */
+ g_array_set_size(tables.vmgenid, 16);
+ 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 559f4b6..10b4afb 100644
--- a/hw/i386/acpi-dsdt.dsl
+++ b/hw/i386/acpi-dsdt.dsl
@@ -307,7 +307,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/acpi-dsdt.hex.generated b/hw/i386/acpi-dsdt.hex.generated
index a21bf41..3fd06d2 100644
--- a/hw/i386/acpi-dsdt.hex.generated
+++ b/hw/i386/acpi-dsdt.hex.generated
@@ -8,7 +8,7 @@ static unsigned char AcpiDsdtAmlCode[] = {
0x0,
0x0,
0x1,
-0x1f,
+0x18,
0x42,
0x58,
0x50,
@@ -32,8 +32,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
0x54,
0x4c,
0x28,
-0x5,
-0x10,
+0x8,
+0x14,
0x20,
0x10,
0x49,
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 1205db8..a5d773e 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"
@@ -1350,6 +1351,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;
@@ -1448,6 +1450,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 054b035..b1d04e2 100644
--- a/hw/i386/q35-acpi-dsdt.dsl
+++ b/hw/i386/q35-acpi-dsdt.dsl
@@ -415,7 +415,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/q35-acpi-dsdt.hex.generated
b/hw/i386/q35-acpi-dsdt.hex.generated
index c9eb4ac..866e648 100644
--- a/hw/i386/q35-acpi-dsdt.hex.generated
+++ b/hw/i386/q35-acpi-dsdt.hex.generated
@@ -8,7 +8,7 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
0x0,
0x0,
0x1,
-0xb7,
+0xac,
0x42,
0x58,
0x50,
@@ -31,9 +31,9 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
0x4e,
0x54,
0x4c,
-0x15,
-0x11,
-0x13,
+0x28,
+0x8,
+0x14,
0x20,
0x10,
0x49,
diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
index 0fd4480..e2d50e4 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
@@ -118,6 +119,48 @@ 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)
+ }
+ }
+ }
+
External(MEMORY_SLOT_NOTIFY_METHOD, MethodObj)
Scope(\_SB.PCI0) {
Device(MEMORY_HOTPLUG_DEVICE) {
diff --git a/hw/i386/ssdt-misc.hex.generated b/hw/i386/ssdt-misc.hex.generated
index ba4268a..f0b7a27 100644
--- a/hw/i386/ssdt-misc.hex.generated
+++ b/hw/i386/ssdt-misc.hex.generated
@@ -26,7 +26,7 @@ static unsigned char ssdp_misc_aml[] = {
0x0,
0x0,
0x1,
-0x8b,
+0x80,
0x42,
0x58,
0x50,
@@ -49,9 +49,9 @@ static unsigned char ssdp_misc_aml[] = {
0x4e,
0x54,
0x4c,
-0x15,
-0x11,
-0x13,
+0x28,
+0x8,
+0x14,
0x20,
0x10,
0x42,
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 979e532..c18b800 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -41,3 +41,4 @@ obj-$(CONFIG_SLAVIO) += slavio_misc.o
obj-$(CONFIG_ZYNQ) += zynq_slcr.o
obj-$(CONFIG_PVPANIC) += pvpanic.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 <address@hidden>
+ *
+ * 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 fe975e6..923e711 100644
--- a/include/hw/acpi/ich9.h
+++ b/include/hw/acpi/ich9.h
@@ -61,4 +61,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 7c3731f..f6fc55c 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -294,6 +294,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 <address@hidden>
+ *
+ * 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
--
1.9.3