* [Qemu-devel] [PATCH V6 0/2] Virtual Machine Generation ID @ 2014-10-19 13:43 Gal Hammer 2014-10-19 13:43 ` [Qemu-devel] [PATCH 1/2] i386: Add a Virtual Machine Generation ID device Gal Hammer 2014-10-19 13:43 ` [Qemu-devel] [PATCH 2/2] tests: update acpi tables after adding the vmgenid device Gal Hammer 0 siblings, 2 replies; 6+ messages in thread From: Gal Hammer @ 2014-10-19 13:43 UTC (permalink / raw) To: qemu-devel; +Cc: Gal Hammer, pbonzini, mst Hi, A two parts patch to add a QEmu support for Microsoft's Virtual Machine Generation ID device. The first one is the ACPI tables changes and the actual device and the second patch updates the tests' ACPI tables. Your comment are welcomed. Thanks, Gal. V6 - 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. V5 - include the pre-compiled ASL file - remove an empty line at end of files. V4 - Move device's description to SSDT table (dynamic). V3 - Fix a typo in error message string. - Move device's description from DSDT back to SSDT table. V2 - Remove "-uuid" command line parameter. - Move device's description from SSDT to DSDT table. - Add new "vmgenid" sysbus device. Gal Hammer (2): i386: Add a Virtual Machine Generation ID device tests: update acpi tables after adding the vmgenid device 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 | 8 +++ 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 | 36 +++++++++++ hw/i386/ssdt-misc.hex.generated | 8 +-- hw/isa/lpc_ich9.c | 1 + hw/misc/Makefile.objs | 1 + hw/misc/vmgenid.c | 116 +++++++++++++++++++++++++++++++++++ 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/acpi-test-data/pc/DSDT | Bin 2807 -> 2820 bytes tests/acpi-test-data/pc/SSDT | Bin 3065 -> 3239 bytes tests/acpi-test-data/q35/DSDT | Bin 7397 -> 7410 bytes tests/acpi-test-data/q35/SSDT | Bin 1346 -> 1520 bytes 25 files changed, 246 insertions(+), 13 deletions(-) create mode 100644 hw/misc/vmgenid.c create mode 100644 include/hw/misc/vmgenid.h -- 1.9.3 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH 1/2] i386: Add a Virtual Machine Generation ID device 2014-10-19 13:43 [Qemu-devel] [PATCH V6 0/2] Virtual Machine Generation ID Gal Hammer @ 2014-10-19 13:43 ` Gal Hammer 2014-10-19 15:14 ` Michael S. Tsirkin 2014-10-19 13:43 ` [Qemu-devel] [PATCH 2/2] tests: update acpi tables after adding the vmgenid device Gal Hammer 1 sibling, 1 reply; 6+ messages in thread From: Gal Hammer @ 2014-10-19 13:43 UTC (permalink / raw) To: qemu-devel; +Cc: Gal Hammer, pbonzini, mst 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 | 8 +++ 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 | 36 +++++++++++ hw/i386/ssdt-misc.hex.generated | 8 +-- hw/isa/lpc_ich9.c | 1 + hw/misc/Makefile.objs | 1 + hw/misc/vmgenid.c | 116 +++++++++++++++++++++++++++++++++++ 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, 246 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 a7368fb..a01c980 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 */ @@ -680,3 +682,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 7b14bbb..5501c0e 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -316,3 +316,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 0bfa814..ad0ef68 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -580,6 +580,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), @@ -617,6 +624,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 00be4bb..27d0494 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -42,6 +42,7 @@ #include "hw/acpi/memory_hotplug.h" #include "sysemu/tpm.h" #include "hw/acpi/tpm.h" +#include "hw/misc/vmgenid.h" /* Supported chipsets: */ #include "hw/acpi/piix4.h" @@ -96,6 +97,7 @@ typedef struct AcpiMiscInfo { const unsigned char *dsdt_code; unsigned dsdt_size; uint16_t pvpanic_port; + bool vm_generation_id_set; } AcpiMiscInfo; typedef struct AcpiBuildPciBusHotplugState { @@ -216,6 +218,7 @@ static void acpi_get_misc_info(AcpiMiscInfo *info) info->has_hpet = hpet_find(); info->has_tpm = tpm_find(); info->pvpanic_port = pvpanic_port(); + info->vm_generation_id_set = vm_generation_id_set(); } static void acpi_get_pci_info(PcPciInfo *info) @@ -1088,6 +1091,11 @@ 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 (!misc->vm_generation_id_set) { + ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml), + ssdt_acpi_vm_gid_addr[0], 32, 0); + } + ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml), ssdt_mctrl_nr_slots[0], 32, nr_mem); 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 d045e8b..95ec233 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" @@ -1361,6 +1362,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; @@ -1459,6 +1461,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..6ae09fb 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,41 @@ 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, VMGENID_BASE_ADDRESS) + + OperationRegion(VGID, SystemMemory, + VMGENID_BASE_ADDRESS, VMGENID_BASE_ADDR_LEN) + + Name(_CRS, ResourceTemplate() { + Memory32Fixed(ReadOnly, + VMGENID_BASE_ADDRESS, VMGENID_BASE_ADDR_LEN) + }) + + 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..01aacd4 --- /dev/null +++ b/hw/misc/vmgenid.c @@ -0,0 +1,116 @@ +/* + * 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; + 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 uint64_t vmgenid_ram_read(void *opaque, hwaddr addr, + unsigned size) +{ + VmGenIdState *s = VMGENID(opaque); + uint64_t value; + + memcpy(&value, s->guid + addr, size); + return value; +} + +static const MemoryRegionOps vmgenid_ram_ops = { + .read = vmgenid_ram_read, + .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); + Object *acpi_obj; + bool first_set = !s->guid_set; + + if (qemu_uuid_parse(value, s->guid) < 0) { + error_setg(errp, "Fail to parse UUID string."); + return; + } + s->guid_set = true; + + /* Skip the acpi notification when setting the vm generation id for the + * first time. This is done because in a q35 machine the gpe register is + * allocated after the device is initialized. */ + if (!first_set) { + 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 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", 16); + 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 7e42448..3b4eed5 100644 --- a/include/hw/acpi/ich9.h +++ b/include/hw/acpi/ich9.h @@ -62,4 +62,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 1c2602e..87912b2 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -290,6 +290,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..3d44421 --- /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 16 + +#endif -- 1.9.3 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] i386: Add a Virtual Machine Generation ID device 2014-10-19 13:43 ` [Qemu-devel] [PATCH 1/2] i386: Add a Virtual Machine Generation ID device Gal Hammer @ 2014-10-19 15:14 ` Michael S. Tsirkin 2014-10-20 5:57 ` Gal Hammer 0 siblings, 1 reply; 6+ messages in thread From: Michael S. Tsirkin @ 2014-10-19 15:14 UTC (permalink / raw) To: Gal Hammer; +Cc: pbonzini, qemu-devel On Sun, Oct 19, 2014 at 04:43:07PM +0300, Gal Hammer wrote: > 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 | 8 +++ > 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 | 36 +++++++++++ > hw/i386/ssdt-misc.hex.generated | 8 +-- > hw/isa/lpc_ich9.c | 1 + > hw/misc/Makefile.objs | 1 + > hw/misc/vmgenid.c | 116 +++++++++++++++++++++++++++++++++++ > 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, 246 insertions(+), 13 deletions(-) > create mode 100644 hw/misc/vmgenid.c > create mode 100644 include/hw/misc/vmgenid.h Please document the host/guest API. It seems that you are using a hard-coded hardware address, and using up a GPE. > > 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 a7368fb..a01c980 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 */ > @@ -680,3 +682,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 7b14bbb..5501c0e 100644 > --- a/hw/acpi/ich9.c > +++ b/hw/acpi/ich9.c > @@ -316,3 +316,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 0bfa814..ad0ef68 100644 > --- a/hw/acpi/piix4.c > +++ b/hw/acpi/piix4.c > @@ -580,6 +580,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), > @@ -617,6 +624,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 00be4bb..27d0494 100644 > --- a/hw/i386/acpi-build.c > +++ b/hw/i386/acpi-build.c > @@ -42,6 +42,7 @@ > #include "hw/acpi/memory_hotplug.h" > #include "sysemu/tpm.h" > #include "hw/acpi/tpm.h" > +#include "hw/misc/vmgenid.h" > > /* Supported chipsets: */ > #include "hw/acpi/piix4.h" > @@ -96,6 +97,7 @@ typedef struct AcpiMiscInfo { > const unsigned char *dsdt_code; > unsigned dsdt_size; > uint16_t pvpanic_port; > + bool vm_generation_id_set; > } AcpiMiscInfo; > > typedef struct AcpiBuildPciBusHotplugState { > @@ -216,6 +218,7 @@ static void acpi_get_misc_info(AcpiMiscInfo *info) > info->has_hpet = hpet_find(); > info->has_tpm = tpm_find(); > info->pvpanic_port = pvpanic_port(); > + info->vm_generation_id_set = vm_generation_id_set(); > } > > static void acpi_get_pci_info(PcPciInfo *info) > @@ -1088,6 +1091,11 @@ 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 (!misc->vm_generation_id_set) { > + ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml), > + ssdt_acpi_vm_gid_addr[0], 32, 0); > + } > + > ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml), > ssdt_mctrl_nr_slots[0], 32, nr_mem); > > 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 d045e8b..95ec233 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" > > @@ -1361,6 +1362,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; > @@ -1459,6 +1461,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..6ae09fb 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,41 @@ 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, VMGENID_BASE_ADDRESS) > + > + OperationRegion(VGID, SystemMemory, > + VMGENID_BASE_ADDRESS, VMGENID_BASE_ADDR_LEN) > + > + Name(_CRS, ResourceTemplate() { > + Memory32Fixed(ReadOnly, > + VMGENID_BASE_ADDRESS, VMGENID_BASE_ADDR_LEN) > + }) > + > + 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..01aacd4 > --- /dev/null > +++ b/hw/misc/vmgenid.c > @@ -0,0 +1,116 @@ > +/* > + * 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; > + 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 uint64_t vmgenid_ram_read(void *opaque, hwaddr addr, > + unsigned size) > +{ > + VmGenIdState *s = VMGENID(opaque); > + uint64_t value; > + > + memcpy(&value, s->guid + addr, size); > + return value; > +} > + > +static const MemoryRegionOps vmgenid_ram_ops = { > + .read = vmgenid_ram_read, > + .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); > + Object *acpi_obj; > + bool first_set = !s->guid_set; > + > + if (qemu_uuid_parse(value, s->guid) < 0) { > + error_setg(errp, "Fail to parse UUID string."); > + return; > + } > + s->guid_set = true; > + > + /* Skip the acpi notification when setting the vm generation id for the > + * first time. This is done because in a q35 machine the gpe register is > + * allocated after the device is initialized. */ > + if (!first_set) { > + 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 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", 16); > + sysbus_init_mmio(sbd, &s->iomem); This will cause an exit on each access to the GID. I'm guessing this is too expensive. > + > + 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 7e42448..3b4eed5 100644 > --- a/include/hw/acpi/ich9.h > +++ b/include/hw/acpi/ich9.h > @@ -62,4 +62,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 1c2602e..87912b2 100644 > --- a/include/hw/i386/pc.h > +++ b/include/hw/i386/pc.h > @@ -290,6 +290,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..3d44421 > --- /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 16 > + > +#endif > -- > 1.9.3 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] i386: Add a Virtual Machine Generation ID device 2014-10-19 15:14 ` Michael S. Tsirkin @ 2014-10-20 5:57 ` Gal Hammer 2014-10-20 7:04 ` Michael S. Tsirkin 0 siblings, 1 reply; 6+ messages in thread From: Gal Hammer @ 2014-10-20 5:57 UTC (permalink / raw) To: Michael S. Tsirkin; +Cc: pbonzini, qemu-devel On 19/10/2014 18:14, Michael S. Tsirkin wrote: > On Sun, Oct 19, 2014 at 04:43:07PM +0300, Gal Hammer wrote: >> 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 | 8 +++ >> 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 | 36 +++++++++++ >> hw/i386/ssdt-misc.hex.generated | 8 +-- >> hw/isa/lpc_ich9.c | 1 + >> hw/misc/Makefile.objs | 1 + >> hw/misc/vmgenid.c | 116 +++++++++++++++++++++++++++++++++++ >> 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, 246 insertions(+), 13 deletions(-) >> create mode 100644 hw/misc/vmgenid.c >> create mode 100644 include/hw/misc/vmgenid.h > > Please document the host/guest API. > It seems that you are using a hard-coded hardware address, > and using up a GPE. I'll add a document file which describes the device's implementation. > > >> >> 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 a7368fb..a01c980 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 */ >> @@ -680,3 +682,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 7b14bbb..5501c0e 100644 >> --- a/hw/acpi/ich9.c >> +++ b/hw/acpi/ich9.c >> @@ -316,3 +316,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 0bfa814..ad0ef68 100644 >> --- a/hw/acpi/piix4.c >> +++ b/hw/acpi/piix4.c >> @@ -580,6 +580,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), >> @@ -617,6 +624,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 00be4bb..27d0494 100644 >> --- a/hw/i386/acpi-build.c >> +++ b/hw/i386/acpi-build.c >> @@ -42,6 +42,7 @@ >> #include "hw/acpi/memory_hotplug.h" >> #include "sysemu/tpm.h" >> #include "hw/acpi/tpm.h" >> +#include "hw/misc/vmgenid.h" >> >> /* Supported chipsets: */ >> #include "hw/acpi/piix4.h" >> @@ -96,6 +97,7 @@ typedef struct AcpiMiscInfo { >> const unsigned char *dsdt_code; >> unsigned dsdt_size; >> uint16_t pvpanic_port; >> + bool vm_generation_id_set; >> } AcpiMiscInfo; >> >> typedef struct AcpiBuildPciBusHotplugState { >> @@ -216,6 +218,7 @@ static void acpi_get_misc_info(AcpiMiscInfo *info) >> info->has_hpet = hpet_find(); >> info->has_tpm = tpm_find(); >> info->pvpanic_port = pvpanic_port(); >> + info->vm_generation_id_set = vm_generation_id_set(); >> } >> >> static void acpi_get_pci_info(PcPciInfo *info) >> @@ -1088,6 +1091,11 @@ 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 (!misc->vm_generation_id_set) { >> + ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml), >> + ssdt_acpi_vm_gid_addr[0], 32, 0); >> + } >> + >> ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml), >> ssdt_mctrl_nr_slots[0], 32, nr_mem); >> >> 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 d045e8b..95ec233 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" >> >> @@ -1361,6 +1362,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; >> @@ -1459,6 +1461,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..6ae09fb 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,41 @@ 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, VMGENID_BASE_ADDRESS) >> + >> + OperationRegion(VGID, SystemMemory, >> + VMGENID_BASE_ADDRESS, VMGENID_BASE_ADDR_LEN) >> + >> + Name(_CRS, ResourceTemplate() { >> + Memory32Fixed(ReadOnly, >> + VMGENID_BASE_ADDRESS, VMGENID_BASE_ADDR_LEN) >> + }) >> + >> + 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..01aacd4 >> --- /dev/null >> +++ b/hw/misc/vmgenid.c >> @@ -0,0 +1,116 @@ >> +/* >> + * 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; >> + 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 uint64_t vmgenid_ram_read(void *opaque, hwaddr addr, >> + unsigned size) >> +{ >> + VmGenIdState *s = VMGENID(opaque); >> + uint64_t value; >> + >> + memcpy(&value, s->guid + addr, size); >> + return value; >> +} >> + >> +static const MemoryRegionOps vmgenid_ram_ops = { >> + .read = vmgenid_ram_read, >> + .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); >> + Object *acpi_obj; >> + bool first_set = !s->guid_set; >> + >> + if (qemu_uuid_parse(value, s->guid) < 0) { >> + error_setg(errp, "Fail to parse UUID string."); >> + return; >> + } >> + s->guid_set = true; >> + >> + /* Skip the acpi notification when setting the vm generation id for the >> + * first time. This is done because in a q35 machine the gpe register is >> + * allocated after the device is initialized. */ >> + if (!first_set) { >> + 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 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", 16); >> + sysbus_init_mmio(sbd, &s->iomem); > > This will cause an exit on each access to the GID. > I'm guessing this is too expensive. Yes, it does cause an exit, but I don't think it is critical because the GID is rarely read by the guest OS. As far as I can tell it is only accessed on reboot and when the GID is changed. Do you prefer that I'll use the cpu_physical_memory_write function? Or do you have a diffrent idea on how to implement it? > > >> + >> + 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 7e42448..3b4eed5 100644 >> --- a/include/hw/acpi/ich9.h >> +++ b/include/hw/acpi/ich9.h >> @@ -62,4 +62,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 1c2602e..87912b2 100644 >> --- a/include/hw/i386/pc.h >> +++ b/include/hw/i386/pc.h >> @@ -290,6 +290,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..3d44421 >> --- /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 16 >> + >> +#endif >> -- >> 1.9.3 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] i386: Add a Virtual Machine Generation ID device 2014-10-20 5:57 ` Gal Hammer @ 2014-10-20 7:04 ` Michael S. Tsirkin 0 siblings, 0 replies; 6+ messages in thread From: Michael S. Tsirkin @ 2014-10-20 7:04 UTC (permalink / raw) To: Gal Hammer; +Cc: pbonzini, qemu-devel On Mon, Oct 20, 2014 at 08:57:05AM +0300, Gal Hammer wrote: > On 19/10/2014 18:14, Michael S. Tsirkin wrote: > >On Sun, Oct 19, 2014 at 04:43:07PM +0300, Gal Hammer wrote: > >>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 | 8 +++ > >> 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 | 36 +++++++++++ > >> hw/i386/ssdt-misc.hex.generated | 8 +-- > >> hw/isa/lpc_ich9.c | 1 + > >> hw/misc/Makefile.objs | 1 + > >> hw/misc/vmgenid.c | 116 +++++++++++++++++++++++++++++++++++ > >> 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, 246 insertions(+), 13 deletions(-) > >> create mode 100644 hw/misc/vmgenid.c > >> create mode 100644 include/hw/misc/vmgenid.h > > > >Please document the host/guest API. > >It seems that you are using a hard-coded hardware address, > >and using up a GPE. > > I'll add a document file which describes the device's implementation. > > > > > > >> > >>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 a7368fb..a01c980 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 */ > >>@@ -680,3 +682,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 7b14bbb..5501c0e 100644 > >>--- a/hw/acpi/ich9.c > >>+++ b/hw/acpi/ich9.c > >>@@ -316,3 +316,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 0bfa814..ad0ef68 100644 > >>--- a/hw/acpi/piix4.c > >>+++ b/hw/acpi/piix4.c > >>@@ -580,6 +580,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), > >>@@ -617,6 +624,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 00be4bb..27d0494 100644 > >>--- a/hw/i386/acpi-build.c > >>+++ b/hw/i386/acpi-build.c > >>@@ -42,6 +42,7 @@ > >> #include "hw/acpi/memory_hotplug.h" > >> #include "sysemu/tpm.h" > >> #include "hw/acpi/tpm.h" > >>+#include "hw/misc/vmgenid.h" > >> > >> /* Supported chipsets: */ > >> #include "hw/acpi/piix4.h" > >>@@ -96,6 +97,7 @@ typedef struct AcpiMiscInfo { > >> const unsigned char *dsdt_code; > >> unsigned dsdt_size; > >> uint16_t pvpanic_port; > >>+ bool vm_generation_id_set; > >> } AcpiMiscInfo; > >> > >> typedef struct AcpiBuildPciBusHotplugState { > >>@@ -216,6 +218,7 @@ static void acpi_get_misc_info(AcpiMiscInfo *info) > >> info->has_hpet = hpet_find(); > >> info->has_tpm = tpm_find(); > >> info->pvpanic_port = pvpanic_port(); > >>+ info->vm_generation_id_set = vm_generation_id_set(); > >> } > >> > >> static void acpi_get_pci_info(PcPciInfo *info) > >>@@ -1088,6 +1091,11 @@ 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 (!misc->vm_generation_id_set) { > >>+ ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml), > >>+ ssdt_acpi_vm_gid_addr[0], 32, 0); > >>+ } > >>+ > >> ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml), > >> ssdt_mctrl_nr_slots[0], 32, nr_mem); > >> > >>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 d045e8b..95ec233 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" > >> > >>@@ -1361,6 +1362,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; > >>@@ -1459,6 +1461,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..6ae09fb 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,41 @@ 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, VMGENID_BASE_ADDRESS) > >>+ > >>+ OperationRegion(VGID, SystemMemory, > >>+ VMGENID_BASE_ADDRESS, VMGENID_BASE_ADDR_LEN) > >>+ > >>+ Name(_CRS, ResourceTemplate() { > >>+ Memory32Fixed(ReadOnly, > >>+ VMGENID_BASE_ADDRESS, VMGENID_BASE_ADDR_LEN) > >>+ }) > >>+ > >>+ 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..01aacd4 > >>--- /dev/null > >>+++ b/hw/misc/vmgenid.c > >>@@ -0,0 +1,116 @@ > >>+/* > >>+ * 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; > >>+ 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 uint64_t vmgenid_ram_read(void *opaque, hwaddr addr, > >>+ unsigned size) > >>+{ > >>+ VmGenIdState *s = VMGENID(opaque); > >>+ uint64_t value; > >>+ > >>+ memcpy(&value, s->guid + addr, size); > >>+ return value; > >>+} > >>+ > >>+static const MemoryRegionOps vmgenid_ram_ops = { > >>+ .read = vmgenid_ram_read, > >>+ .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); > >>+ Object *acpi_obj; > >>+ bool first_set = !s->guid_set; > >>+ > >>+ if (qemu_uuid_parse(value, s->guid) < 0) { > >>+ error_setg(errp, "Fail to parse UUID string."); > >>+ return; > >>+ } > >>+ s->guid_set = true; > >>+ > >>+ /* Skip the acpi notification when setting the vm generation id for the > >>+ * first time. This is done because in a q35 machine the gpe register is > >>+ * allocated after the device is initialized. */ > >>+ if (!first_set) { > >>+ 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 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", 16); > >>+ sysbus_init_mmio(sbd, &s->iomem); > > > >This will cause an exit on each access to the GID. > >I'm guessing this is too expensive. > > Yes, it does cause an exit, but I don't think it is critical because the GID > is rarely read by the guest OS. As far as I can tell it is only accessed on > reboot and when the GID is changed. > > Do you prefer that I'll use the cpu_physical_memory_write function? Or do > you have a diffrent idea on how to implement it? I think you need to get hold of some RAM, and use that. For example, allocate a buffer, pass the address to host in _INI. > > > > > >>+ > >>+ 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 7e42448..3b4eed5 100644 > >>--- a/include/hw/acpi/ich9.h > >>+++ b/include/hw/acpi/ich9.h > >>@@ -62,4 +62,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 1c2602e..87912b2 100644 > >>--- a/include/hw/i386/pc.h > >>+++ b/include/hw/i386/pc.h > >>@@ -290,6 +290,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..3d44421 > >>--- /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 16 > >>+ > >>+#endif > >>-- > >>1.9.3 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [Qemu-devel] [PATCH 2/2] tests: update acpi tables after adding the vmgenid device 2014-10-19 13:43 [Qemu-devel] [PATCH V6 0/2] Virtual Machine Generation ID Gal Hammer 2014-10-19 13:43 ` [Qemu-devel] [PATCH 1/2] i386: Add a Virtual Machine Generation ID device Gal Hammer @ 2014-10-19 13:43 ` Gal Hammer 1 sibling, 0 replies; 6+ messages in thread From: Gal Hammer @ 2014-10-19 13:43 UTC (permalink / raw) To: qemu-devel; +Cc: Gal Hammer, pbonzini, mst --- tests/acpi-test-data/pc/DSDT | Bin 2807 -> 2820 bytes tests/acpi-test-data/pc/SSDT | Bin 3065 -> 3239 bytes tests/acpi-test-data/q35/DSDT | Bin 7397 -> 7410 bytes tests/acpi-test-data/q35/SSDT | Bin 1346 -> 1520 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/acpi-test-data/pc/DSDT b/tests/acpi-test-data/pc/DSDT index d37ec34454e6f3db5e91b777f94e03be67a5f583..8c86b1e39454f611ee25ababe0ef429956ba7562 100644 GIT binary patch delta 65 zcmew^+9Jl~66_Mf!p*?I=(mwef=knhFWx=Cl_TE6(}ma3Il$Avz`%?_L^$5nz<{AG UMlU|tDL%~C-IJ?fvK`k>0P4aI+5i9m delta 52 zcmZn>`!34m66_N4or{5iv0)>Z1ec5}Z@hbeD@VMCrwgy6bAYFTfq@x=2wS|5fdRv0 HZ?2sHWr7Ua diff --git a/tests/acpi-test-data/pc/SSDT b/tests/acpi-test-data/pc/SSDT index eb2d8b698ce6a3a910a05244a3b6cf80bf818fb9..1f72e5736d825ffbf0bc5d55360f4bfe27cc198b 100644 GIT binary patch delta 199 zcmew<zFd+kIM^j*IS&H^BhyB%NXB|!u9)~>r}*e57p^d0cTbLZ4^J1~Kv&;T0|Nsi z299`VAUDi6-aR!h-Z{TCuOzhyDCpwihani|?&%0LmVqI<0myV=0J87@;}QUx5ELvZ z$i>&j36i}3PXI_(GKfgT2ZuN^6zGApB`jc@oWQVzVIj*BE`AXiM;DhMjshVjri22J WY)1kELjgla0wcqcgw08e)42erhcprZ delta 24 fcmZ23`BR)LIM^lRCpQBFWA{d`NXE^AOw+gkVtNN8 diff --git a/tests/acpi-test-data/q35/DSDT b/tests/acpi-test-data/q35/DSDT index 2d2bc4adaf54666fe7864e7f39203411b7c308f7..b45f6065ad6140bd987550cc22ff38b09243188f 100644 GIT binary patch delta 65 zcmaEA`N@*YCD<k8lMDj`<JFB^mNJ_DT=DJ!t{m|mo-VwO&H<hV1_ovfBEs>m1_lgm UF?#XAPVr&B?w(u?ljCLD0C3V0KL7v# delta 52 zcmexl`P7ojCD<k8sSE=Hqv%F1OBop_u6XwVSB`iOPZwTC=KxOw0|PS#5w>_A0|SQ1 HIWlbke7y}n diff --git a/tests/acpi-test-data/q35/SSDT b/tests/acpi-test-data/q35/SSDT index 778b79bf428b5d7602b7b80c9434e38c79718bb2..5ca654bd91354a7ff023b0a380015612d53f5dd6 100644 GIT binary patch delta 199 zcmX@a^?{o!IM^lR11kdq<FSogk&N}eTru&%PVv!AE?i;0?w%a+9-c0|fv&!x1_lO3 z3>@*!KyH|CynAY1ymNkOUP)>ZP|(H24?{4_-P4hW0SKZSfJ_$#Ap8D5E&-qkLBWE8 zTzqYuAj$jx1b}2EgNQ_YaEK#AfgVU(!UDF*2@FdZ7P2hi;un!|ba4sdC=g;|N+<xy Wb|f$`6fkroFfuGj*qp@pfEfT^ZZ%N= delta 24 fcmeyseTa)IIM^k`iIstY(QhMHB;#g5ru)nQRbd8W -- 1.9.3 ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2014-10-20 7:00 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-10-19 13:43 [Qemu-devel] [PATCH V6 0/2] Virtual Machine Generation ID Gal Hammer 2014-10-19 13:43 ` [Qemu-devel] [PATCH 1/2] i386: Add a Virtual Machine Generation ID device Gal Hammer 2014-10-19 15:14 ` Michael S. Tsirkin 2014-10-20 5:57 ` Gal Hammer 2014-10-20 7:04 ` Michael S. Tsirkin 2014-10-19 13:43 ` [Qemu-devel] [PATCH 2/2] tests: update acpi tables after adding 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).