This patch implements the "ACPI device, control methods" section of "docs/vmgenid.txt", with dynamic AML generation.
A small portion of this patch was inspired by Gal Hammer's [PATCH V15 4/5] i386: add a Virtual Machine Generation ID device http://thread.gmane.org/gmane.comp.emulators.qemu/332451/focus=332454 TODO: the ACPICA instance that is built into the Linux kernel warns about the fact that both _L04 and _E04 are provided by GPE 04, when the code in this patch is active. Therefore this patch should also conditionalize _L04 (ATM in "hw/i386/acpi-dsdt.dsl" and "hw/i386/q35-acpi-dsdt.dsl"), so that they are only generated when VMGENID is *not* active. Cc: Paolo Bonzini <pbonz...@redhat.com> Cc: Gal Hammer <gham...@redhat.com> Cc: Igor Mammedov <imamm...@redhat.com> Cc: "Michael S. Tsirkin" <m...@redhat.com> Signed-off-by: Laszlo Ersek <ler...@redhat.com> --- hw/i386/acpi-build.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index a742f25..67be94a 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1126,6 +1126,85 @@ build_ssdt(GArray *table_data, GArray *linker, aml_append(ssdt, scope); } + if (true /* lersek: misc->vmgenid_iobase */) { + unsigned adbp_offset; + size_t genid_incr; + + scope = aml_scope("\\_SB"); + dev = aml_device("VMGI"); + + aml_append(dev, aml_name_decl("_CID", aml_string("VM_Gen_Counter"))); + aml_append(dev, aml_name_decl("_DDN", aml_string("VM_Gen_Counter"))); + aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0002"))); + + aml_append(dev, aml_name_decl("_STA", aml_int(0xF))); + + method = aml_method_serialized("ADDR", 0, true); + + aml_append(method, + aml_data_table_region("TBLR", + aml_string("UEFI"), + aml_string("%s", ACPI_BUILD_APPNAME6), + aml_string("QEMUPARM"))); + field = aml_field("TBLR", AML_ANY_ACC, AML_PRESERVE); + adbp_offset = offsetof (AcpiQemuParamTable, vmgenid_addr_base_ptr); + /* Offset() before ADBP, expressed in bits */ + aml_append(field, aml_reserved_field(adbp_offset * 8)); + aml_append(field, aml_named_field("ADBP", 64)); + aml_append(method, field); + + aml_append(method, + aml_operation_region("VMGR", AML_SYSTEM_IO, + 0x512 /* lersek: misc->vmgenid_iobase */, + 9)); + field = aml_field("VMGR", AML_DWORD_ACC, AML_PRESERVE); + aml_append(field, aml_named_field("PTLO", 32)); + aml_append(field, aml_named_field("PTHI", 32)); + aml_append(field, aml_access_field(AML_BYTE_ACC)); + aml_append(field, aml_named_field("DONE", 8)); + aml_append(method, field); + + aml_append(method, aml_name_decl("RESU", aml_buffer(8, NULL))); + aml_append(method, + aml_create_qword_field(aml_name("RESU"), aml_int(0), + "ADFU")); + aml_append(method, + aml_create_dword_field(aml_name("RESU"), aml_int(0), + "ADLO")); + aml_append(method, + aml_create_dword_field(aml_name("RESU"), aml_int(4), + "ADHI")); + + /* + * Offset increment from the end of the parameter table (ie. where ADBP + * points to) until the generation ID field, skipping over the "OVMF + * SDT Header probe suppressor" and "VMGenID alignment padding" fields + * in the blob. + */ + genid_incr = VM_GENERATION_ID_OFFSET - sizeof(AcpiQemuParamTable); + aml_append(method, aml_store(aml_add(aml_name("ADBP"), + aml_int(genid_incr)), + aml_name("ADFU"))); + aml_append(method, aml_store(aml_name("ADLO"), aml_name("PTLO"))); + aml_append(method, aml_store(aml_name("ADHI"), aml_name("PTHI"))); + aml_append(method, aml_store(aml_int(0), aml_name("DONE"))); + + pkg = aml_package(2); + aml_append(pkg, aml_name("ADLO")); + aml_append(pkg, aml_name("ADHI")); + aml_append(method, aml_return(pkg)); + + aml_append(dev, method); + aml_append(scope, dev); + aml_append(ssdt, scope); + + scope = aml_scope("\\_GPE"); + method = aml_method("_E04", 0); + aml_append(method, aml_notify(aml_name("\\_SB.VMGI"), aml_int(0x80))); + aml_append(scope, method); + aml_append(ssdt, scope); + } + sb_scope = aml_scope("\\_SB"); { /* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */ -- 1.8.3.1