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.
The GUID is set using a new "-vmgenid" command line parameter. Signed-off-by: Gal Hammer <gham...@redhat.com> --- hw/i386/acpi-build.c | 23 +++++++++++++++++++++++ hw/i386/ssdt-misc.dsl | 33 +++++++++++++++++++++++++++++++++ qemu-options.hx | 9 +++++++++ vl.c | 11 +++++++++++ 4 files changed, 76 insertions(+) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 816c6d9..838c72c 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -54,6 +54,9 @@ #include "qapi/qmp/qint.h" #include "qom/qom-qobject.h" +extern uint8_t vm_generation_id[16]; +extern bool vm_generation_id_set; + /* These are used to size the ACPI tables for -M pc-i440fx-1.7 and * -M pc-i440fx-2.0. Even if the actual amount of AML generated grows * a little bit, there should be plenty of free space since the DSDT @@ -1051,6 +1054,7 @@ build_ssdt(GArray *table_data, GArray *linker, unsigned acpi_cpus = guest_info->apic_id_limit; int ssdt_start = table_data->len; uint8_t *ssdt_ptr; + uint32_t vm_gid_physical_address; int i; /* The current AML generator can cover the APIC ID range [0..255], @@ -1076,6 +1080,25 @@ 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) { + uint8_t *vm_gid_ptr; + + vm_gid_physical_address = ssdt_start + ssdt_acpi_vm_gid[0]; + vm_gid_ptr = acpi_data_get_ptr(ssdt_ptr, sizeof(ssdp_misc_aml), + ssdt_acpi_vm_gid[0], 16); + memcpy(vm_gid_ptr, vm_generation_id, sizeof(vm_generation_id)); + + bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, + ACPI_BUILD_TABLE_FILE, + table_data, ssdt_ptr + ssdt_acpi_vm_gid_addr[0], + sizeof(uint32_t)); + } else { + vm_gid_physical_address = 0; + } + + ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml), + ssdt_acpi_vm_gid_addr[0], 32, vm_gid_physical_address); + ACPI_BUILD_SET_LE(ssdt_ptr, sizeof(ssdp_misc_aml), ssdt_mctrl_nr_slots[0], 32, nr_mem); diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl index d329b8b..8a001a7 100644 --- a/hw/i386/ssdt-misc.dsl +++ b/hw/i386/ssdt-misc.dsl @@ -118,6 +118,39 @@ 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) + + ACPI_EXTRACT_NAME_BUFFER16 ssdt_acpi_vm_gid + Name(VGID, Buffer(16) { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) + + 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_HOPTLUG_DEVICE) { diff --git a/qemu-options.hx b/qemu-options.hx index 96516c1..a6d475c 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -369,6 +369,15 @@ STEXI Set system UUID. ETEXI +DEF("vmgenid", HAS_ARG, QEMU_OPTION_vmgenid, + "-vmgenid %08x-%04x-%04x-%04x-%012x\n" + " specify the virtual machine generation ID\n", QEMU_ARCH_I386) +STEXI +@item -uuid @var{uuid} +@findex -uuid +Set the virtual machine generation ID. +ETEXI + STEXI @end table ETEXI diff --git a/vl.c b/vl.c index a8029d5..a5ef0d5 100644 --- a/vl.c +++ b/vl.c @@ -203,6 +203,9 @@ NodeInfo numa_info[MAX_NODES]; uint8_t qemu_uuid[16]; bool qemu_uuid_set; +uint8_t vm_generation_id[16]; +bool vm_generation_id_set; + static QEMUBootSetHandler *boot_set_handler; static void *boot_set_opaque; @@ -3784,6 +3787,14 @@ int main(int argc, char **argv, char **envp) } qemu_uuid_set = true; break; + case QEMU_OPTION_vmgenid: + if(qemu_uuid_parse(optarg, vm_generation_id) < 0) { + fprintf(stderr, "Fail to parse UUID string." + " Wrong format.\n"); + exit(1); + } + vm_generation_id_set = true; + break; case QEMU_OPTION_option_rom: if (nb_option_roms >= MAX_OPTION_ROMS) { fprintf(stderr, "Too many option ROMs\n"); -- 1.9.3