diff mbox

[PULL,02/15] docs: VM Generation ID device description

Message ID 1488435591-17882-3-git-send-email-mst@redhat.com
State New
Headers show

Commit Message

Michael S. Tsirkin March 2, 2017, 6:20 a.m. UTC
From: Ben Warren <ben@skyportsystems.com>

This patch is based off an earlier version by
Gal Hammer (ghammer@redhat.com)

Requirements section, ASCII diagrams and overall help
provided by Laszlo Ersek (lersek@redhat.com)

Signed-off-by: Gal Hammer <ghammer@redhat.com>
Signed-off-by: Ben Warren <ben@skyportsystems.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 docs/specs/vmgenid.txt | 245 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 245 insertions(+)
 create mode 100644 docs/specs/vmgenid.txt

Comments

Marc-André Lureau April 12, 2017, 8:06 p.m. UTC | #1
Hi

On Thu, Mar 2, 2017 at 10:22 AM Michael S. Tsirkin <mst@redhat.com> wrote:

> From: Ben Warren <ben@skyportsystems.com>
>
> This patch is based off an earlier version by
> Gal Hammer (ghammer@redhat.com)
>
> Requirements section, ASCII diagrams and overall help
> provided by Laszlo Ersek (lersek@redhat.com)
>
> Signed-off-by: Gal Hammer <ghammer@redhat.com>
> Signed-off-by: Ben Warren <ben@skyportsystems.com>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> Reviewed-by: Igor Mammedov <imammedo@redhat.com>
> Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
>  docs/specs/vmgenid.txt | 245
> +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 245 insertions(+)
>  create mode 100644 docs/specs/vmgenid.txt
>
> diff --git a/docs/specs/vmgenid.txt b/docs/specs/vmgenid.txt
> new file mode 100644
> index 0000000..aa9f518
> --- /dev/null
> +++ b/docs/specs/vmgenid.txt
> @@ -0,0 +1,245 @@
> +VIRTUAL MACHINE GENERATION ID
> +=============================
> +
> +Copyright (C) 2016 Red Hat, Inc.
> +Copyright (C) 2017 Skyport Systems, Inc.
> +
> +This work is licensed under the terms of the GNU GPL, version 2 or later.
> +See the COPYING file in the top-level directory.
> +
> +===
> +
> +The VM generation ID (vmgenid) device is an emulated device which
> +exposes a 128-bit, cryptographically random, integer value identifier,
> +referred to as a Globally Unique Identifier, or GUID.
> +
> +This allows management applications (e.g. libvirt) to notify the guest
> +operating system when the virtual machine is executed with a different
> +configuration (e.g. snapshot execution or creation from a template).  The
> +guest operating system notices the change, and is then able to react as
> +appropriate by marking its copies of distributed databases as dirty,
> +re-initializing its random number generator etc.
> +
> +
> +Requirements
> +------------
> +
> +These requirements are extracted from the "How to implement virtual
> machine
> +generation ID support in a virtualization platform" section of the
> +specification, dated August 1, 2012.
> +
> +
> +The document may be found on the web at:
> +  http://go.microsoft.com/fwlink/?LinkId=260709
> +
> +R1a. The generation ID shall live in an 8-byte aligned buffer.
> +
> +R1b. The buffer holding the generation ID shall be in guest RAM, ROM, or
> device
> +     MMIO range.
> +
> +R1c. The buffer holding the generation ID shall be kept separate from
> areas
> +     used by the operating system.
> +
> +R1d. The buffer shall not be covered by an AddressRangeMemory or
> +     AddressRangeACPI entry in the E820 or UEFI memory map.
> +
> +R1e. The generation ID shall not live in a page frame that could be
> mapped with
> +     caching disabled. (In other words, regardless of whether the
> generation ID
> +     lives in RAM, ROM or MMIO, it shall only be mapped as cacheable.)
> +
> +R2 to R5. [These AML requirements are isolated well enough in the
> Microsoft
> +          specification for us to simply refer to them here.]
> +
> +R6. The hypervisor shall expose a _HID (hardware identifier) object in the
> +    VMGenId device's scope that is unique to the hypervisor vendor.
> +
> +
> +QEMU Implementation
> +-------------------
> +
> +The above-mentioned specification does not dictate which ACPI descriptor
> table
> +will contain the VM Generation ID device.  Other implementations (Hyper-V
> and
> +Xen) put it in the main descriptor table (Differentiated System
> Description
> +Table or DSDT).  For ease of debugging and implementation, we have
> decided to
> +put it in its own Secondary System Description Table, or SSDT.
> +
> +The following is a dump of the contents from a running system:
> +
> +# iasl -p ./SSDT -d /sys/firmware/acpi/tables/SSDT
> +
> +Intel ACPI Component Architecture
> +ASL+ Optimizing Compiler version 20150717-64
> +Copyright (c) 2000 - 2015 Intel Corporation
> +
> +Reading ACPI table from file /sys/firmware/acpi/tables/SSDT - Length
> +00000198 (0x0000C6)
> +ACPI: SSDT 0x0000000000000000 0000C6 (v01 BOCHS  VMGENID  00000001 BXPC
> +00000001)
> +Acpi table [SSDT] successfully installed and loaded
> +Pass 1 parse of [SSDT]
> +Pass 2 parse of [SSDT]
> +Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)
> +
> +Parsing completed
> +Disassembly completed
> +ASL Output:    ./SSDT.dsl - 1631 bytes
> +# cat SSDT.dsl
> +/*
> + * Intel ACPI Component Architecture
> + * AML/ASL+ Disassembler version 20150717-64
> + * Copyright (c) 2000 - 2015 Intel Corporation
> + *
> + * Disassembling to symbolic ASL+ operators
> + *
> + * Disassembly of /sys/firmware/acpi/tables/SSDT, Sun Feb  5 00:19:37 2017
> + *
> + * Original Table Header:
> + *     Signature        "SSDT"
> + *     Length           0x000000CA (202)
> + *     Revision         0x01
> + *     Checksum         0x4B
> + *     OEM ID           "BOCHS "
> + *     OEM Table ID     "VMGENID"
> + *     OEM Revision     0x00000001 (1)
> + *     Compiler ID      "BXPC"
> + *     Compiler Version 0x00000001 (1)
> + */
> +DefinitionBlock ("/sys/firmware/acpi/tables/SSDT.aml", "SSDT", 1, "BOCHS
> ",
> +"VMGENID", 0x00000001)
> +{
> +    Name (VGIA, 0x07FFF000)
> +    Scope (\_SB)
> +    {
> +        Device (VGEN)
> +        {
> +            Name (_HID, "QEMUVGID")  // _HID: Hardware ID
> +            Name (_CID, "VM_Gen_Counter")  // _CID: Compatible ID
> +            Name (_DDN, "VM_Gen_Counter")  // _DDN: DOS Device Name
> +            Method (_STA, 0, NotSerialized)  // _STA: Status
> +            {
> +                Local0 = 0x0F
> +                If ((VGIA == Zero))
> +                {
> +                    Local0 = Zero
> +                }
> +
> +                Return (Local0)
> +            }
> +
> +            Method (ADDR, 0, NotSerialized)
> +            {
> +                Local0 = Package (0x02) {}
> +                Index (Local0, Zero) = (VGIA + 0x28)
> +                Index (Local0, One) = Zero
> +                Return (Local0)
> +            }
> +        }
> +    }
> +
> +    Method (\_GPE._E05, 0, NotSerialized)  // _Exx: Edge-Triggered GPE
> +    {
> +        Notify (\_SB.VGEN, 0x80) // Status Change
> +    }
> +}
> +
> +
> +Design Details:
> +---------------
> +
> +Requirements R1a through R1e dictate that the memory holding the
> +VM Generation ID must be allocated and owned by the guest firmware,
> +in this case BIOS or UEFI.  However, to be useful, QEMU must be able to
> +change the contents of the memory at runtime, specifically when starting a
> +backed-up or snapshotted image.  In order to do this, QEMU must know the
> +address that has been allocated.
> +
> +The mechanism chosen for this memory sharing is writeable fw_cfg blobs.
> +These are data object that are visible to both QEMU and guests, and are
> +addressable as sequential files.
> +
> +More information about fw_cfg can be found in "docs/specs/fw_cfg.txt"
> +
> +Two fw_cfg blobs are used in this case:
> +
> +/etc/vmgenid_guid - contains the actual VM Generation ID GUID
> +                  - read-only to the guest
> +/etc/vmgenid_addr - contains the address of the downloaded vmgenid blob
> +                  - writeable by the guest
> +
> +
> +QEMU sends the following commands to the guest at startup:
> +
> +1. Allocate memory for vmgenid_guid fw_cfg blob.
> +2. Write the address of vmgenid_guid into the SSDT (VGIA ACPI variable as
> +   shown above in the iasl dump).  Note that this change is not propagated
> +   back to QEMU.
> +3. Write the address of vmgenid_guid back to QEMU's copy of vmgenid_addr
> +   via the fw_cfg DMA interface.
> +
> +After step 3, QEMU is able to update the contents of vmgenid_guid at will.
> +
> +Since BIOS or UEFI does not necessarily run when we wish to change the
> GUID,
> +the value of VGIA is persisted via the VMState mechanism.
> +
> +As spelled out in the specification, any change to the GUID executes an
> +ACPI notification.  The exact handler to use is not specified, so the
> vmgenid
> +device uses the first unused one:  \_GPE._E05.
> +
> +
> +Endian-ness Considerations:
> +---------------------------
> +
> +Although not specified in Microsoft's document, it is assumed that the
> +device is expected to use little-endian format.
> +
> +All GUID passed in via command line or monitor are treated as big-endian.
> +GUID values displayed via monitor are shown in big-endian format.
> +
> +
> +GUID Storage Format:
> +--------------------
> +
> +In order to implement an OVMF "SDT Header Probe Suppressor", the contents
> of
> +the vmgenid_guid fw_cfg blob are not simply a 128-bit GUID.  There is also
> +significant padding in order to align and fill a memory page, as shown in
> the
> +following diagram:
> +
> ++----------------------------------+
> +| SSDT with OEM Table ID = VMGENID |
> ++----------------------------------+
> +| ...                              |       TOP OF PAGE
> +| VGIA dword object ---------------|-----> +---------------------------+
> +| ...                              |       | fw-allocated array for    |
> +| _STA method referring to VGIA    |       | "etc/vmgenid_guid"        |
> +| ...                              |       +---------------------------+
> +| ADDR method referring to VGIA    |       |  0: OVMF SDT Header probe |
> +| ...                              |       |     suppressor            |
> ++----------------------------------+       | 36: padding for 8-byte    |
> +                                           |     alignment             |
> +                                           | 40: GUID                  |
> +                                           | 56: padding to page size  |
> +                                           +---------------------------+
> +                                           END OF PAGE
> +
> +
> +Device Usage:
> +-------------
> +
> +The device has one property, which may be only be set using the command
> line:
> +
> +  guid - sets the value of the GUID.  A special value "auto" instructs
> +         QEMU to generate a new random GUID.
> +
> +For example:
> +
> +  QEMU  -device vmgenid,guid="324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
> +  QEMU  -device vmgenid,guid=auto
>

The default will keep uuid to null, should it be documented? Wouldn't it
make sense to default to auto?


> +The property may be queried via QMP/HMP:
> +
> +  (QEMU) query-vm-generation-id
> +  {"return": {"guid": "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"}}
> +
> +Setting of this parameter is intentionally left out from the QMP/HMP
> +interfaces.  There are no known use cases for changing the GUID once QEMU
> is
> +running, and adding this capability would greatly increase the complexity.
>

Is this supposed to be not permitted?

{ "execute": "qom-set", "arguments": { "path":
"/machine/peripheral-anon/device[1]", "property": "guid", "value": "auto" }
}

Is there any linux kernel support being worked on?

thanks
Laszlo Ersek April 12, 2017, 8:17 p.m. UTC | #2
On 04/12/17 22:06, Marc-André Lureau wrote:
> On Thu, Mar 2, 2017 at 10:22 AM Michael S. Tsirkin <mst@redhat.com> wrote:

>> +Device Usage:
>> +-------------
>> +
>> +The device has one property, which may be only be set using the command
>> line:
>> +
>> +  guid - sets the value of the GUID.  A special value "auto" instructs
>> +         QEMU to generate a new random GUID.
>> +
>> +For example:
>> +
>> +  QEMU  -device vmgenid,guid="324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
>> +  QEMU  -device vmgenid,guid=auto
>>
> 
> The default will keep uuid to null, should it be documented? Wouldn't it
> make sense to default to auto?

I guess it might.

> 
> 
>> +The property may be queried via QMP/HMP:
>> +
>> +  (QEMU) query-vm-generation-id
>> +  {"return": {"guid": "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"}}
>> +
>> +Setting of this parameter is intentionally left out from the QMP/HMP
>> +interfaces.  There are no known use cases for changing the GUID once QEMU
>> is
>> +running, and adding this capability would greatly increase the complexity.
>>
> 
> Is this supposed to be not permitted?
> 
> { "execute": "qom-set", "arguments": { "path":
> "/machine/peripheral-anon/device[1]", "property": "guid", "value": "auto" }
> }

I don't know if qom-set can be disabled for individual devices / device
properties. Either way, setting a new GUID for VMGENID will definitely
take custom code.

> Is there any linux kernel support being worked on?

There's an RHBZ for it (alias "vmgenid-kernel"):

https://bugzilla.redhat.com/show_bug.cgi?id=1159983

(It is private because RHBZs for the kernel component are private by
default.)

Thanks
Laszlo
Cameron Esfahani via April 12, 2017, 8:17 p.m. UTC | #3
> On Apr 12, 2017, at 1:06 PM, Marc-André Lureau <marcandre.lureau@gmail.com> wrote:
> 
> Hi
> 
> On Thu, Mar 2, 2017 at 10:22 AM Michael S. Tsirkin <mst@redhat.com <mailto:mst@redhat.com>> wrote:
> From: Ben Warren <ben@skyportsystems.com <mailto:ben@skyportsystems.com>>
> 
> This patch is based off an earlier version by
> Gal Hammer (ghammer@redhat.com <mailto:ghammer@redhat.com>)
> 
> Requirements section, ASCII diagrams and overall help
> provided by Laszlo Ersek (lersek@redhat.com <mailto:lersek@redhat.com>)
> 
> Signed-off-by: Gal Hammer <ghammer@redhat.com <mailto:ghammer@redhat.com>>
> Signed-off-by: Ben Warren <ben@skyportsystems.com <mailto:ben@skyportsystems.com>>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com <mailto:lersek@redhat.com>>
> Reviewed-by: Igor Mammedov <imammedo@redhat.com <mailto:imammedo@redhat.com>>
> Reviewed-by: Michael S. Tsirkin <mst@redhat.com <mailto:mst@redhat.com>>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com <mailto:mst@redhat.com>>
> ---
>  docs/specs/vmgenid.txt | 245 +++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 245 insertions(+)
>  create mode 100644 docs/specs/vmgenid.txt
> 
> diff --git a/docs/specs/vmgenid.txt b/docs/specs/vmgenid.txt
> new file mode 100644
> index 0000000..aa9f518
> --- /dev/null
> +++ b/docs/specs/vmgenid.txt
> @@ -0,0 +1,245 @@
> +VIRTUAL MACHINE GENERATION ID
> +=============================
> +
> +Copyright (C) 2016 Red Hat, Inc.
> +Copyright (C) 2017 Skyport Systems, Inc.
> +
> +This work is licensed under the terms of the GNU GPL, version 2 or later.
> +See the COPYING file in the top-level directory.
> +
> +===
> +
> +The VM generation ID (vmgenid) device is an emulated device which
> +exposes a 128-bit, cryptographically random, integer value identifier,
> +referred to as a Globally Unique Identifier, or GUID.
> +
> +This allows management applications (e.g. libvirt) to notify the guest
> +operating system when the virtual machine is executed with a different
> +configuration (e.g. snapshot execution or creation from a template).  The
> +guest operating system notices the change, and is then able to react as
> +appropriate by marking its copies of distributed databases as dirty,
> +re-initializing its random number generator etc.
> +
> +
> +Requirements
> +------------
> +
> +These requirements are extracted from the "How to implement virtual machine
> +generation ID support in a virtualization platform" section of the
> +specification, dated August 1, 2012.
> +
> +
> +The document may be found on the web at:
> +  http://go.microsoft.com/fwlink/?LinkId=260709 <http://go.microsoft.com/fwlink/?LinkId=260709>
> +
> +R1a. The generation ID shall live in an 8-byte aligned buffer.
> +
> +R1b. The buffer holding the generation ID shall be in guest RAM, ROM, or device
> +     MMIO range.
> +
> +R1c. The buffer holding the generation ID shall be kept separate from areas
> +     used by the operating system.
> +
> +R1d. The buffer shall not be covered by an AddressRangeMemory or
> +     AddressRangeACPI entry in the E820 or UEFI memory map.
> +
> +R1e. The generation ID shall not live in a page frame that could be mapped with
> +     caching disabled. (In other words, regardless of whether the generation ID
> +     lives in RAM, ROM or MMIO, it shall only be mapped as cacheable.)
> +
> +R2 to R5. [These AML requirements are isolated well enough in the Microsoft
> +          specification for us to simply refer to them here.]
> +
> +R6. The hypervisor shall expose a _HID (hardware identifier) object in the
> +    VMGenId device's scope that is unique to the hypervisor vendor.
> +
> +
> +QEMU Implementation
> +-------------------
> +
> +The above-mentioned specification does not dictate which ACPI descriptor table
> +will contain the VM Generation ID device.  Other implementations (Hyper-V and
> +Xen) put it in the main descriptor table (Differentiated System Description
> +Table or DSDT).  For ease of debugging and implementation, we have decided to
> +put it in its own Secondary System Description Table, or SSDT.
> +
> +The following is a dump of the contents from a running system:
> +
> +# iasl -p ./SSDT -d /sys/firmware/acpi/tables/SSDT
> +
> +Intel ACPI Component Architecture
> +ASL+ Optimizing Compiler version 20150717-64
> +Copyright (c) 2000 - 2015 Intel Corporation
> +
> +Reading ACPI table from file /sys/firmware/acpi/tables/SSDT - Length
> +00000198 (0x0000C6)
> +ACPI: SSDT 0x0000000000000000 0000C6 (v01 BOCHS  VMGENID  00000001 BXPC
> +00000001)
> +Acpi table [SSDT] successfully installed and loaded
> +Pass 1 parse of [SSDT]
> +Pass 2 parse of [SSDT]
> +Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)
> +
> +Parsing completed
> +Disassembly completed
> +ASL Output:    ./SSDT.dsl - 1631 bytes
> +# cat SSDT.dsl
> +/*
> + * Intel ACPI Component Architecture
> + * AML/ASL+ Disassembler version 20150717-64
> + * Copyright (c) 2000 - 2015 Intel Corporation
> + *
> + * Disassembling to symbolic ASL+ operators
> + *
> + * Disassembly of /sys/firmware/acpi/tables/SSDT, Sun Feb  5 00:19:37 2017
> + *
> + * Original Table Header:
> + *     Signature        "SSDT"
> + *     Length           0x000000CA (202)
> + *     Revision         0x01
> + *     Checksum         0x4B
> + *     OEM ID           "BOCHS "
> + *     OEM Table ID     "VMGENID"
> + *     OEM Revision     0x00000001 (1)
> + *     Compiler ID      "BXPC"
> + *     Compiler Version 0x00000001 (1)
> + */
> +DefinitionBlock ("/sys/firmware/acpi/tables/SSDT.aml", "SSDT", 1, "BOCHS ",
> +"VMGENID", 0x00000001)
> +{
> +    Name (VGIA, 0x07FFF000)
> +    Scope (\_SB)
> +    {
> +        Device (VGEN)
> +        {
> +            Name (_HID, "QEMUVGID")  // _HID: Hardware ID
> +            Name (_CID, "VM_Gen_Counter")  // _CID: Compatible ID
> +            Name (_DDN, "VM_Gen_Counter")  // _DDN: DOS Device Name
> +            Method (_STA, 0, NotSerialized)  // _STA: Status
> +            {
> +                Local0 = 0x0F
> +                If ((VGIA == Zero))
> +                {
> +                    Local0 = Zero
> +                }
> +
> +                Return (Local0)
> +            }
> +
> +            Method (ADDR, 0, NotSerialized)
> +            {
> +                Local0 = Package (0x02) {}
> +                Index (Local0, Zero) = (VGIA + 0x28)
> +                Index (Local0, One) = Zero
> +                Return (Local0)
> +            }
> +        }
> +    }
> +
> +    Method (\_GPE._E05, 0, NotSerialized)  // _Exx: Edge-Triggered GPE
> +    {
> +        Notify (\_SB.VGEN, 0x80) // Status Change
> +    }
> +}
> +
> +
> +Design Details:
> +---------------
> +
> +Requirements R1a through R1e dictate that the memory holding the
> +VM Generation ID must be allocated and owned by the guest firmware,
> +in this case BIOS or UEFI.  However, to be useful, QEMU must be able to
> +change the contents of the memory at runtime, specifically when starting a
> +backed-up or snapshotted image.  In order to do this, QEMU must know the
> +address that has been allocated.
> +
> +The mechanism chosen for this memory sharing is writeable fw_cfg blobs.
> +These are data object that are visible to both QEMU and guests, and are
> +addressable as sequential files.
> +
> +More information about fw_cfg can be found in "docs/specs/fw_cfg.txt"
> +
> +Two fw_cfg blobs are used in this case:
> +
> +/etc/vmgenid_guid - contains the actual VM Generation ID GUID
> +                  - read-only to the guest
> +/etc/vmgenid_addr - contains the address of the downloaded vmgenid blob
> +                  - writeable by the guest
> +
> +
> +QEMU sends the following commands to the guest at startup:
> +
> +1. Allocate memory for vmgenid_guid fw_cfg blob.
> +2. Write the address of vmgenid_guid into the SSDT (VGIA ACPI variable as
> +   shown above in the iasl dump).  Note that this change is not propagated
> +   back to QEMU.
> +3. Write the address of vmgenid_guid back to QEMU's copy of vmgenid_addr
> +   via the fw_cfg DMA interface.
> +
> +After step 3, QEMU is able to update the contents of vmgenid_guid at will.
> +
> +Since BIOS or UEFI does not necessarily run when we wish to change the GUID,
> +the value of VGIA is persisted via the VMState mechanism.
> +
> +As spelled out in the specification, any change to the GUID executes an
> +ACPI notification.  The exact handler to use is not specified, so the vmgenid
> +device uses the first unused one:  \_GPE._E05.
> +
> +
> +Endian-ness Considerations:
> +---------------------------
> +
> +Although not specified in Microsoft's document, it is assumed that the
> +device is expected to use little-endian format.
> +
> +All GUID passed in via command line or monitor are treated as big-endian.
> +GUID values displayed via monitor are shown in big-endian format.
> +
> +
> +GUID Storage Format:
> +--------------------
> +
> +In order to implement an OVMF "SDT Header Probe Suppressor", the contents of
> +the vmgenid_guid fw_cfg blob are not simply a 128-bit GUID.  There is also
> +significant padding in order to align and fill a memory page, as shown in the
> +following diagram:
> +
> ++----------------------------------+
> +| SSDT with OEM Table ID = VMGENID |
> ++----------------------------------+
> +| ...                              |       TOP OF PAGE
> +| VGIA dword object ---------------|-----> +---------------------------+
> +| ...                              |       | fw-allocated array for    |
> +| _STA method referring to VGIA    |       | "etc/vmgenid_guid"        |
> +| ...                              |       +---------------------------+
> +| ADDR method referring to VGIA    |       |  0: OVMF SDT Header probe |
> +| ...                              |       |     suppressor            |
> ++----------------------------------+       | 36: padding for 8-byte    |
> +                                           |     alignment             |
> +                                           | 40: GUID                  |
> +                                           | 56: padding to page size  |
> +                                           +---------------------------+
> +                                           END OF PAGE
> +
> +
> +Device Usage:
> +-------------
> +
> +The device has one property, which may be only be set using the command line:
> +
> +  guid - sets the value of the GUID.  A special value "auto" instructs
> +         QEMU to generate a new random GUID.
> +
> +For example:
> +
> +  QEMU  -device vmgenid,guid="324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
> +  QEMU  -device vmgenid,guid=auto
> 
> The default will keep uuid to null, should it be documented? Wouldn't it make sense to default to auto?
There is no default - you have to supply a value. It’s up to whatever software is managing VM lifecycle to decide what value to pass in.  Always setting to ‘auto’ will cause a lot of churn within Windows that may or may not be acceptable to your use case.
>  
> +The property may be queried via QMP/HMP:
> +
> +  (QEMU) query-vm-generation-id
> +  {"return": {"guid": "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"}}
> +
> +Setting of this parameter is intentionally left out from the QMP/HMP
> +interfaces.  There are no known use cases for changing the GUID once QEMU is
> +running, and adding this capability would greatly increase the complexity.
>  
> Is this supposed to be not permitted?
> 
> { "execute": "qom-set", "arguments": { "path": "/machine/peripheral-anon/device[1]", "property": "guid", "value": "auto" } }
> 
> Is there any linux kernel support being worked on?
This isn’t really relevant to the Linux kernel, at least in any way I can think of.  What did you have in mind?
> 
> thanks
> -- 
> Marc-André Lureau

—Ben
Michael S. Tsirkin April 12, 2017, 8:20 p.m. UTC | #4
On Wed, Apr 12, 2017 at 08:06:32PM +0000, Marc-André Lureau wrote:
> Hi
> 
> On Thu, Mar 2, 2017 at 10:22 AM Michael S. Tsirkin <mst@redhat.com> wrote:
> 
>     From: Ben Warren <ben@skyportsystems.com>
> 
>     This patch is based off an earlier version by
>     Gal Hammer (ghammer@redhat.com)
> 
>     Requirements section, ASCII diagrams and overall help
>     provided by Laszlo Ersek (lersek@redhat.com)
> 
>     Signed-off-by: Gal Hammer <ghammer@redhat.com>
>     Signed-off-by: Ben Warren <ben@skyportsystems.com>
>     Reviewed-by: Laszlo Ersek <lersek@redhat.com>
>     Reviewed-by: Igor Mammedov <imammedo@redhat.com>
>     Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
>     Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
>     ---
>      docs/specs/vmgenid.txt | 245
>     +++++++++++++++++++++++++++++++++++++++++++++++++
>      1 file changed, 245 insertions(+)
>      create mode 100644 docs/specs/vmgenid.txt
> 
>     diff --git a/docs/specs/vmgenid.txt b/docs/specs/vmgenid.txt
>     new file mode 100644
>     index 0000000..aa9f518
>     --- /dev/null
>     +++ b/docs/specs/vmgenid.txt
>     @@ -0,0 +1,245 @@
>     +VIRTUAL MACHINE GENERATION ID
>     +=============================
>     +
>     +Copyright (C) 2016 Red Hat, Inc.
>     +Copyright (C) 2017 Skyport Systems, Inc.
>     +
>     +This work is licensed under the terms of the GNU GPL, version 2 or later.
>     +See the COPYING file in the top-level directory.
>     +
>     +===
>     +
>     +The VM generation ID (vmgenid) device is an emulated device which
>     +exposes a 128-bit, cryptographically random, integer value identifier,
>     +referred to as a Globally Unique Identifier, or GUID.
>     +
>     +This allows management applications (e.g. libvirt) to notify the guest
>     +operating system when the virtual machine is executed with a different
>     +configuration (e.g. snapshot execution or creation from a template).  The
>     +guest operating system notices the change, and is then able to react as
>     +appropriate by marking its copies of distributed databases as dirty,
>     +re-initializing its random number generator etc.
>     +
>     +
>     +Requirements
>     +------------
>     +
>     +These requirements are extracted from the "How to implement virtual
>     machine
>     +generation ID support in a virtualization platform" section of the
>     +specification, dated August 1, 2012.
>     +
>     +
>     +The document may be found on the web at:
>     +  http://go.microsoft.com/fwlink/?LinkId=260709
>     +
>     +R1a. The generation ID shall live in an 8-byte aligned buffer.
>     +
>     +R1b. The buffer holding the generation ID shall be in guest RAM, ROM, or
>     device
>     +     MMIO range.
>     +
>     +R1c. The buffer holding the generation ID shall be kept separate from
>     areas
>     +     used by the operating system.
>     +
>     +R1d. The buffer shall not be covered by an AddressRangeMemory or
>     +     AddressRangeACPI entry in the E820 or UEFI memory map.
>     +
>     +R1e. The generation ID shall not live in a page frame that could be mapped
>     with
>     +     caching disabled. (In other words, regardless of whether the
>     generation ID
>     +     lives in RAM, ROM or MMIO, it shall only be mapped as cacheable.)
>     +
>     +R2 to R5. [These AML requirements are isolated well enough in the
>     Microsoft
>     +          specification for us to simply refer to them here.]
>     +
>     +R6. The hypervisor shall expose a _HID (hardware identifier) object in the
>     +    VMGenId device's scope that is unique to the hypervisor vendor.
>     +
>     +
>     +QEMU Implementation
>     +-------------------
>     +
>     +The above-mentioned specification does not dictate which ACPI descriptor
>     table
>     +will contain the VM Generation ID device.  Other implementations (Hyper-V
>     and
>     +Xen) put it in the main descriptor table (Differentiated System
>     Description
>     +Table or DSDT).  For ease of debugging and implementation, we have decided
>     to
>     +put it in its own Secondary System Description Table, or SSDT.
>     +
>     +The following is a dump of the contents from a running system:
>     +
>     +# iasl -p ./SSDT -d /sys/firmware/acpi/tables/SSDT
>     +
>     +Intel ACPI Component Architecture
>     +ASL+ Optimizing Compiler version 20150717-64
>     +Copyright (c) 2000 - 2015 Intel Corporation
>     +
>     +Reading ACPI table from file /sys/firmware/acpi/tables/SSDT - Length
>     +00000198 (0x0000C6)
>     +ACPI: SSDT 0x0000000000000000 0000C6 (v01 BOCHS  VMGENID  00000001 BXPC
>     +00000001)
>     +Acpi table [SSDT] successfully installed and loaded
>     +Pass 1 parse of [SSDT]
>     +Pass 2 parse of [SSDT]
>     +Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)
>     +
>     +Parsing completed
>     +Disassembly completed
>     +ASL Output:    ./SSDT.dsl - 1631 bytes
>     +# cat SSDT.dsl
>     +/*
>     + * Intel ACPI Component Architecture
>     + * AML/ASL+ Disassembler version 20150717-64
>     + * Copyright (c) 2000 - 2015 Intel Corporation
>     + *
>     + * Disassembling to symbolic ASL+ operators
>     + *
>     + * Disassembly of /sys/firmware/acpi/tables/SSDT, Sun Feb  5 00:19:37 2017
>     + *
>     + * Original Table Header:
>     + *     Signature        "SSDT"
>     + *     Length           0x000000CA (202)
>     + *     Revision         0x01
>     + *     Checksum         0x4B
>     + *     OEM ID           "BOCHS "
>     + *     OEM Table ID     "VMGENID"
>     + *     OEM Revision     0x00000001 (1)
>     + *     Compiler ID      "BXPC"
>     + *     Compiler Version 0x00000001 (1)
>     + */
>     +DefinitionBlock ("/sys/firmware/acpi/tables/SSDT.aml", "SSDT", 1, "BOCHS
>     ",
>     +"VMGENID", 0x00000001)
>     +{
>     +    Name (VGIA, 0x07FFF000)
>     +    Scope (\_SB)
>     +    {
>     +        Device (VGEN)
>     +        {
>     +            Name (_HID, "QEMUVGID")  // _HID: Hardware ID
>     +            Name (_CID, "VM_Gen_Counter")  // _CID: Compatible ID
>     +            Name (_DDN, "VM_Gen_Counter")  // _DDN: DOS Device Name
>     +            Method (_STA, 0, NotSerialized)  // _STA: Status
>     +            {
>     +                Local0 = 0x0F
>     +                If ((VGIA == Zero))
>     +                {
>     +                    Local0 = Zero
>     +                }
>     +
>     +                Return (Local0)
>     +            }
>     +
>     +            Method (ADDR, 0, NotSerialized)
>     +            {
>     +                Local0 = Package (0x02) {}
>     +                Index (Local0, Zero) = (VGIA + 0x28)
>     +                Index (Local0, One) = Zero
>     +                Return (Local0)
>     +            }
>     +        }
>     +    }
>     +
>     +    Method (\_GPE._E05, 0, NotSerialized)  // _Exx: Edge-Triggered GPE
>     +    {
>     +        Notify (\_SB.VGEN, 0x80) // Status Change
>     +    }
>     +}
>     +
>     +
>     +Design Details:
>     +---------------
>     +
>     +Requirements R1a through R1e dictate that the memory holding the
>     +VM Generation ID must be allocated and owned by the guest firmware,
>     +in this case BIOS or UEFI.  However, to be useful, QEMU must be able to
>     +change the contents of the memory at runtime, specifically when starting a
>     +backed-up or snapshotted image.  In order to do this, QEMU must know the
>     +address that has been allocated.
>     +
>     +The mechanism chosen for this memory sharing is writeable fw_cfg blobs.
>     +These are data object that are visible to both QEMU and guests, and are
>     +addressable as sequential files.
>     +
>     +More information about fw_cfg can be found in "docs/specs/fw_cfg.txt"
>     +
>     +Two fw_cfg blobs are used in this case:
>     +
>     +/etc/vmgenid_guid - contains the actual VM Generation ID GUID
>     +                  - read-only to the guest
>     +/etc/vmgenid_addr - contains the address of the downloaded vmgenid blob
>     +                  - writeable by the guest
>     +
>     +
>     +QEMU sends the following commands to the guest at startup:
>     +
>     +1. Allocate memory for vmgenid_guid fw_cfg blob.
>     +2. Write the address of vmgenid_guid into the SSDT (VGIA ACPI variable as
>     +   shown above in the iasl dump).  Note that this change is not propagated
>     +   back to QEMU.
>     +3. Write the address of vmgenid_guid back to QEMU's copy of vmgenid_addr
>     +   via the fw_cfg DMA interface.
>     +
>     +After step 3, QEMU is able to update the contents of vmgenid_guid at will.
>     +
>     +Since BIOS or UEFI does not necessarily run when we wish to change the
>     GUID,
>     +the value of VGIA is persisted via the VMState mechanism.
>     +
>     +As spelled out in the specification, any change to the GUID executes an
>     +ACPI notification.  The exact handler to use is not specified, so the
>     vmgenid
>     +device uses the first unused one:  \_GPE._E05.
>     +
>     +
>     +Endian-ness Considerations:
>     +---------------------------
>     +
>     +Although not specified in Microsoft's document, it is assumed that the
>     +device is expected to use little-endian format.
>     +
>     +All GUID passed in via command line or monitor are treated as big-endian.
>     +GUID values displayed via monitor are shown in big-endian format.
>     +
>     +
>     +GUID Storage Format:
>     +--------------------
>     +
>     +In order to implement an OVMF "SDT Header Probe Suppressor", the contents
>     of
>     +the vmgenid_guid fw_cfg blob are not simply a 128-bit GUID.  There is also
>     +significant padding in order to align and fill a memory page, as shown in
>     the
>     +following diagram:
>     +
>     ++----------------------------------+
>     +| SSDT with OEM Table ID = VMGENID |
>     ++----------------------------------+
>     +| ...                              |       TOP OF PAGE
>     +| VGIA dword object ---------------|-----> +---------------------------+
>     +| ...                              |       | fw-allocated array for    |
>     +| _STA method referring to VGIA    |       | "etc/vmgenid_guid"        |
>     +| ...                              |       +---------------------------+
>     +| ADDR method referring to VGIA    |       |  0: OVMF SDT Header probe |
>     +| ...                              |       |     suppressor            |
>     ++----------------------------------+       | 36: padding for 8-byte    |
>     +                                           |     alignment             |
>     +                                           | 40: GUID                  |
>     +                                           | 56: padding to page size  |
>     +                                           +---------------------------+
>     +                                           END OF PAGE
>     +
>     +
>     +Device Usage:
>     +-------------
>     +
>     +The device has one property, which may be only be set using the command
>     line:
>     +
>     +  guid - sets the value of the GUID.  A special value "auto" instructs
>     +         QEMU to generate a new random GUID.
>     +
>     +For example:
>     +
>     +  QEMU  -device vmgenid,guid="324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
>     +  QEMU  -device vmgenid,guid=auto
> 
> 
> The default will keep uuid to null, should it be documented? Wouldn't it make
> sense to default to auto?

Interesting. I'd say default should fail init.

> 
>     +The property may be queried via QMP/HMP:
>     +
>     +  (QEMU) query-vm-generation-id
>     +  {"return": {"guid": "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"}}
>     +
>     +Setting of this parameter is intentionally left out from the QMP/HMP
>     +interfaces.  There are no known use cases for changing the GUID once QEMU
>     is
>     +running, and adding this capability would greatly increase the complexity.
> 
>  
> Is this supposed to be not permitted?
> 
> { "execute": "qom-set", "arguments": { "path": "/machine/peripheral-anon/device
> [1]", "property": "guid", "value": "auto" } }

anon means in particular no stability.

Also we are yet to tie this to generate
an interrupt and update guest memory properly.
Patches welcome.

> Is there any linux kernel support being worked on?

I vaguely rememeber some patches but couldn't find them.
An ACPI driver would be easy to implement, one thing to
be careful about is to make sure all memory maps are cached
as spec requires this.

> thanks
> --
> Marc-André Lureau
Marc-André Lureau April 12, 2017, 8:22 p.m. UTC | #5
Hi

On Thu, Apr 13, 2017 at 12:17 AM Ben Warren <ben@skyportsystems.com> wrote:

> On Apr 12, 2017, at 1:06 PM, Marc-André Lureau <marcandre.lureau@gmail.com>
> wrote:
>
> +Device Usage:
> +-------------
> +
> +The device has one property, which may be only be set using the command
> line:
> +
> +  guid - sets the value of the GUID.  A special value "auto" instructs
> +         QEMU to generate a new random GUID.
> +
> +For example:
> +
> +  QEMU  -device vmgenid,guid="324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
> +  QEMU  -device vmgenid,guid=auto
>
>
> The default will keep uuid to null, should it be documented? Wouldn't it
> make sense to default to auto?
>
> There is no default - you have to supply a value. It’s up to whatever
> software is managing VM lifecycle to decide what value to pass in.  Always
> setting to ‘auto’ will cause a lot of churn within Windows that may or may
> not be acceptable to your use case.
>
>
Why would you have a vmgenid device if it's always null? Does that please
some windows use-cases as well?


>
>
> +The property may be queried via QMP/HMP:
> +
> +  (QEMU) query-vm-generation-id
> +  {"return": {"guid": "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"}}
> +
> +Setting of this parameter is intentionally left out from the QMP/HMP
> +interfaces.  There are no known use cases for changing the GUID once QEMU
> is
> +running, and adding this capability would greatly increase the complexity.
>
>
> Is this supposed to be not permitted?
>
> { "execute": "qom-set", "arguments": { "path":
> "/machine/peripheral-anon/device[1]", "property": "guid", "value": "auto" }
> }
>
> Is there any linux kernel support being worked on?
>
> This isn’t really relevant to the Linux kernel, at least in any way I can
> think of.  What did you have in mind?
>

Testing, but apparently we do have RFE for RHEL as Laszlo pointed out.

Thanks
Cameron Esfahani via April 12, 2017, 8:25 p.m. UTC | #6
> On Apr 12, 2017, at 1:22 PM, Marc-André Lureau <marcandre.lureau@gmail.com> wrote:
> 
> Hi
> 
> On Thu, Apr 13, 2017 at 12:17 AM Ben Warren <ben@skyportsystems.com <mailto:ben@skyportsystems.com>> wrote:
>> On Apr 12, 2017, at 1:06 PM, Marc-André Lureau <marcandre.lureau@gmail.com <mailto:marcandre.lureau@gmail.com>> wrote:
>> 
>> +Device Usage:
>> +-------------
>> +
>> +The device has one property, which may be only be set using the command line:
>> +
>> +  guid - sets the value of the GUID.  A special value "auto" instructs
>> +         QEMU to generate a new random GUID.
>> +
>> +For example:
>> +
>> +  QEMU  -device vmgenid,guid="324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
>> +  QEMU  -device vmgenid,guid=auto
>> 
>> The default will keep uuid to null, should it be documented? Wouldn't it make sense to default to auto?
> 
> There is no default - you have to supply a value. It’s up to whatever software is managing VM lifecycle to decide what value to pass in.  Always setting to ‘auto’ will cause a lot of churn within Windows that may or may not be acceptable to your use case.
> 
> 
> Why would you have a vmgenid device if it's always null? Does that please some windows use-cases as well? 
>  
I don’t get what you mean by this.  What device is always null?  Either the device is instantiated or it isn’t.  If not there, Windows will not find a device and I don’t know how derived objects (Invocation ID, etc.) are handled.
>>  
>> +The property may be queried via QMP/HMP:
>> +
>> +  (QEMU) query-vm-generation-id
>> +  {"return": {"guid": "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"}}
>> +
>> +Setting of this parameter is intentionally left out from the QMP/HMP
>> +interfaces.  There are no known use cases for changing the GUID once QEMU is
>> +running, and adding this capability would greatly increase the complexity.
>>  
>> Is this supposed to be not permitted?
>> 
>> { "execute": "qom-set", "arguments": { "path": "/machine/peripheral-anon/device[1]", "property": "guid", "value": "auto" } }
>> 
>> Is there any linux kernel support being worked on?
> 
> This isn’t really relevant to the Linux kernel, at least in any way I can think of.  What did you have in mind?
> 
> Testing, but apparently we do have RFE for RHEL as Laszlo pointed out.
OK, so you mean a guest driver.  I do have one that needs work to go upstream, but has been helpful to me in testing.
https://github.com/ben-skyportsystems/vmgenid-test <https://github.com/ben-skyportsystems/vmgenid-test>

> 
> Thanks
> -- 
> Marc-André Lureau
Marc-André Lureau April 12, 2017, 8:47 p.m. UTC | #7
Hi

On Thu, Apr 13, 2017 at 12:25 AM Ben Warren <ben@skyportsystems.com> wrote:

> On Apr 12, 2017, at 1:22 PM, Marc-André Lureau <marcandre.lureau@gmail.com>
> wrote:
>
> Hi
>
> On Thu, Apr 13, 2017 at 12:17 AM Ben Warren <ben@skyportsystems.com>
> wrote:
>
> On Apr 12, 2017, at 1:06 PM, Marc-André Lureau <marcandre.lureau@gmail.com>
> wrote:
>
> +Device Usage:
> +-------------
> +
> +The device has one property, which may be only be set using the command
> line:
> +
> +  guid - sets the value of the GUID.  A special value "auto" instructs
> +         QEMU to generate a new random GUID.
> +
> +For example:
> +
> +  QEMU  -device vmgenid,guid="324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
> +  QEMU  -device vmgenid,guid=auto
>
>
> The default will keep uuid to null, should it be documented? Wouldn't it
> make sense to default to auto?
>
> There is no default - you have to supply a value. It’s up to whatever
> software is managing VM lifecycle to decide what value to pass in.  Always
> setting to ‘auto’ will cause a lot of churn within Windows that may or may
> not be acceptable to your use case.
>
>
> Why would you have a vmgenid device if it's always null? Does that please
> some windows use-cases as well?
>
>
> I don’t get what you mean by this.  What device is always null?  Either
> the device is instantiated or it isn’t.  If not there, Windows will not
> find a device and I don’t know how derived objects (Invocation ID, etc.)
> are handled.
>

If you start a VM without specifying guid argument, you'll always have a
genid null uuid, event after a migration (this could have been handled by
qemu without requiring management layer, no?). I don't understand why auto
would create more churn than what the management layer would do by setting
new uuid for each VM started. Could you explain?


>
>
> +The property may be queried via QMP/HMP:
> +
> +  (QEMU) query-vm-generation-id
> +  {"return": {"guid": "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"}}
> +
> +Setting of this parameter is intentionally left out from the QMP/HMP
> +interfaces.  There are no known use cases for changing the GUID once QEMU
> is
> +running, and adding this capability would greatly increase the complexity.
>
>
> Is this supposed to be not permitted?
>
> { "execute": "qom-set", "arguments": { "path":
> "/machine/peripheral-anon/device[1]", "property": "guid", "value": "auto" }
> }
>
> Is there any linux kernel support being worked on?
>
> This isn’t really relevant to the Linux kernel, at least in any way I can
> think of.  What did you have in mind?
>
>
> Testing, but apparently we do have RFE for RHEL as Laszlo pointed out.
>
> OK, so you mean a guest driver.  I do have one that needs work to go
> upstream, but has been helpful to me in testing.
> https://github.com/ben-skyportsystems/vmgenid-test
>

Thanks, that's exactly what I was looking for :)
Cameron Esfahani via April 12, 2017, 9:03 p.m. UTC | #8
> On Apr 12, 2017, at 1:47 PM, Marc-André Lureau <marcandre.lureau@gmail.com> wrote:
> 
> Hi
> 
> On Thu, Apr 13, 2017 at 12:25 AM Ben Warren <ben@skyportsystems.com <mailto:ben@skyportsystems.com>> wrote:
>> On Apr 12, 2017, at 1:22 PM, Marc-André Lureau <marcandre.lureau@gmail.com <mailto:marcandre.lureau@gmail.com>> wrote:
>> 
>> Hi
>> 
>> On Thu, Apr 13, 2017 at 12:17 AM Ben Warren <ben@skyportsystems.com <mailto:ben@skyportsystems.com>> wrote:
>>> On Apr 12, 2017, at 1:06 PM, Marc-André Lureau <marcandre.lureau@gmail.com <mailto:marcandre.lureau@gmail.com>> wrote:
>>> 
>>> +Device Usage:
>>> +-------------
>>> +
>>> +The device has one property, which may be only be set using the command line:
>>> +
>>> +  guid - sets the value of the GUID.  A special value "auto" instructs
>>> +         QEMU to generate a new random GUID.
>>> +
>>> +For example:
>>> +
>>> +  QEMU  -device vmgenid,guid="324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
>>> +  QEMU  -device vmgenid,guid=auto
>>> 
>>> The default will keep uuid to null, should it be documented? Wouldn't it make sense to default to auto?
>> 
>> There is no default - you have to supply a value. It’s up to whatever software is managing VM lifecycle to decide what value to pass in.  Always setting to ‘auto’ will cause a lot of churn within Windows that may or may not be acceptable to your use case.
>> 
>> 
>> Why would you have a vmgenid device if it's always null? Does that please some windows use-cases as well? 
>>  
> 
> I don’t get what you mean by this.  What device is always null?  Either the device is instantiated or it isn’t.  If not there, Windows will not find a device and I don’t know how derived objects (Invocation ID, etc.) are handled.
> 
> If you start a VM without specifying guid argument, you'll always have a genid null uuid, event after a migration (this could have been handled by qemu without requiring management layer, no?). I don't understand why auto would create more churn than what the management layer would do by setting new uuid for each VM started. Could you explain?
> 
Looks like there’s a bug.  GUID should be a mandatory parameter.  As for the churn, I’ll give you one example.  If an Active Directory Domain Controller (ADDC) detects a change in VM Generation ID, it takes this to mean that the VM has been rolled back in time, and so its replication sequence numbers are “dirty”.  This has the effect of causing the Domain controller to perform a full “pull replication” with other ADDCs.  In large deployments this can be costly.  VM Generation ID is used by other applications besides AD.
> 
>>>  
>>> +The property may be queried via QMP/HMP:
>>> +
>>> +  (QEMU) query-vm-generation-id
>>> +  {"return": {"guid": "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"}}
>>> +
>>> +Setting of this parameter is intentionally left out from the QMP/HMP
>>> +interfaces.  There are no known use cases for changing the GUID once QEMU is
>>> +running, and adding this capability would greatly increase the complexity.
>>>  
>>> Is this supposed to be not permitted?
>>> 
>>> { "execute": "qom-set", "arguments": { "path": "/machine/peripheral-anon/device[1]", "property": "guid", "value": "auto" } }
>>> 
>>> Is there any linux kernel support being worked on?
>> 
>> This isn’t really relevant to the Linux kernel, at least in any way I can think of.  What did you have in mind?
>> 
>> Testing, but apparently we do have RFE for RHEL as Laszlo pointed out.
> 
> OK, so you mean a guest driver.  I do have one that needs work to go upstream, but has been helpful to me in testing.
> https://github.com/ben-skyportsystems/vmgenid-test <https://github.com/ben-skyportsystems/vmgenid-test>
> 
> Thanks, that's exactly what I was looking for :) 

Good.  I wish I had the time to integrate this upstream, but it’s one of those things that is good enough, and so will have to wait for another time.
> -- 
> Marc-André Lureau
Marc-André Lureau April 12, 2017, 9:17 p.m. UTC | #9
Hi

On Thu, Apr 13, 2017 at 1:03 AM Ben Warren <ben@skyportsystems.com> wrote:

> On Apr 12, 2017, at 1:47 PM, Marc-André Lureau <marcandre.lureau@gmail.com>
> wrote:
>
> Hi
>
> On Thu, Apr 13, 2017 at 12:25 AM Ben Warren <ben@skyportsystems.com>
> wrote:
>
> On Apr 12, 2017, at 1:22 PM, Marc-André Lureau <marcandre.lureau@gmail.com>
> wrote:
>
> Hi
>
> On Thu, Apr 13, 2017 at 12:17 AM Ben Warren <ben@skyportsystems.com>
> wrote:
>
> On Apr 12, 2017, at 1:06 PM, Marc-André Lureau <marcandre.lureau@gmail.com>
> wrote:
>
> +Device Usage:
> +-------------
> +
> +The device has one property, which may be only be set using the command
> line:
> +
> +  guid - sets the value of the GUID.  A special value "auto" instructs
> +         QEMU to generate a new random GUID.
> +
> +For example:
> +
> +  QEMU  -device vmgenid,guid="324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
> +  QEMU  -device vmgenid,guid=auto
>
>
> The default will keep uuid to null, should it be documented? Wouldn't it
> make sense to default to auto?
>
> There is no default - you have to supply a value. It’s up to whatever
> software is managing VM lifecycle to decide what value to pass in.  Always
> setting to ‘auto’ will cause a lot of churn within Windows that may or may
> not be acceptable to your use case.
>
>
> Why would you have a vmgenid device if it's always null? Does that please
> some windows use-cases as well?
>
>
> I don’t get what you mean by this.  What device is always null?  Either
> the device is instantiated or it isn’t.  If not there, Windows will not
> find a device and I don’t know how derived objects (Invocation ID, etc.)
> are handled.
>
>
> If you start a VM without specifying guid argument, you'll always have a
> genid null uuid, event after a migration (this could have been handled by
> qemu without requiring management layer, no?). I don't understand why auto
> would create more churn than what the management layer would do by setting
> new uuid for each VM started. Could you explain?
>
> Looks like there’s a bug.  GUID should be a mandatory parameter.
>

Not necessarily a bug, if the guid can be changed when starting a "new" VM,
which I think should work.

However, I didn't manage to get your driver noticing the acpi event. I
tried to migrate/save & restore, and no vmgenid_notify kernel messages came
out, nor notices got incremented. How did you test it?


> As for the churn, I’ll give you one example.  If an Active Directory
> Domain Controller (ADDC) detects a change in VM Generation ID, it takes
> this to mean that the VM has been rolled back in time, and so its
> replication sequence numbers are “dirty”.  This has the effect of causing
> the Domain controller to perform a full “pull replication” with other
> ADDCs.  In large deployments this can be costly.  VM Generation ID is used
> by other applications besides AD.
>
>

I start to understand better the use case and how the device should be used.

thanks again

>
>
>
> +The property may be queried via QMP/HMP:
> +
> +  (QEMU) query-vm-generation-id
> +  {"return": {"guid": "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"}}
> +
> +Setting of this parameter is intentionally left out from the QMP/HMP
> +interfaces.  There are no known use cases for changing the GUID once QEMU
> is
> +running, and adding this capability would greatly increase the complexity.
>
>
> Is this supposed to be not permitted?
>
> { "execute": "qom-set", "arguments": { "path":
> "/machine/peripheral-anon/device[1]", "property": "guid", "value": "auto" }
> }
>
> Is there any linux kernel support being worked on?
>
> This isn’t really relevant to the Linux kernel, at least in any way I can
> think of.  What did you have in mind?
>
>
> Testing, but apparently we do have RFE for RHEL as Laszlo pointed out.
>
> OK, so you mean a guest driver.  I do have one that needs work to go
> upstream, but has been helpful to me in testing.
> https://github.com/ben-skyportsystems/vmgenid-test
>
>
> Thanks, that's exactly what I was looking for :)
>
>
> Good.  I wish I had the time to integrate this upstream, but it’s one of
> those things that is good enough, and so will have to wait for another time.
>
> --
> Marc-André Lureau
>
> --
Marc-André Lureau
Michael S. Tsirkin April 12, 2017, 9:25 p.m. UTC | #10
On Wed, Apr 12, 2017 at 09:17:12PM +0000, Marc-André Lureau wrote:
> Hi
> 
> On Thu, Apr 13, 2017 at 1:03 AM Ben Warren <ben@skyportsystems.com> wrote:
> 
>         On Apr 12, 2017, at 1:47 PM, Marc-André Lureau <
>         marcandre.lureau@gmail.com> wrote:
> 
>         Hi
> 
>         On Thu, Apr 13, 2017 at 12:25 AM Ben Warren <ben@skyportsystems.com>
>         wrote:
> 
>                 On Apr 12, 2017, at 1:22 PM, Marc-André Lureau <
>                 marcandre.lureau@gmail.com> wrote:
> 
>                 Hi
> 
>                 On Thu, Apr 13, 2017 at 12:17 AM Ben Warren <
>                 ben@skyportsystems.com> wrote:
> 
>                         On Apr 12, 2017, at 1:06 PM, Marc-André Lureau <
>                         marcandre.lureau@gmail.com> wrote:
> 
> 
>                             +Device Usage:
>                             +-------------
>                             +
>                             +The device has one property, which may be only be
>                             set using the command line:
>                             +
>                             +  guid - sets the value of the GUID.  A special
>                             value "auto" instructs
>                             +         QEMU to generate a new random GUID.
>                             +
>                             +For example:
>                             +
>                             +  QEMU  -device vmgenid,guid=
>                             "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
>                             +  QEMU  -device vmgenid,guid=auto
> 
> 
>                         The default will keep uuid to null, should it be
>                         documented? Wouldn't it make sense to default to auto?
> 
>                     There is no default - you have to supply a value. It’s up
>                     to whatever software is managing VM lifecycle to decide
>                     what value to pass in.  Always setting to ‘auto’ will cause
>                     a lot of churn within Windows that may or may not be
>                     acceptable to your use case.
> 
> 
> 
>                 Why would you have a vmgenid device if it's always null? Does
>                 that please some windows use-cases as well? 
>                  
> 
>             I don’t get what you mean by this.  What device is always null? 
>             Either the device is instantiated or it isn’t.  If not there,
>             Windows will not find a device and I don’t know how derived objects
>             (Invocation ID, etc.) are handled.
> 
> 
>         If you start a VM without specifying guid argument, you'll always have
>         a genid null uuid, event after a migration (this could have been
>         handled by qemu without requiring management layer, no?). I don't
>         understand why auto would create more churn than what the management
>         layer would do by setting new uuid for each VM started. Could you
>         explain?
> 
> 
>     Looks like there’s a bug.  GUID should be a mandatory parameter. 
> 
> 
> Not necessarily a bug, if the guid can be changed when starting a "new" VM,
> which I think should work.

I think spec does not allow for a special "invalid" guid value ATM.


> However, I didn't manage to get your driver noticing the acpi event. I tried to
> migrate/save & restore, and no vmgenid_notify kernel messages came out, nor
> notices got incremented. How did you test it?
>  
> 
>     As for the churn, I’ll give you one example.  If an Active Directory Domain
>     Controller (ADDC) detects a change in VM Generation ID, it takes this to
>     mean that the VM has been rolled back in time, and so its replication
>     sequence numbers are “dirty”.  This has the effect of causing the Domain
>     controller to perform a full “pull replication” with other ADDCs.  In large
>     deployments this can be costly.  VM Generation ID is used by other
>     applications besides AD.
> 
> 
> 
> 
> I start to understand better the use case and how the device should be used.
>  
> thanks again
> 
> 
> 
>                          
> 
>                             +The property may be queried via QMP/HMP:
>                             +
>                             +  (QEMU) query-vm-generation-id
>                             +  {"return": {"guid":
>                             "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"}}
>                             +
>                             +Setting of this parameter is intentionally left
>                             out from the QMP/HMP
>                             +interfaces.  There are no known use cases for
>                             changing the GUID once QEMU is
>                             +running, and adding this capability would greatly
>                             increase the complexity.
> 
>                          
>                         Is this supposed to be not permitted?
> 
>                         { "execute": "qom-set", "arguments": { "path": "/
>                         machine/peripheral-anon/device[1]", "property": "guid",
>                         "value": "auto" } }
> 
>                         Is there any linux kernel support being worked on?
> 
>                     This isn’t really relevant to the Linux kernel, at least in
>                     any way I can think of.  What did you have in mind?
> 
> 
>                 Testing, but apparently we do have RFE for RHEL as Laszlo
>                 pointed out.
> 
>             OK, so you mean a guest driver.  I do have one that needs work to
>             go upstream, but has been helpful to me in testing.
>             https://github.com/ben-skyportsystems/vmgenid-test
> 
> 
>         Thanks, that's exactly what I was looking for :) 
> 
> 
>     Good.  I wish I had the time to integrate this upstream, but it’s one of
>     those things that is good enough, and so will have to wait for another
>     time.
> 
> 
>         -- 
>         Marc-André Lureau
> 
> --
> Marc-André Lureau
Marc-André Lureau April 13, 2017, 10:18 a.m. UTC | #11
Hi

On Thu, Apr 13, 2017 at 1:17 AM Marc-André Lureau <
marcandre.lureau@gmail.com> wrote:

> Hi
>
> On Thu, Apr 13, 2017 at 1:03 AM Ben Warren <ben@skyportsystems.com> wrote:
>
> On Apr 12, 2017, at 1:47 PM, Marc-André Lureau <marcandre.lureau@gmail.com>
> wrote:
>
> Hi
>
> On Thu, Apr 13, 2017 at 12:25 AM Ben Warren <ben@skyportsystems.com>
> wrote:
>
> On Apr 12, 2017, at 1:22 PM, Marc-André Lureau <marcandre.lureau@gmail.com>
> wrote:
>
> Hi
>
> On Thu, Apr 13, 2017 at 12:17 AM Ben Warren <ben@skyportsystems.com>
> wrote:
>
> On Apr 12, 2017, at 1:06 PM, Marc-André Lureau <marcandre.lureau@gmail.com>
> wrote:
>
> +Device Usage:
> +-------------
> +
> +The device has one property, which may be only be set using the command
> line:
> +
> +  guid - sets the value of the GUID.  A special value "auto" instructs
> +         QEMU to generate a new random GUID.
> +
> +For example:
> +
> +  QEMU  -device vmgenid,guid="324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
> +  QEMU  -device vmgenid,guid=auto
>
>
> The default will keep uuid to null, should it be documented? Wouldn't it
> make sense to default to auto?
>
> There is no default - you have to supply a value. It’s up to whatever
> software is managing VM lifecycle to decide what value to pass in.  Always
> setting to ‘auto’ will cause a lot of churn within Windows that may or may
> not be acceptable to your use case.
>
>
> Why would you have a vmgenid device if it's always null? Does that please
> some windows use-cases as well?
>
>
> I don’t get what you mean by this.  What device is always null?  Either
> the device is instantiated or it isn’t.  If not there, Windows will not
> find a device and I don’t know how derived objects (Invocation ID, etc.)
> are handled.
>
>
> If you start a VM without specifying guid argument, you'll always have a
> genid null uuid, event after a migration (this could have been handled by
> qemu without requiring management layer, no?). I don't understand why auto
> would create more churn than what the management layer would do by setting
> new uuid for each VM started. Could you explain?
>
> Looks like there’s a bug.  GUID should be a mandatory parameter.
>
>
> Not necessarily a bug, if the guid can be changed when starting a "new"
> VM, which I think should work.
>
> However, I didn't manage to get your driver noticing the acpi event. I
> tried to migrate/save & restore, and no vmgenid_notify kernel messages came
> out, nor notices got incremented. How did you test it?
>
>

Actually I was using an old bios, now I can change the guid and the guest
notices the change.

 { "execute": "qom-set", "arguments": { "path":
"/machine/peripheral-anon/device[1]", "property": "guid", "value": "..." } }

works, the guest noticed the change and the new value can be read. I don't
know what else would be required (except a better API) to allow QMP to
modify it.

thanks
diff mbox

Patch

diff --git a/docs/specs/vmgenid.txt b/docs/specs/vmgenid.txt
new file mode 100644
index 0000000..aa9f518
--- /dev/null
+++ b/docs/specs/vmgenid.txt
@@ -0,0 +1,245 @@ 
+VIRTUAL MACHINE GENERATION ID
+=============================
+
+Copyright (C) 2016 Red Hat, Inc.
+Copyright (C) 2017 Skyport Systems, Inc.
+
+This work is licensed under the terms of the GNU GPL, version 2 or later.
+See the COPYING file in the top-level directory.
+
+===
+
+The VM generation ID (vmgenid) device is an emulated device which
+exposes a 128-bit, cryptographically random, integer value identifier,
+referred to as a Globally Unique Identifier, or GUID.
+
+This allows management applications (e.g. libvirt) to notify the guest
+operating system when the virtual machine is executed with a different
+configuration (e.g. snapshot execution or creation from a template).  The
+guest operating system notices the change, and is then able to react as
+appropriate by marking its copies of distributed databases as dirty,
+re-initializing its random number generator etc.
+
+
+Requirements
+------------
+
+These requirements are extracted from the "How to implement virtual machine
+generation ID support in a virtualization platform" section of the
+specification, dated August 1, 2012.
+
+
+The document may be found on the web at:
+  http://go.microsoft.com/fwlink/?LinkId=260709
+
+R1a. The generation ID shall live in an 8-byte aligned buffer.
+
+R1b. The buffer holding the generation ID shall be in guest RAM, ROM, or device
+     MMIO range.
+
+R1c. The buffer holding the generation ID shall be kept separate from areas
+     used by the operating system.
+
+R1d. The buffer shall not be covered by an AddressRangeMemory or
+     AddressRangeACPI entry in the E820 or UEFI memory map.
+
+R1e. The generation ID shall not live in a page frame that could be mapped with
+     caching disabled. (In other words, regardless of whether the generation ID
+     lives in RAM, ROM or MMIO, it shall only be mapped as cacheable.)
+
+R2 to R5. [These AML requirements are isolated well enough in the Microsoft
+          specification for us to simply refer to them here.]
+
+R6. The hypervisor shall expose a _HID (hardware identifier) object in the
+    VMGenId device's scope that is unique to the hypervisor vendor.
+
+
+QEMU Implementation
+-------------------
+
+The above-mentioned specification does not dictate which ACPI descriptor table
+will contain the VM Generation ID device.  Other implementations (Hyper-V and
+Xen) put it in the main descriptor table (Differentiated System Description
+Table or DSDT).  For ease of debugging and implementation, we have decided to
+put it in its own Secondary System Description Table, or SSDT.
+
+The following is a dump of the contents from a running system:
+
+# iasl -p ./SSDT -d /sys/firmware/acpi/tables/SSDT
+
+Intel ACPI Component Architecture
+ASL+ Optimizing Compiler version 20150717-64
+Copyright (c) 2000 - 2015 Intel Corporation
+
+Reading ACPI table from file /sys/firmware/acpi/tables/SSDT - Length
+00000198 (0x0000C6)
+ACPI: SSDT 0x0000000000000000 0000C6 (v01 BOCHS  VMGENID  00000001 BXPC
+00000001)
+Acpi table [SSDT] successfully installed and loaded
+Pass 1 parse of [SSDT]
+Pass 2 parse of [SSDT]
+Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)
+
+Parsing completed
+Disassembly completed
+ASL Output:    ./SSDT.dsl - 1631 bytes
+# cat SSDT.dsl
+/*
+ * Intel ACPI Component Architecture
+ * AML/ASL+ Disassembler version 20150717-64
+ * Copyright (c) 2000 - 2015 Intel Corporation
+ *
+ * Disassembling to symbolic ASL+ operators
+ *
+ * Disassembly of /sys/firmware/acpi/tables/SSDT, Sun Feb  5 00:19:37 2017
+ *
+ * Original Table Header:
+ *     Signature        "SSDT"
+ *     Length           0x000000CA (202)
+ *     Revision         0x01
+ *     Checksum         0x4B
+ *     OEM ID           "BOCHS "
+ *     OEM Table ID     "VMGENID"
+ *     OEM Revision     0x00000001 (1)
+ *     Compiler ID      "BXPC"
+ *     Compiler Version 0x00000001 (1)
+ */
+DefinitionBlock ("/sys/firmware/acpi/tables/SSDT.aml", "SSDT", 1, "BOCHS ",
+"VMGENID", 0x00000001)
+{
+    Name (VGIA, 0x07FFF000)
+    Scope (\_SB)
+    {
+        Device (VGEN)
+        {
+            Name (_HID, "QEMUVGID")  // _HID: Hardware ID
+            Name (_CID, "VM_Gen_Counter")  // _CID: Compatible ID
+            Name (_DDN, "VM_Gen_Counter")  // _DDN: DOS Device Name
+            Method (_STA, 0, NotSerialized)  // _STA: Status
+            {
+                Local0 = 0x0F
+                If ((VGIA == Zero))
+                {
+                    Local0 = Zero
+                }
+
+                Return (Local0)
+            }
+
+            Method (ADDR, 0, NotSerialized)
+            {
+                Local0 = Package (0x02) {}
+                Index (Local0, Zero) = (VGIA + 0x28)
+                Index (Local0, One) = Zero
+                Return (Local0)
+            }
+        }
+    }
+
+    Method (\_GPE._E05, 0, NotSerialized)  // _Exx: Edge-Triggered GPE
+    {
+        Notify (\_SB.VGEN, 0x80) // Status Change
+    }
+}
+
+
+Design Details:
+---------------
+
+Requirements R1a through R1e dictate that the memory holding the
+VM Generation ID must be allocated and owned by the guest firmware,
+in this case BIOS or UEFI.  However, to be useful, QEMU must be able to
+change the contents of the memory at runtime, specifically when starting a
+backed-up or snapshotted image.  In order to do this, QEMU must know the
+address that has been allocated.
+
+The mechanism chosen for this memory sharing is writeable fw_cfg blobs.
+These are data object that are visible to both QEMU and guests, and are
+addressable as sequential files.
+
+More information about fw_cfg can be found in "docs/specs/fw_cfg.txt"
+
+Two fw_cfg blobs are used in this case:
+
+/etc/vmgenid_guid - contains the actual VM Generation ID GUID
+                  - read-only to the guest
+/etc/vmgenid_addr - contains the address of the downloaded vmgenid blob
+                  - writeable by the guest
+
+
+QEMU sends the following commands to the guest at startup:
+
+1. Allocate memory for vmgenid_guid fw_cfg blob.
+2. Write the address of vmgenid_guid into the SSDT (VGIA ACPI variable as
+   shown above in the iasl dump).  Note that this change is not propagated
+   back to QEMU.
+3. Write the address of vmgenid_guid back to QEMU's copy of vmgenid_addr
+   via the fw_cfg DMA interface.
+
+After step 3, QEMU is able to update the contents of vmgenid_guid at will.
+
+Since BIOS or UEFI does not necessarily run when we wish to change the GUID,
+the value of VGIA is persisted via the VMState mechanism.
+
+As spelled out in the specification, any change to the GUID executes an
+ACPI notification.  The exact handler to use is not specified, so the vmgenid
+device uses the first unused one:  \_GPE._E05.
+
+
+Endian-ness Considerations:
+---------------------------
+
+Although not specified in Microsoft's document, it is assumed that the
+device is expected to use little-endian format.
+
+All GUID passed in via command line or monitor are treated as big-endian.
+GUID values displayed via monitor are shown in big-endian format.
+
+
+GUID Storage Format:
+--------------------
+
+In order to implement an OVMF "SDT Header Probe Suppressor", the contents of
+the vmgenid_guid fw_cfg blob are not simply a 128-bit GUID.  There is also
+significant padding in order to align and fill a memory page, as shown in the
+following diagram:
+
++----------------------------------+
+| SSDT with OEM Table ID = VMGENID |
++----------------------------------+
+| ...                              |       TOP OF PAGE
+| VGIA dword object ---------------|-----> +---------------------------+
+| ...                              |       | fw-allocated array for    |
+| _STA method referring to VGIA    |       | "etc/vmgenid_guid"        |
+| ...                              |       +---------------------------+
+| ADDR method referring to VGIA    |       |  0: OVMF SDT Header probe |
+| ...                              |       |     suppressor            |
++----------------------------------+       | 36: padding for 8-byte    |
+                                           |     alignment             |
+                                           | 40: GUID                  |
+                                           | 56: padding to page size  |
+                                           +---------------------------+
+                                           END OF PAGE
+
+
+Device Usage:
+-------------
+
+The device has one property, which may be only be set using the command line:
+
+  guid - sets the value of the GUID.  A special value "auto" instructs
+         QEMU to generate a new random GUID.
+
+For example:
+
+  QEMU  -device vmgenid,guid="324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
+  QEMU  -device vmgenid,guid=auto
+
+The property may be queried via QMP/HMP:
+
+  (QEMU) query-vm-generation-id
+  {"return": {"guid": "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"}}
+
+Setting of this parameter is intentionally left out from the QMP/HMP
+interfaces.  There are no known use cases for changing the GUID once QEMU is
+running, and adding this capability would greatly increase the complexity.