All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID
@ 2017-02-16 23:15 ben
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 1/8] linker-loader: Add new 'write pointer' command ben
                   ` (8 more replies)
  0 siblings, 9 replies; 53+ messages in thread
From: ben @ 2017-02-16 23:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: lersek, mst, imammedo, Ben Warren

From: Ben Warren <ben@skyportsystems.com>

This patch set adds support for passing a GUID to Windows guests.  It is a
re-implementation of previous patch sets written by Igor Mammedov et al, but
this time passing the GUID data as a fw_cfg blob.

This patch set has dependencies on new guest functionality, in particular the
support for a new linker-loader command and the ability to write back data
to QEMU over a DMA link.  Work is in flight in both SeaBIOS and OVMF to support this.

v7->v8:
    - Rebased to top of tree.
    - Fixed two small bugs in "write pointer" function
    - minor re-ordering of data in patches
    - Fixed unit test by adding delays/retries to reading RSDP table

v6->v7:
    - Rebased to top of tree.
    - Added 'src_offset' field to "write pointer" command
    - Reworked unit tests based on feedback
    - various minor changes based on feedback
    - Added entries to MAINTAINERS file

v5->v6:
    - Rebased to top of tree.
    - Changed device from sysbus to a simple device.  This removed the need for
      adding dynamic sysbus support to pc_piix boards.
    - Removed patch that introduced QWORD patching of AML.
    - Removed ability to set GUID via QMP/HMP.
    - Improved comments/documentation in code.

v4->v5:
    - Added significantly more detail to the documentation.
    - Replaced the previously-implemented linker-loader command with a new one:
      "write pointer".  This allows writing the guest address of a fw_cfg blob back
      to an arbitrary offset in a writeable fw_cfg file visible to QEMU.  This will
      require support in SeaBIOS and OVMF (ongoing).
    - Fixed endianness issues throughout.
    - Several styling cleanups.

v3->v4:
    - Rebased to top of tree.
    - Re-added document patch that was accidentally dropped from the last revision.
    - Added VMState functionality so that VGIA is restored properly.
    - Added Unit tests
v2->v3:
    - Added second writeable fw_cfg for storing the VM Generaiton ID
      address.  This uses a new linker-loader command for instructing the
      guest to write back the allocated address.  A patch for SeaBIOS has been
      submitted (https://www.seabios.org/pipermail/seabios/2017-January/011079.html)
      and the resulting binary will need to be pulled into QEMU once accepted.
    - Setting VM Generation ID by command line or qmp/hmp now accepts an "auto"
      value, whereby QEMU generates a random GUID.
    - Incorporated review comments from v2 mainly around code styling and AML syntax
    - Changed to use the E05 ACPI event instead of E00
v1->v2:
    - Removed "changed" boolean parameter as it is unneeded
    - Added ACPI Notify logic
    - Style changes to pass checkpatch.pl
    - Added support for dynamic sysbus to pc_piix boards


Ben Warren (7):
  linker-loader: Add new 'write pointer' command
  docs: VM Generation ID device description
  ACPI: Add vmgenid blob storage to the build tables
  ACPI: Add Virtual Machine Generation ID support
  tests: Move reusable ACPI code into a utility file
  tests: Add unit tests for the VM Generation ID feature
  MAINTAINERS: Add VM Generation ID entries

Igor Mammedov (1):
  qmp/hmp: add query-vm-generation-id and 'info vm-generation-id'
    commands

 MAINTAINERS                          |  11 ++
 default-configs/i386-softmmu.mak     |   1 +
 default-configs/x86_64-softmmu.mak   |   1 +
 docs/specs/vmgenid.txt               | 245 +++++++++++++++++++++++++++++++++
 hmp-commands-info.hx                 |  14 ++
 hmp.c                                |   9 ++
 hmp.h                                |   1 +
 hw/acpi/Makefile.objs                |   1 +
 hw/acpi/aml-build.c                  |   2 +
 hw/acpi/bios-linker-loader.c         |  66 ++++++++-
 hw/acpi/vmgenid.c                    | 258 +++++++++++++++++++++++++++++++++++
 hw/i386/acpi-build.c                 |  16 +++
 include/hw/acpi/acpi_dev_interface.h |   1 +
 include/hw/acpi/aml-build.h          |   1 +
 include/hw/acpi/bios-linker-loader.h |   7 +
 include/hw/acpi/vmgenid.h            |  35 +++++
 qapi-schema.json                     |  20 +++
 stubs/Makefile.objs                  |   1 +
 stubs/vmgenid.c                      |   9 ++
 tests/Makefile.include               |   4 +-
 tests/acpi-utils.c                   |  65 +++++++++
 tests/acpi-utils.h                   |  94 +++++++++++++
 tests/bios-tables-test.c             | 132 ++----------------
 tests/vmgenid-test.c                 | 200 +++++++++++++++++++++++++++
 24 files changed, 1073 insertions(+), 121 deletions(-)
 create mode 100644 docs/specs/vmgenid.txt
 create mode 100644 hw/acpi/vmgenid.c
 create mode 100644 include/hw/acpi/vmgenid.h
 create mode 100644 stubs/vmgenid.c
 create mode 100644 tests/acpi-utils.c
 create mode 100644 tests/acpi-utils.h
 create mode 100644 tests/vmgenid-test.c

-- 
2.7.4

^ permalink raw reply	[flat|nested] 53+ messages in thread

* [Qemu-devel] [PATCH v8 1/8] linker-loader: Add new 'write pointer' command
  2017-02-16 23:15 [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID ben
@ 2017-02-16 23:15 ` ben
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 2/8] docs: VM Generation ID device description ben
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 53+ messages in thread
From: ben @ 2017-02-16 23:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: lersek, mst, imammedo, Ben Warren

From: Ben Warren <ben@skyportsystems.com>

This is similar to the existing 'add pointer' functionality, but instead
of instructing the guest (BIOS or UEFI) to patch memory, it instructs
the guest to write the pointer back to QEMU via a writeable fw_cfg file.

Signed-off-by: Ben Warren <ben@skyportsystems.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
---
 hw/acpi/bios-linker-loader.c         | 66 ++++++++++++++++++++++++++++++++++--
 include/hw/acpi/bios-linker-loader.h |  7 ++++
 2 files changed, 70 insertions(+), 3 deletions(-)

diff --git a/hw/acpi/bios-linker-loader.c b/hw/acpi/bios-linker-loader.c
index d963ebe..046183a 100644
--- a/hw/acpi/bios-linker-loader.c
+++ b/hw/acpi/bios-linker-loader.c
@@ -78,6 +78,21 @@ struct BiosLinkerLoaderEntry {
             uint32_t length;
         } cksum;
 
+        /*
+         * COMMAND_WRITE_POINTER - write the fw_cfg file (originating from
+         * @dest_file) at @wr_pointer.offset, by adding a pointer to
+         * @src_offset within the table originating from @src_file.
+         * 1,2,4 or 8 byte unsigned addition is used depending on
+         * @wr_pointer.size.
+         */
+        struct {
+            char dest_file[BIOS_LINKER_LOADER_FILESZ];
+            char src_file[BIOS_LINKER_LOADER_FILESZ];
+            uint32_t dst_offset;
+            uint32_t src_offset;
+            uint8_t size;
+        } wr_pointer;
+
         /* padding */
         char pad[124];
     };
@@ -85,9 +100,10 @@ struct BiosLinkerLoaderEntry {
 typedef struct BiosLinkerLoaderEntry BiosLinkerLoaderEntry;
 
 enum {
-    BIOS_LINKER_LOADER_COMMAND_ALLOCATE     = 0x1,
-    BIOS_LINKER_LOADER_COMMAND_ADD_POINTER  = 0x2,
-    BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM = 0x3,
+    BIOS_LINKER_LOADER_COMMAND_ALLOCATE          = 0x1,
+    BIOS_LINKER_LOADER_COMMAND_ADD_POINTER       = 0x2,
+    BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM      = 0x3,
+    BIOS_LINKER_LOADER_COMMAND_WRITE_POINTER     = 0x4,
 };
 
 enum {
@@ -278,3 +294,47 @@ void bios_linker_loader_add_pointer(BIOSLinker *linker,
 
     g_array_append_vals(linker->cmd_blob, &entry, sizeof entry);
 }
+
+/*
+ * bios_linker_loader_write_pointer: ask guest to write a pointer to the
+ * source file into the destination file, and write it back to QEMU via
+ * fw_cfg DMA.
+ *
+ * @linker: linker object instance
+ * @dest_file: destination file that must be written
+ * @dst_patched_offset: location within destination file blob to be patched
+ *                      with the pointer to @src_file, in bytes
+ * @dst_patched_offset_size: size of the pointer to be patched
+ *                      at @dst_patched_offset in @dest_file blob, in bytes
+ * @src_file: source file who's address must be taken
+ * @src_offset: location within source file blob to which
+ *              @dest_file+@dst_patched_offset will point to after
+ *              firmware's executed WRITE_POINTER command
+ */
+void bios_linker_loader_write_pointer(BIOSLinker *linker,
+                                    const char *dest_file,
+                                    uint32_t dst_patched_offset,
+                                    uint8_t dst_patched_size,
+                                    const char *src_file,
+                                    uint32_t src_offset)
+{
+    BiosLinkerLoaderEntry entry;
+    const BiosLinkerFileEntry *source_file =
+        bios_linker_find_file(linker, src_file);
+
+    assert(source_file);
+    assert(src_offset < source_file->blob->len);
+    memset(&entry, 0, sizeof entry);
+    strncpy(entry.wr_pointer.dest_file, dest_file,
+            sizeof entry.wr_pointer.dest_file - 1);
+    strncpy(entry.wr_pointer.src_file, src_file,
+            sizeof entry.wr_pointer.src_file - 1);
+    entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_WRITE_POINTER);
+    entry.wr_pointer.dst_offset = cpu_to_le32(dst_patched_offset);
+    entry.wr_pointer.src_offset = cpu_to_le32(src_offset);
+    entry.wr_pointer.size = dst_patched_size;
+    assert(dst_patched_size == 1 || dst_patched_size == 2 ||
+           dst_patched_size == 4 || dst_patched_size == 8);
+
+    g_array_append_vals(linker->cmd_blob, &entry, sizeof entry);
+}
diff --git a/include/hw/acpi/bios-linker-loader.h b/include/hw/acpi/bios-linker-loader.h
index fa1e5d1..efe17b0 100644
--- a/include/hw/acpi/bios-linker-loader.h
+++ b/include/hw/acpi/bios-linker-loader.h
@@ -26,5 +26,12 @@ void bios_linker_loader_add_pointer(BIOSLinker *linker,
                                     const char *src_file,
                                     uint32_t src_offset);
 
+void bios_linker_loader_write_pointer(BIOSLinker *linker,
+                                      const char *dest_file,
+                                      uint32_t dst_patched_offset,
+                                      uint8_t dst_patched_size,
+                                      const char *src_file,
+                                      uint32_t src_offset);
+
 void bios_linker_loader_cleanup(BIOSLinker *linker);
 #endif
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [Qemu-devel] [PATCH v8 2/8] docs: VM Generation ID device description
  2017-02-16 23:15 [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID ben
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 1/8] linker-loader: Add new 'write pointer' command ben
@ 2017-02-16 23:15 ` ben
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 3/8] ACPI: Add vmgenid blob storage to the build tables ben
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 53+ messages in thread
From: ben @ 2017-02-16 23:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: lersek, mst, imammedo, Ben Warren, Gal Hammer

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>
---
 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 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.
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [Qemu-devel] [PATCH v8 3/8] ACPI: Add vmgenid blob storage to the build tables
  2017-02-16 23:15 [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID ben
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 1/8] linker-loader: Add new 'write pointer' command ben
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 2/8] docs: VM Generation ID device description ben
@ 2017-02-16 23:15 ` ben
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support ben
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 53+ messages in thread
From: ben @ 2017-02-16 23:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: lersek, mst, imammedo, Ben Warren

From: Ben Warren <ben@skyportsystems.com>

This allows them to be centrally initialized and destroyed

The "AcpiBuildTables.vmgenid" array will be used to construct the
"etc/vmgenid_guid" fw_cfg blob.

Its contents will be linked into fw_cfg after being built on the
pc_machine_done() -> acpi_setup() -> acpi_build() call path, and dropped
without use on the subsequent, guest triggered, acpi_build_update() ->
acpi_build() call path.

Signed-off-by: Ben Warren <ben@skyportsystems.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
---
 hw/acpi/aml-build.c         | 2 ++
 include/hw/acpi/aml-build.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index b2a1e40..c6f2032 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1559,6 +1559,7 @@ void acpi_build_tables_init(AcpiBuildTables *tables)
     tables->rsdp = g_array_new(false, true /* clear */, 1);
     tables->table_data = g_array_new(false, true /* clear */, 1);
     tables->tcpalog = g_array_new(false, true /* clear */, 1);
+    tables->vmgenid = g_array_new(false, true /* clear */, 1);
     tables->linker = bios_linker_loader_init();
 }
 
@@ -1568,6 +1569,7 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
     g_array_free(tables->rsdp, true);
     g_array_free(tables->table_data, true);
     g_array_free(tables->tcpalog, mfre);
+    g_array_free(tables->vmgenid, mfre);
 }
 
 /* Build rsdt table */
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 559326c..00c21f1 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -210,6 +210,7 @@ struct AcpiBuildTables {
     GArray *table_data;
     GArray *rsdp;
     GArray *tcpalog;
+    GArray *vmgenid;
     BIOSLinker *linker;
 } AcpiBuildTables;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-16 23:15 [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID ben
                   ` (2 preceding siblings ...)
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 3/8] ACPI: Add vmgenid blob storage to the build tables ben
@ 2017-02-16 23:15 ` ben
  2017-02-17 10:43   ` Igor Mammedov
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 5/8] qmp/hmp: add query-vm-generation-id and 'info vm-generation-id' commands ben
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 53+ messages in thread
From: ben @ 2017-02-16 23:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: lersek, mst, imammedo, Ben Warren

From: Ben Warren <ben@skyportsystems.com>

This implements the VM Generation ID feature by passing a 128-bit
GUID to the guest via a fw_cfg blob.
Any time the GUID changes, an ACPI notify event is sent to the guest

The user interface is a simple device with one parameter:
 - guid (string, must be "auto" or in UUID format
   xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)

Signed-off-by: Ben Warren <ben@skyportsystems.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
---
 default-configs/i386-softmmu.mak     |   1 +
 default-configs/x86_64-softmmu.mak   |   1 +
 hw/acpi/Makefile.objs                |   1 +
 hw/acpi/vmgenid.c                    | 242 +++++++++++++++++++++++++++++++++++
 hw/i386/acpi-build.c                 |  16 +++
 include/hw/acpi/acpi_dev_interface.h |   1 +
 include/hw/acpi/vmgenid.h            |  35 +++++
 7 files changed, 297 insertions(+)
 create mode 100644 hw/acpi/vmgenid.c
 create mode 100644 include/hw/acpi/vmgenid.h

diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 48b07a4..029e952 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -59,3 +59,4 @@ CONFIG_I82801B11=y
 CONFIG_SMBIOS=y
 CONFIG_HYPERV_TESTDEV=$(CONFIG_KVM)
 CONFIG_PXB=y
+CONFIG_ACPI_VMGENID=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index fd96345..d1d7432 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -59,3 +59,4 @@ CONFIG_I82801B11=y
 CONFIG_SMBIOS=y
 CONFIG_HYPERV_TESTDEV=$(CONFIG_KVM)
 CONFIG_PXB=y
+CONFIG_ACPI_VMGENID=y
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index 6acf798..11c35bc 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -5,6 +5,7 @@ common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o
 common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o
 common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o
 common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
+common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o
 common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
 
 common-obj-y += acpi_interface.o
diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c
new file mode 100644
index 0000000..c8465df
--- /dev/null
+++ b/hw/acpi/vmgenid.c
@@ -0,0 +1,242 @@
+/*
+ *  Virtual Machine Generation ID Device
+ *
+ *  Copyright (C) 2017 Skyport Systems.
+ *
+ *  Author: Ben Warren <ben@skyportsystems.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 "qemu/osdep.h"
+#include "qmp-commands.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/acpi/vmgenid.h"
+#include "hw/nvram/fw_cfg.h"
+#include "sysemu/sysemu.h"
+
+void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid,
+                        BIOSLinker *linker)
+{
+    Aml *ssdt, *dev, *scope, *method, *addr, *if_ctx;
+    uint32_t vgia_offset;
+    QemuUUID guid_le;
+
+    /* Fill in the GUID values.  These need to be converted to little-endian
+     * first, since that's what the guest expects
+     */
+    g_array_set_size(guid, VMGENID_FW_CFG_SIZE - ARRAY_SIZE(guid_le.data));
+    guid_le = vms->guid;
+    qemu_uuid_bswap(&guid_le);
+    /* The GUID is written at a fixed offset into the fw_cfg file
+     * in order to implement the "OVMF SDT Header probe suppressor"
+     * see docs/specs/vmgenid.txt for more details
+     */
+    g_array_insert_vals(guid, VMGENID_GUID_OFFSET, guid_le.data,
+                        ARRAY_SIZE(guid_le.data));
+
+    /* Put this in a separate SSDT table */
+    ssdt = init_aml_allocator();
+
+    /* Reserve space for header */
+    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
+
+    /* Storage for the GUID address */
+    vgia_offset = table_data->len +
+        build_append_named_dword(ssdt->buf, "VGIA");
+    scope = aml_scope("\\_SB");
+    dev = aml_device("VGEN");
+    aml_append(dev, aml_name_decl("_HID", aml_string("QEMUVGID")));
+    aml_append(dev, aml_name_decl("_CID", aml_string("VM_Gen_Counter")));
+    aml_append(dev, aml_name_decl("_DDN", aml_string("VM_Gen_Counter")));
+
+    /* Simple status method to check that address is linked and non-zero */
+    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
+    addr = aml_local(0);
+    aml_append(method, aml_store(aml_int(0xf), addr));
+    if_ctx = aml_if(aml_equal(aml_name("VGIA"), aml_int(0)));
+    aml_append(if_ctx, aml_store(aml_int(0), addr));
+    aml_append(method, if_ctx);
+    aml_append(method, aml_return(addr));
+    aml_append(dev, method);
+
+    /* the ADDR method returns two 32-bit words representing the lower and
+     * upper halves * of the physical address of the fw_cfg blob
+     * (holding the GUID)
+     */
+    method = aml_method("ADDR", 0, AML_NOTSERIALIZED);
+
+    addr = aml_local(0);
+    aml_append(method, aml_store(aml_package(2), addr));
+
+    aml_append(method, aml_store(aml_add(aml_name("VGIA"),
+                                         aml_int(VMGENID_GUID_OFFSET), NULL),
+                                 aml_index(addr, aml_int(0))));
+    aml_append(method, aml_store(aml_int(0), aml_index(addr, aml_int(1))));
+    aml_append(method, aml_return(addr));
+
+    aml_append(dev, method);
+    aml_append(scope, dev);
+    aml_append(ssdt, scope);
+
+    /* attach an ACPI notify */
+    method = aml_method("\\_GPE._E05", 0, AML_NOTSERIALIZED);
+    aml_append(method, aml_notify(aml_name("\\_SB.VGEN"), aml_int(0x80)));
+    aml_append(ssdt, method);
+
+    g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len);
+
+    /* Allocate guest memory for the Data fw_cfg blob */
+    bios_linker_loader_alloc(linker, VMGENID_GUID_FW_CFG_FILE, guid, 4096,
+                             false /* page boundary, high memory */);
+
+    /* Patch address of GUID fw_cfg blob into the ADDR fw_cfg blob
+     * so QEMU can write the GUID there.  The address is expected to be
+     * < 4GB, but write 64 bits anyway.
+     * The address that is patched in is offset in order to implement
+     * the "OVMF SDT Header probe suppressor"
+     * see docs/specs/vmgenid.txt for more details.
+     */
+    bios_linker_loader_write_pointer(linker,
+        VMGENID_ADDR_FW_CFG_FILE, 0, sizeof(uint64_t),
+        VMGENID_GUID_FW_CFG_FILE, VMGENID_GUID_OFFSET);
+
+    /* Patch address of GUID fw_cfg blob into the AML so OSPM can retrieve
+     * and read it.  Note that while we provide storage for 64 bits, only
+     * the least-signficant 32 get patched into AML.
+     */
+    bios_linker_loader_add_pointer(linker,
+        ACPI_BUILD_TABLE_FILE, vgia_offset, sizeof(uint32_t),
+        VMGENID_GUID_FW_CFG_FILE, 0);
+
+    build_header(linker, table_data,
+        (void *)(table_data->data + table_data->len - ssdt->buf->len),
+        "SSDT", ssdt->buf->len, 1, NULL, "VMGENID");
+    free_aml_allocator();
+}
+
+void vmgenid_add_fw_cfg(VmGenIdState *vms, FWCfgState *s, GArray *guid)
+{
+    /* Create a read-only fw_cfg file for GUID */
+    fw_cfg_add_file(s, VMGENID_GUID_FW_CFG_FILE, guid->data,
+                    VMGENID_FW_CFG_SIZE);
+    /* Create a read-write fw_cfg file for Address */
+    fw_cfg_add_file_callback(s, VMGENID_ADDR_FW_CFG_FILE, NULL, NULL,
+                             vms->vmgenid_addr_le,
+                             ARRAY_SIZE(vms->vmgenid_addr_le), false);
+}
+
+static void vmgenid_update_guest(VmGenIdState *vms)
+{
+    Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, NULL);
+    uint32_t vmgenid_addr;
+    QemuUUID guid_le;
+
+    if (obj) {
+        /* Write the GUID to guest memory */
+        memcpy(&vmgenid_addr, vms->vmgenid_addr_le, sizeof(vmgenid_addr));
+        vmgenid_addr = le32_to_cpu(vmgenid_addr);
+        /* A zero value in vmgenid_addr means that BIOS has not yet written
+         * the address
+         */
+        if (vmgenid_addr) {
+            /* QemuUUID has the first three words as big-endian, and expect
+             * that any GUIDs passed in will always be BE.  The guest,
+             * however, will expect the fields to be little-endian.
+             * Perform a byte swap immediately before writing.
+             */
+            guid_le = vms->guid;
+            qemu_uuid_bswap(&guid_le);
+            /* The GUID is written at a fixed offset into the fw_cfg file
+             * in order to implement the "OVMF SDT Header probe suppressor"
+             * see docs/specs/vmgenid.txt for more details.
+             */
+            cpu_physical_memory_write(vmgenid_addr, guid_le.data,
+                                      sizeof(guid_le.data));
+            /* Send _GPE.E05 event */
+            acpi_send_event(DEVICE(obj), ACPI_VMGENID_CHANGE_STATUS);
+        }
+    }
+}
+
+static void vmgenid_set_guid(Object *obj, const char *value, Error **errp)
+{
+    VmGenIdState *vms = VMGENID(obj);
+
+    if (!strcmp(value, "auto")) {
+        qemu_uuid_generate(&vms->guid);
+    } else if (qemu_uuid_parse(value, &vms->guid) < 0) {
+        error_setg(errp, "'%s. %s': Failed to parse GUID string: %s",
+                   object_get_typename(OBJECT(vms)), VMGENID_GUID, value);
+        return;
+    }
+
+    vmgenid_update_guest(vms);
+}
+
+/* After restoring an image, we need to update the guest memory and notify
+ * it of a potential change to VM Generation ID
+ */
+static int vmgenid_post_load(void *opaque, int version_id)
+{
+    VmGenIdState *vms = opaque;
+    vmgenid_update_guest(vms);
+    return 0;
+}
+
+static const VMStateDescription vmstate_vmgenid = {
+    .name = "vmgenid",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .post_load = vmgenid_post_load,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8_ARRAY(vmgenid_addr_le, VmGenIdState, sizeof(uint64_t)),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static void vmgenid_handle_reset(void *opaque)
+{
+    VmGenIdState *vms = VMGENID(opaque);
+    /* Clear the guest-allocated GUID address when the VM resets */
+    memset(vms->vmgenid_addr_le, 0, ARRAY_SIZE(vms->vmgenid_addr_le));
+}
+
+static void vmgenid_realize(DeviceState *dev, Error **errp)
+{
+    VmGenIdState *vms = VMGENID(dev);
+    qemu_register_reset(vmgenid_handle_reset, vms);
+}
+
+static void vmgenid_device_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->vmsd = &vmstate_vmgenid;
+    dc->realize = vmgenid_realize;
+    dc->hotpluggable = false;
+
+    object_class_property_add_str(klass, VMGENID_GUID, NULL,
+                                  vmgenid_set_guid, NULL);
+    object_class_property_set_description(klass, VMGENID_GUID,
+                                    "Set Global Unique Identifier "
+                                    "(big-endian) or auto for random value",
+                                    NULL);
+}
+
+static const TypeInfo vmgenid_device_info = {
+    .name          = VMGENID_DEVICE,
+    .parent        = TYPE_DEVICE,
+    .instance_size = sizeof(VmGenIdState),
+    .class_init    = vmgenid_device_class_init,
+};
+
+static void vmgenid_register_types(void)
+{
+    type_register_static(&vmgenid_device_info);
+}
+
+type_init(vmgenid_register_types)
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 1c928ab..db04cf5 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/acpi/vmgenid.h"
 #include "sysemu/tpm_backend.h"
 #include "hw/timer/mc146818rtc_regs.h"
 #include "sysemu/numa.h"
@@ -2610,6 +2611,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
     size_t aml_len = 0;
     GArray *tables_blob = tables->table_data;
     AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
+    Object *vmgenid_dev;
 
     acpi_get_pm_info(&pm);
     acpi_get_misc_info(&misc);
@@ -2653,6 +2655,13 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
     acpi_add_table(table_offsets, tables_blob);
     build_madt(tables_blob, tables->linker, pcms);
 
+    vmgenid_dev = find_vmgenid_dev();
+    if (vmgenid_dev) {
+        acpi_add_table(table_offsets, tables_blob);
+        vmgenid_build_acpi(VMGENID(vmgenid_dev), tables_blob,
+                           tables->vmgenid, tables->linker);
+    }
+
     if (misc.has_hpet) {
         acpi_add_table(table_offsets, tables_blob);
         build_hpet(tables_blob, tables->linker);
@@ -2823,6 +2832,7 @@ void acpi_setup(void)
     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
     AcpiBuildTables tables;
     AcpiBuildState *build_state;
+    Object *vmgenid_dev;
 
     if (!pcms->fw_cfg) {
         ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n");
@@ -2859,6 +2869,12 @@ void acpi_setup(void)
     fw_cfg_add_file(pcms->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
                     tables.tcpalog->data, acpi_data_len(tables.tcpalog));
 
+    vmgenid_dev = find_vmgenid_dev();
+    if (vmgenid_dev) {
+        vmgenid_add_fw_cfg(VMGENID(vmgenid_dev), pcms->fw_cfg,
+                           tables.vmgenid);
+    }
+
     if (!pcmc->rsdp_in_ram) {
         /*
          * Keep for compatibility with old machine types.
diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h
index 71d3c48..3c2e4e9 100644
--- a/include/hw/acpi/acpi_dev_interface.h
+++ b/include/hw/acpi/acpi_dev_interface.h
@@ -11,6 +11,7 @@ typedef enum {
     ACPI_CPU_HOTPLUG_STATUS = 4,
     ACPI_MEMORY_HOTPLUG_STATUS = 8,
     ACPI_NVDIMM_HOTPLUG_STATUS = 16,
+    ACPI_VMGENID_CHANGE_STATUS = 32,
 } AcpiEventStatusBits;
 
 #define TYPE_ACPI_DEVICE_IF "acpi-device-interface"
diff --git a/include/hw/acpi/vmgenid.h b/include/hw/acpi/vmgenid.h
new file mode 100644
index 0000000..db7fa0e
--- /dev/null
+++ b/include/hw/acpi/vmgenid.h
@@ -0,0 +1,35 @@
+#ifndef ACPI_VMGENID_H
+#define ACPI_VMGENID_H
+
+#include "hw/acpi/bios-linker-loader.h"
+#include "hw/qdev.h"
+#include "qemu/uuid.h"
+
+#define VMGENID_DEVICE           "vmgenid"
+#define VMGENID_GUID             "guid"
+#define VMGENID_GUID_FW_CFG_FILE      "etc/vmgenid_guid"
+#define VMGENID_ADDR_FW_CFG_FILE      "etc/vmgenid_addr"
+
+#define VMGENID_FW_CFG_SIZE      4096 /* Occupy a page of memory */
+#define VMGENID_GUID_OFFSET      40   /* allow space for
+                                       * OVMF SDT Header Probe Supressor
+                                       */
+
+#define VMGENID(obj) OBJECT_CHECK(VmGenIdState, (obj), VMGENID_DEVICE)
+
+typedef struct VmGenIdState {
+    DeviceClass parent_obj;
+    QemuUUID guid;                /* The 128-bit GUID seen by the guest */
+    uint8_t vmgenid_addr_le[8];   /* Address of the GUID (little-endian) */
+} VmGenIdState;
+
+static inline Object *find_vmgenid_dev(void)
+{
+    return object_resolve_path_type("", VMGENID_DEVICE, NULL);
+}
+
+void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid,
+                        BIOSLinker *linker);
+void vmgenid_add_fw_cfg(VmGenIdState *vms, FWCfgState *s, GArray *guid);
+
+#endif
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [Qemu-devel] [PATCH v8 5/8] qmp/hmp: add query-vm-generation-id and 'info vm-generation-id' commands
  2017-02-16 23:15 [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID ben
                   ` (3 preceding siblings ...)
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support ben
@ 2017-02-16 23:15 ` ben
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 6/8] tests: Move reusable ACPI code into a utility file ben
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 53+ messages in thread
From: ben @ 2017-02-16 23:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: lersek, mst, imammedo, Ben Warren

From: Igor Mammedov <imammedo@redhat.com>

Add commands to query Virtual Machine Generation ID counter.

QMP command example:
    { "execute": "query-vm-generation-id" }

HMP command example:
    info vm-generation-id

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Ben Warren <ben@skyportsystems.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
---
 hmp-commands-info.hx | 14 ++++++++++++++
 hmp.c                |  9 +++++++++
 hmp.h                |  1 +
 hw/acpi/vmgenid.c    | 16 ++++++++++++++++
 qapi-schema.json     | 20 ++++++++++++++++++++
 stubs/Makefile.objs  |  1 +
 stubs/vmgenid.c      |  9 +++++++++
 7 files changed, 70 insertions(+)
 create mode 100644 stubs/vmgenid.c

diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index b0f35e6..a53f105 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -802,6 +802,20 @@ Show information about hotpluggable CPUs
 ETEXI
 
 STEXI
+@item info vm-generation-id
+@findex vm-generation-id
+Show Virtual Machine Generation ID
+ETEXI
+
+    {
+        .name       = "vm-generation-id",
+        .args_type  = "",
+        .params     = "",
+        .help       = "Show Virtual Machine Generation ID",
+        .cmd = hmp_info_vm_generation_id,
+    },
+
+STEXI
 @end table
 ETEXI
 
diff --git a/hmp.c b/hmp.c
index 2bc4f06..535613d 100644
--- a/hmp.c
+++ b/hmp.c
@@ -2565,3 +2565,12 @@ void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict)
 
     qapi_free_HotpluggableCPUList(saved);
 }
+
+void hmp_info_vm_generation_id(Monitor *mon, const QDict *qdict)
+{
+    GuidInfo *info = qmp_query_vm_generation_id(NULL);
+    if (info) {
+        monitor_printf(mon, "%s\n", info->guid);
+    }
+    qapi_free_GuidInfo(info);
+}
diff --git a/hmp.h b/hmp.h
index 05daf7c..799fd37 100644
--- a/hmp.h
+++ b/hmp.h
@@ -137,5 +137,6 @@ void hmp_rocker_of_dpa_flows(Monitor *mon, const QDict *qdict);
 void hmp_rocker_of_dpa_groups(Monitor *mon, const QDict *qdict);
 void hmp_info_dump(Monitor *mon, const QDict *qdict);
 void hmp_hotpluggable_cpus(Monitor *mon, const QDict *qdict);
+void hmp_info_vm_generation_id(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c
index c8465df..744f284 100644
--- a/hw/acpi/vmgenid.c
+++ b/hw/acpi/vmgenid.c
@@ -240,3 +240,19 @@ static void vmgenid_register_types(void)
 }
 
 type_init(vmgenid_register_types)
+
+GuidInfo *qmp_query_vm_generation_id(Error **errp)
+{
+    GuidInfo *info;
+    VmGenIdState *vms;
+    Object *obj = find_vmgenid_dev();
+
+    if (!obj) {
+        return NULL;
+    }
+    vms = VMGENID(obj);
+
+    info = g_malloc0(sizeof(*info));
+    info->guid = qemu_uuid_unparse_strdup(&vms->guid);
+    return info;
+}
diff --git a/qapi-schema.json b/qapi-schema.json
index 5edb08d..396e49c 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -6056,3 +6056,23 @@
 #
 ##
 { 'command': 'query-hotpluggable-cpus', 'returns': ['HotpluggableCPU'] }
+
+##
+# @GuidInfo:
+#
+# GUID information.
+#
+# @guid: the globally unique identifier
+#
+# Since: 2.9
+##
+{ 'struct': 'GuidInfo', 'data': {'guid': 'str'} }
+
+##
+# @query-vm-generation-id:
+#
+# Show Virtual Machine Generation ID
+#
+# Since 2.9
+##
+{ 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' }
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index a187295..0bffca6 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -35,3 +35,4 @@ stub-obj-y += qmp_pc_dimm_device_list.o
 stub-obj-y += target-monitor-defs.o
 stub-obj-y += target-get-monitor-def.o
 stub-obj-y += pc_madt_cpu_entry.o
+stub-obj-y += vmgenid.o
diff --git a/stubs/vmgenid.c b/stubs/vmgenid.c
new file mode 100644
index 0000000..c64eb7a
--- /dev/null
+++ b/stubs/vmgenid.c
@@ -0,0 +1,9 @@
+#include "qemu/osdep.h"
+#include "qmp-commands.h"
+#include "qapi/qmp/qerror.h"
+
+GuidInfo *qmp_query_vm_generation_id(Error **errp)
+{
+    error_setg(errp, QERR_UNSUPPORTED);
+    return NULL;
+}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [Qemu-devel] [PATCH v8 6/8] tests: Move reusable ACPI code into a utility file
  2017-02-16 23:15 [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID ben
                   ` (4 preceding siblings ...)
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 5/8] qmp/hmp: add query-vm-generation-id and 'info vm-generation-id' commands ben
@ 2017-02-16 23:15 ` ben
  2017-02-20 14:49   ` Igor Mammedov
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 7/8] tests: Add unit tests for the VM Generation ID feature ben
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 53+ messages in thread
From: ben @ 2017-02-16 23:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: lersek, mst, imammedo, Ben Warren

From: Ben Warren <ben@skyportsystems.com>

Also usable by upcoming VM Generation ID tests

Signed-off-by: Ben Warren <ben@skyportsystems.com>
---
 MAINTAINERS              |   2 +
 tests/Makefile.include   |   2 +-
 tests/acpi-utils.c       |  65 +++++++++++++++++++++++
 tests/acpi-utils.h       |  94 +++++++++++++++++++++++++++++++++
 tests/bios-tables-test.c | 132 ++++++-----------------------------------------
 5 files changed, 177 insertions(+), 118 deletions(-)
 create mode 100644 tests/acpi-utils.c
 create mode 100644 tests/acpi-utils.h

diff --git a/MAINTAINERS b/MAINTAINERS
index fb57d8e..81d4baf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -909,6 +909,8 @@ F: hw/acpi/*
 F: hw/smbios/*
 F: hw/i386/acpi-build.[hc]
 F: hw/arm/virt-acpi-build.c
+F: tests/bios-tables-test.c
+F: tests/acpi-utils.[hc]
 
 ppc4xx
 M: Alexander Graf <agraf@suse.de>
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 634394a..143507e 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -667,7 +667,7 @@ tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
 tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y)
 tests/boot-serial-test$(EXESUF): tests/boot-serial-test.o $(libqos-obj-y)
 tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \
-	tests/boot-sector.o $(libqos-obj-y)
+	tests/boot-sector.o tests/acpi-utils.o $(libqos-obj-y)
 tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y)
 tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
 tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y)
diff --git a/tests/acpi-utils.c b/tests/acpi-utils.c
new file mode 100644
index 0000000..41dc1ea
--- /dev/null
+++ b/tests/acpi-utils.c
@@ -0,0 +1,65 @@
+/*
+ * ACPI Utility Functions
+ *
+ * Copyright (c) 2013 Red Hat Inc.
+ * Copyright (c) 2017 Skyport Systems
+ *
+ * Authors:
+ *  Michael S. Tsirkin <mst@redhat.com>,
+ *  Ben Warren <ben@skyportsystems.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 "qemu/osdep.h"
+#include <glib/gstdio.h>
+#include "qemu-common.h"
+#include "hw/smbios/smbios.h"
+#include "qemu/bitmap.h"
+#include "acpi-utils.h"
+#include "boot-sector.h"
+
+uint8_t acpi_calc_checksum(const uint8_t *data, int len)
+{
+    int i;
+    uint8_t sum = 0;
+
+    for (i = 0; i < len; i++) {
+        sum += data[i];
+    }
+
+    return sum;
+}
+
+uint32_t acpi_find_rsdp_address(void)
+{
+    uint32_t off;
+
+    /* RSDP location can vary across a narrow range */
+    for (off = 0xf0000; off < 0x100000; off += 0x10) {
+        uint8_t sig[] = "RSD PTR ";
+        int i;
+
+        for (i = 0; i < sizeof sig - 1; ++i) {
+            sig[i] = readb(off + i);
+        }
+
+        if (!memcmp(sig, "RSD PTR ", sizeof sig)) {
+            break;
+        }
+    }
+    return off;
+}
+
+void acpi_parse_rsdp_table(uint32_t addr, AcpiRsdpDescriptor *rsdp_table)
+{
+    ACPI_READ_FIELD(rsdp_table->signature, addr);
+    ACPI_ASSERT_CMP64(rsdp_table->signature, "RSD PTR ");
+
+    ACPI_READ_FIELD(rsdp_table->checksum, addr);
+    ACPI_READ_ARRAY(rsdp_table->oem_id, addr);
+    ACPI_READ_FIELD(rsdp_table->revision, addr);
+    ACPI_READ_FIELD(rsdp_table->rsdt_physical_address, addr);
+    ACPI_READ_FIELD(rsdp_table->length, addr);
+}
diff --git a/tests/acpi-utils.h b/tests/acpi-utils.h
new file mode 100644
index 0000000..9f9a2d5
--- /dev/null
+++ b/tests/acpi-utils.h
@@ -0,0 +1,94 @@
+/*
+ * Utilities for working with ACPI tables
+ *
+ * Copyright (c) 2013 Red Hat Inc.
+ *
+ * Authors:
+ *  Michael S. Tsirkin <mst@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 TEST_ACPI_UTILS_H
+#define TEST_ACPI_UTILS_H
+
+#include "hw/acpi/acpi-defs.h"
+#include "libqtest.h"
+
+/* DSDT and SSDTs format */
+typedef struct {
+    AcpiTableHeader header;
+    gchar *aml;            /* aml bytecode from guest */
+    gsize aml_len;
+    gchar *aml_file;
+    gchar *asl;            /* asl code generated from aml */
+    gsize asl_len;
+    gchar *asl_file;
+    bool tmp_files_retain;   /* do not delete the temp asl/aml */
+} QEMU_PACKED AcpiSdtTable;
+
+#define ACPI_READ_FIELD(field, addr)           \
+    do {                                       \
+        switch (sizeof(field)) {               \
+        case 1:                                \
+            field = readb(addr);               \
+            break;                             \
+        case 2:                                \
+            field = readw(addr);               \
+            break;                             \
+        case 4:                                \
+            field = readl(addr);               \
+            break;                             \
+        case 8:                                \
+            field = readq(addr);               \
+            break;                             \
+        default:                               \
+            g_assert(false);                   \
+        }                                      \
+        addr += sizeof(field);                  \
+    } while (0);
+
+#define ACPI_READ_ARRAY_PTR(arr, length, addr)  \
+    do {                                        \
+        int idx;                                \
+        for (idx = 0; idx < length; ++idx) {    \
+            ACPI_READ_FIELD(arr[idx], addr);    \
+        }                                       \
+    } while (0);
+
+#define ACPI_READ_ARRAY(arr, addr)                               \
+    ACPI_READ_ARRAY_PTR(arr, sizeof(arr) / sizeof(arr[0]), addr)
+
+#define ACPI_READ_TABLE_HEADER(table, addr)                      \
+    do {                                                         \
+        ACPI_READ_FIELD((table)->signature, addr);               \
+        ACPI_READ_FIELD((table)->length, addr);                  \
+        ACPI_READ_FIELD((table)->revision, addr);                \
+        ACPI_READ_FIELD((table)->checksum, addr);                \
+        ACPI_READ_ARRAY((table)->oem_id, addr);                  \
+        ACPI_READ_ARRAY((table)->oem_table_id, addr);            \
+        ACPI_READ_FIELD((table)->oem_revision, addr);            \
+        ACPI_READ_ARRAY((table)->asl_compiler_id, addr);         \
+        ACPI_READ_FIELD((table)->asl_compiler_revision, addr);   \
+    } while (0);
+
+#define ACPI_ASSERT_CMP(actual, expected) do { \
+    uint32_t ACPI_ASSERT_CMP_le = cpu_to_le32(actual); \
+    char ACPI_ASSERT_CMP_str[5] = {}; \
+    memcpy(ACPI_ASSERT_CMP_str, &ACPI_ASSERT_CMP_le, 4); \
+    g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
+} while (0)
+
+#define ACPI_ASSERT_CMP64(actual, expected) do { \
+    uint64_t ACPI_ASSERT_CMP_le = cpu_to_le64(actual); \
+    char ACPI_ASSERT_CMP_str[9] = {}; \
+    memcpy(ACPI_ASSERT_CMP_str, &ACPI_ASSERT_CMP_le, 8); \
+    g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
+} while (0)
+
+uint8_t acpi_calc_checksum(const uint8_t *data, int len);
+uint32_t acpi_find_rsdp_address(void);
+void acpi_parse_rsdp_table(uint32_t addr, AcpiRsdpDescriptor *rsdp_table);
+
+#endif  /* TEST_ACPI_UTILS_H */
diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index 5404805..423a6f5 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -13,10 +13,9 @@
 #include "qemu/osdep.h"
 #include <glib/gstdio.h>
 #include "qemu-common.h"
-#include "libqtest.h"
-#include "hw/acpi/acpi-defs.h"
 #include "hw/smbios/smbios.h"
 #include "qemu/bitmap.h"
+#include "acpi-utils.h"
 #include "boot-sector.h"
 
 #define MACHINE_PC "pc"
@@ -24,18 +23,6 @@
 
 #define ACPI_REBUILD_EXPECTED_AML "TEST_ACPI_REBUILD_AML"
 
-/* DSDT and SSDTs format */
-typedef struct {
-    AcpiTableHeader header;
-    gchar *aml;            /* aml bytecode from guest */
-    gsize aml_len;
-    gchar *aml_file;
-    gchar *asl;            /* asl code generated from aml */
-    gsize asl_len;
-    gchar *asl_file;
-    bool tmp_files_retain;   /* do not delete the temp asl/aml */
-} QEMU_PACKED AcpiSdtTable;
-
 typedef struct {
     const char *machine;
     const char *variant;
@@ -53,65 +40,6 @@ typedef struct {
     int required_struct_types_len;
 } test_data;
 
-#define ACPI_READ_FIELD(field, addr)           \
-    do {                                       \
-        switch (sizeof(field)) {               \
-        case 1:                                \
-            field = readb(addr);               \
-            break;                             \
-        case 2:                                \
-            field = readw(addr);               \
-            break;                             \
-        case 4:                                \
-            field = readl(addr);               \
-            break;                             \
-        case 8:                                \
-            field = readq(addr);               \
-            break;                             \
-        default:                               \
-            g_assert(false);                   \
-        }                                      \
-        addr += sizeof(field);                  \
-    } while (0);
-
-#define ACPI_READ_ARRAY_PTR(arr, length, addr)  \
-    do {                                        \
-        int idx;                                \
-        for (idx = 0; idx < length; ++idx) {    \
-            ACPI_READ_FIELD(arr[idx], addr);    \
-        }                                       \
-    } while (0);
-
-#define ACPI_READ_ARRAY(arr, addr)                               \
-    ACPI_READ_ARRAY_PTR(arr, sizeof(arr)/sizeof(arr[0]), addr)
-
-#define ACPI_READ_TABLE_HEADER(table, addr)                      \
-    do {                                                         \
-        ACPI_READ_FIELD((table)->signature, addr);               \
-        ACPI_READ_FIELD((table)->length, addr);                  \
-        ACPI_READ_FIELD((table)->revision, addr);                \
-        ACPI_READ_FIELD((table)->checksum, addr);                \
-        ACPI_READ_ARRAY((table)->oem_id, addr);                  \
-        ACPI_READ_ARRAY((table)->oem_table_id, addr);            \
-        ACPI_READ_FIELD((table)->oem_revision, addr);            \
-        ACPI_READ_ARRAY((table)->asl_compiler_id, addr);         \
-        ACPI_READ_FIELD((table)->asl_compiler_revision, addr);   \
-    } while (0);
-
-#define ACPI_ASSERT_CMP(actual, expected) do { \
-    uint32_t ACPI_ASSERT_CMP_le = cpu_to_le32(actual); \
-    char ACPI_ASSERT_CMP_str[5] = {}; \
-    memcpy(ACPI_ASSERT_CMP_str, &ACPI_ASSERT_CMP_le, 4); \
-    g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
-} while (0)
-
-#define ACPI_ASSERT_CMP64(actual, expected) do { \
-    uint64_t ACPI_ASSERT_CMP_le = cpu_to_le64(actual); \
-    char ACPI_ASSERT_CMP_str[9] = {}; \
-    memcpy(ACPI_ASSERT_CMP_str, &ACPI_ASSERT_CMP_le, 8); \
-    g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
-} while (0)
-
 static char disk[] = "tests/acpi-test-disk-XXXXXX";
 static const char *data_dir = "tests/acpi-test-data";
 #ifdef CONFIG_IASL
@@ -147,36 +75,9 @@ static void free_test_data(test_data *data)
     g_array_free(data->tables, false);
 }
 
-static uint8_t acpi_checksum(const uint8_t *data, int len)
-{
-    int i;
-    uint8_t sum = 0;
-
-    for (i = 0; i < len; i++) {
-        sum += data[i];
-    }
-
-    return sum;
-}
-
 static void test_acpi_rsdp_address(test_data *data)
 {
-    uint32_t off;
-
-    /* OK, now find RSDP */
-    for (off = 0xf0000; off < 0x100000; off += 0x10) {
-        uint8_t sig[] = "RSD PTR ";
-        int i;
-
-        for (i = 0; i < sizeof sig - 1; ++i) {
-            sig[i] = readb(off + i);
-        }
-
-        if (!memcmp(sig, "RSD PTR ", sizeof sig)) {
-            break;
-        }
-    }
-
+    uint32_t off = acpi_find_rsdp_address();
     g_assert_cmphex(off, <, 0x100000);
     data->rsdp_addr = off;
 }
@@ -186,17 +87,10 @@ static void test_acpi_rsdp_table(test_data *data)
     AcpiRsdpDescriptor *rsdp_table = &data->rsdp_table;
     uint32_t addr = data->rsdp_addr;
 
-    ACPI_READ_FIELD(rsdp_table->signature, addr);
-    ACPI_ASSERT_CMP64(rsdp_table->signature, "RSD PTR ");
-
-    ACPI_READ_FIELD(rsdp_table->checksum, addr);
-    ACPI_READ_ARRAY(rsdp_table->oem_id, addr);
-    ACPI_READ_FIELD(rsdp_table->revision, addr);
-    ACPI_READ_FIELD(rsdp_table->rsdt_physical_address, addr);
-    ACPI_READ_FIELD(rsdp_table->length, addr);
+    acpi_parse_rsdp_table(addr, rsdp_table);
 
     /* rsdp checksum is not for the whole table, but for the first 20 bytes */
-    g_assert(!acpi_checksum((uint8_t *)rsdp_table, 20));
+    g_assert(!acpi_calc_checksum((uint8_t *)rsdp_table, 20));
 }
 
 static void test_acpi_rsdt_table(test_data *data)
@@ -220,8 +114,9 @@ static void test_acpi_rsdt_table(test_data *data)
     tables = g_new0(uint32_t, tables_nr);
     ACPI_READ_ARRAY_PTR(tables, tables_nr, addr);
 
-    checksum = acpi_checksum((uint8_t *)rsdt_table, rsdt_table->length) +
-               acpi_checksum((uint8_t *)tables, tables_nr * sizeof(uint32_t));
+    checksum = acpi_calc_checksum((uint8_t *)rsdt_table, rsdt_table->length) +
+               acpi_calc_checksum((uint8_t *)tables,
+                                  tables_nr * sizeof(uint32_t));
     g_assert(!checksum);
 
    /* SSDT tables after FADT */
@@ -279,7 +174,7 @@ static void test_acpi_fadt_table(test_data *data)
     ACPI_READ_FIELD(fadt_table->flags, addr);
 
     ACPI_ASSERT_CMP(fadt_table->signature, "FACP");
-    g_assert(!acpi_checksum((uint8_t *)fadt_table, fadt_table->length));
+    g_assert(!acpi_calc_checksum((uint8_t *)fadt_table, fadt_table->length));
 }
 
 static void test_acpi_facs_table(test_data *data)
@@ -308,8 +203,10 @@ static void test_dst_table(AcpiSdtTable *sdt_table, uint32_t addr)
     sdt_table->aml = g_malloc0(sdt_table->aml_len);
     ACPI_READ_ARRAY_PTR(sdt_table->aml, sdt_table->aml_len, addr);
 
-    checksum = acpi_checksum((uint8_t *)sdt_table, sizeof(AcpiTableHeader)) +
-               acpi_checksum((uint8_t *)sdt_table->aml, sdt_table->aml_len);
+    checksum = acpi_calc_checksum((uint8_t *)sdt_table,
+                                  sizeof(AcpiTableHeader)) +
+               acpi_calc_checksum((uint8_t *)sdt_table->aml,
+                                  sdt_table->aml_len);
     g_assert(!checksum);
 }
 
@@ -608,8 +505,9 @@ static bool smbios_ep_table_ok(test_data *data)
         return false;
     }
     ACPI_READ_FIELD(ep_table->smbios_bcd_revision, addr);
-    if (acpi_checksum((uint8_t *)ep_table, sizeof *ep_table) ||
-        acpi_checksum((uint8_t *)ep_table + 0x10, sizeof *ep_table - 0x10)) {
+    if (acpi_calc_checksum((uint8_t *)ep_table, sizeof *ep_table) ||
+        acpi_calc_checksum((uint8_t *)ep_table + 0x10,
+                           sizeof *ep_table - 0x10)) {
         return false;
     }
     return true;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [Qemu-devel] [PATCH v8 7/8] tests: Add unit tests for the VM Generation ID feature
  2017-02-16 23:15 [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID ben
                   ` (5 preceding siblings ...)
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 6/8] tests: Move reusable ACPI code into a utility file ben
@ 2017-02-16 23:15 ` ben
  2017-02-20 14:49   ` Igor Mammedov
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 8/8] MAINTAINERS: Add VM Generation ID entries ben
  2017-02-20 14:57 ` [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID Igor Mammedov
  8 siblings, 1 reply; 53+ messages in thread
From: ben @ 2017-02-16 23:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: lersek, mst, imammedo, Ben Warren

From: Ben Warren <ben@skyportsystems.com>

The following tests are implemented:
* test that a GUID passed in by command line is propagated to the guest.
  Read the GUID from guest memory
* test that the "auto" argument to the GUID generates a valid GUID, as
  seen by the guest.
* test that a GUID passed in can be queried from the monitor

  This patch is loosely based on a previous patch from:
  Gal Hammer <ghammer@redhat.com>  and Igor Mammedov <imammedo@redhat.com>

Signed-off-by: Ben Warren <ben@skyportsystems.com>
---
 tests/Makefile.include |   2 +
 tests/vmgenid-test.c   | 200 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 202 insertions(+)
 create mode 100644 tests/vmgenid-test.c

diff --git a/tests/Makefile.include b/tests/Makefile.include
index 143507e..8d36341 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -241,6 +241,7 @@ check-qtest-i386-y += tests/usb-hcd-xhci-test$(EXESUF)
 gcov-files-i386-y += hw/usb/hcd-xhci.c
 check-qtest-i386-y += tests/pc-cpu-test$(EXESUF)
 check-qtest-i386-y += tests/q35-test$(EXESUF)
+check-qtest-i386-y += tests/vmgenid-test$(EXESUF)
 gcov-files-i386-y += hw/pci-host/q35.c
 check-qtest-i386-$(CONFIG_VHOST_NET_TEST_i386) += tests/vhost-user-test$(EXESUF)
 ifeq ($(CONFIG_VHOST_NET_TEST_i386),)
@@ -726,6 +727,7 @@ tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o contrib/ivshmem-server/ivshmem
 tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o contrib/libvhost-user/libvhost-user.o $(test-util-obj-y)
 tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y)
 tests/test-arm-mptimer$(EXESUF): tests/test-arm-mptimer.o
+tests/vmgenid-test$(EXESUF): tests/vmgenid-test.o tests/acpi-utils.o
 
 tests/migration/stress$(EXESUF): tests/migration/stress.o
 	$(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ,"LINK","$(TARGET_DIR)$@")
diff --git a/tests/vmgenid-test.c b/tests/vmgenid-test.c
new file mode 100644
index 0000000..123beae
--- /dev/null
+++ b/tests/vmgenid-test.c
@@ -0,0 +1,200 @@
+/*
+ * QTest testcase for VM Generation ID
+ *
+ * Copyright (c) 2016 Red Hat, Inc.
+ * Copyright (c) 2017 Skyport Systems
+ *
+ * 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 <glib.h>
+#include <string.h>
+#include <unistd.h>
+#include "qemu/osdep.h"
+#include "qemu/bitmap.h"
+#include "qemu/uuid.h"
+#include "hw/acpi/acpi-defs.h"
+#include "acpi-utils.h"
+#include "libqtest.h"
+
+#define VGID_GUID "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
+#define VMGENID_GUID_OFFSET 40   /* allow space for
+                                  * OVMF SDT Header Probe Supressor
+                                  */
+#define RSDP_ADDR_INVALID 0x100000 /* RSDP must be below this address */
+#define RSDP_SLEEP_US     100000   /* Sleep for 100ms between tries */
+#define RSDP_TRIES_MAX    100      /* Max total time is 10 seconds */
+
+typedef struct {
+    AcpiTableHeader header;
+    gchar name_op;
+    gchar vgia[4];
+    gchar val_op;
+    uint32_t vgia_val;
+} QEMU_PACKED VgidTable;
+
+static uint32_t acpi_find_vgia(void)
+{
+    uint32_t off;
+    AcpiRsdpDescriptor rsdp_table;
+    uint32_t rsdt;
+    AcpiRsdtDescriptorRev1 rsdt_table;
+    int tables_nr;
+    uint32_t *tables;
+    AcpiTableHeader ssdt_table;
+    VgidTable vgid_table;
+    int i;
+
+    /* Tables may take a short time to be set up by the guest */
+    for (i = 0; i < RSDP_TRIES_MAX; i++) {
+        off = acpi_find_rsdp_address();
+        if (off < RSDP_ADDR_INVALID) {
+            break;
+        }
+        g_usleep(RSDP_SLEEP_US);
+    }
+    g_assert_cmphex(off, <, RSDP_ADDR_INVALID);
+
+    acpi_parse_rsdp_table(off, &rsdp_table);
+
+    rsdt = rsdp_table.rsdt_physical_address;
+    /* read the header */
+    ACPI_READ_TABLE_HEADER(&rsdt_table, rsdt);
+    ACPI_ASSERT_CMP(rsdt_table.signature, "RSDT");
+
+    /* compute the table entries in rsdt */
+    tables_nr = (rsdt_table.length - sizeof(AcpiRsdtDescriptorRev1)) /
+                sizeof(uint32_t);
+    g_assert_cmpint(tables_nr, >, 0);
+
+    /* get the addresses of the tables pointed by rsdt */
+    tables = g_new0(uint32_t, tables_nr);
+    ACPI_READ_ARRAY_PTR(tables, tables_nr, rsdt);
+
+    for (i = 0; i < tables_nr; i++) {
+        ACPI_READ_TABLE_HEADER(&ssdt_table, tables[i]);
+        if (!strncmp((char *)ssdt_table.oem_table_id, "VMGENID", 7)) {
+            /* the first entry in the table should be VGIA
+             * That's all we need
+             */
+            ACPI_READ_FIELD(vgid_table.name_op, tables[i]);
+            g_assert(vgid_table.name_op == 0x08);  /* name */
+            ACPI_READ_ARRAY(vgid_table.vgia, tables[i]);
+            g_assert(memcmp(vgid_table.vgia, "VGIA", 4) == 0);
+            ACPI_READ_FIELD(vgid_table.val_op, tables[i]);
+            g_assert(vgid_table.val_op == 0x0C);  /* dword */
+            ACPI_READ_FIELD(vgid_table.vgia_val, tables[i]);
+            /* The GUID is written at a fixed offset into the fw_cfg file
+             * in order to implement the "OVMF SDT Header probe suppressor"
+             * see docs/specs/vmgenid.txt for more details
+             */
+            return vgid_table.vgia_val + VMGENID_GUID_OFFSET;
+        }
+    }
+    return 0;
+}
+
+static void read_guid_from_memory(QemuUUID *guid)
+{
+    uint32_t vmgenid_addr;
+    int i;
+
+    vmgenid_addr = acpi_find_vgia();
+    g_assert(vmgenid_addr);
+
+    /* Read the GUID directly from guest memory */
+    for (i = 0; i < 16; i++) {
+        guid->data[i] = readb(vmgenid_addr + i);
+    }
+    /* The GUID is in little-endian format in the guest, while QEMU
+     * uses big-endian.  Swap after reading.
+     */
+    qemu_uuid_bswap(guid);
+}
+
+static void read_guid_from_monitor(QemuUUID *guid)
+{
+    QDict *rsp, *rsp_ret;
+    const char *guid_str;
+
+    rsp = qmp("{ 'execute': 'query-vm-generation-id' }");
+    if (qdict_haskey(rsp, "return")) {
+        rsp_ret = qdict_get_qdict(rsp, "return");
+        g_assert(qdict_haskey(rsp_ret, "guid"));
+        guid_str = qdict_get_str(rsp_ret, "guid");
+        g_assert(qemu_uuid_parse(guid_str, guid) == 0);
+    }
+    QDECREF(rsp);
+}
+
+static void vmgenid_set_guid_test(void)
+{
+    QemuUUID expected, measured;
+    gchar *cmd;
+
+    g_assert(qemu_uuid_parse(VGID_GUID, &expected) == 0);
+
+    cmd = g_strdup_printf("-machine accel=tcg -device vmgenid,id=testvgid,"
+                          "guid=%s", VGID_GUID);
+    qtest_start(cmd);
+
+    /* Read the GUID from accessing guest memory */
+    read_guid_from_memory(&measured);
+    g_assert(memcmp(measured.data, expected.data, sizeof(measured.data)) == 0);
+
+    qtest_quit(global_qtest);
+    g_free(cmd);
+}
+
+static void vmgenid_set_guid_auto_test(void)
+{
+    const char *cmd;
+    QemuUUID measured;
+
+    cmd = "-machine accel=tcg -device vmgenid,id=testvgid," "guid=auto";
+    qtest_start(cmd);
+
+    read_guid_from_memory(&measured);
+
+    /* Just check that the GUID is non-null */
+    g_assert(!qemu_uuid_is_null(&measured));
+
+    qtest_quit(global_qtest);
+}
+
+static void vmgenid_query_monitor_test(void)
+{
+    QemuUUID expected, measured;
+    gchar *cmd;
+
+    g_assert(qemu_uuid_parse(VGID_GUID, &expected) == 0);
+
+    cmd = g_strdup_printf("-machine accel=tcg -device vmgenid,id=testvgid,"
+                          "guid=%s", VGID_GUID);
+    qtest_start(cmd);
+
+    /* Read the GUID via the monitor */
+    read_guid_from_monitor(&measured);
+    g_assert(memcmp(measured.data, expected.data, sizeof(measured.data)) == 0);
+
+    qtest_quit(global_qtest);
+    g_free(cmd);
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+
+    g_test_init(&argc, &argv, NULL);
+
+    qtest_add_func("/vmgenid/vmgenid/set-guid",
+                   vmgenid_set_guid_test);
+    qtest_add_func("/vmgenid/vmgenid/set-guid-auto",
+                   vmgenid_set_guid_auto_test);
+    qtest_add_func("/vmgenid/vmgenid/query-monitor",
+                   vmgenid_query_monitor_test);
+    ret = g_test_run();
+
+    return ret;
+}
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* [Qemu-devel] [PATCH v8 8/8] MAINTAINERS: Add VM Generation ID entries
  2017-02-16 23:15 [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID ben
                   ` (6 preceding siblings ...)
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 7/8] tests: Add unit tests for the VM Generation ID feature ben
@ 2017-02-16 23:15 ` ben
  2017-02-20 14:50   ` Igor Mammedov
  2017-02-20 14:57 ` [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID Igor Mammedov
  8 siblings, 1 reply; 53+ messages in thread
From: ben @ 2017-02-16 23:15 UTC (permalink / raw)
  To: qemu-devel; +Cc: lersek, mst, imammedo, Ben Warren

From: Ben Warren <ben@skyportsystems.com>

Signed-off-by: Ben Warren <ben@skyportsystems.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 MAINTAINERS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 81d4baf..8f5dd35 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1125,6 +1125,15 @@ F: hw/nvram/chrp_nvram.c
 F: include/hw/nvram/chrp_nvram.h
 F: tests/prom-env-test.c
 
+VM Generation ID
+M: Ben Warren <ben@skyportsystems.com>
+S: Maintained
+F: hw/acpi/vmgenid.c
+F: include/hw/acpi/vmgenid.h
+F: docs/specs/vmgenid.txt
+F: tests/vmgenid-test.c
+F: stubs/vmgenid.c
+
 Subsystems
 ----------
 Audio
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support ben
@ 2017-02-17 10:43   ` Igor Mammedov
  2017-02-17 12:50     ` Laszlo Ersek
  2017-02-17 15:33     ` Ben Warren
  0 siblings, 2 replies; 53+ messages in thread
From: Igor Mammedov @ 2017-02-17 10:43 UTC (permalink / raw)
  To: ben; +Cc: qemu-devel, lersek, mst

On Thu, 16 Feb 2017 15:15:36 -0800
ben@skyportsystems.com wrote:

> From: Ben Warren <ben@skyportsystems.com>
> 
> This implements the VM Generation ID feature by passing a 128-bit
> GUID to the guest via a fw_cfg blob.
> Any time the GUID changes, an ACPI notify event is sent to the guest
> 
> The user interface is a simple device with one parameter:
>  - guid (string, must be "auto" or in UUID format
>    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
I've given it some testing with WS2012R2 and v4 patches for Seabios,

Windows is able to read initial GUID allocation and writeback
seems to work somehow:

(qemu) info vm-generation-id 
c109c09b-0e8b-42d5-9b33-8409c9dcd16c

vmgenid client in Windows reads it as 2 following 64bit integers:
42d50e8bc109c09b:6cd1dcc90984339b

However update path/restore from snapshot doesn't
here is as I've tested it:

qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
(qemu) info vm-generation-id 
c109c09b-0e8b-42d5-9b33-8409c9dcd16c
(qemu) stop
(qemu) migrate "exec:gzip -c > STATEFILE.gz" 
(qemu) quit

qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
-incoming "exec: gzip -c -d STATEFILE.gz"
(qemu) info vm-generation-id 
28b587fa-991b-4267-80d7-9cf28b746fe9

guest
 1. doesn't get GPE notification that it must receive
 2. vmgenid client in Windows reads the same value
      42d50e8bc109c09b:6cd1dcc90984339b


> 
> Signed-off-by: Ben Warren <ben@skyportsystems.com>
> Reviewed-by: Igor Mammedov <imammedo@redhat.com>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> Tested-by: Laszlo Ersek <lersek@redhat.com>
> ---
>  default-configs/i386-softmmu.mak     |   1 +
>  default-configs/x86_64-softmmu.mak   |   1 +
>  hw/acpi/Makefile.objs                |   1 +
>  hw/acpi/vmgenid.c                    | 242 +++++++++++++++++++++++++++++++++++
>  hw/i386/acpi-build.c                 |  16 +++
>  include/hw/acpi/acpi_dev_interface.h |   1 +
>  include/hw/acpi/vmgenid.h            |  35 +++++
>  7 files changed, 297 insertions(+)
>  create mode 100644 hw/acpi/vmgenid.c
>  create mode 100644 include/hw/acpi/vmgenid.h
> 
> diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
> index 48b07a4..029e952 100644
> --- a/default-configs/i386-softmmu.mak
> +++ b/default-configs/i386-softmmu.mak
> @@ -59,3 +59,4 @@ CONFIG_I82801B11=y
>  CONFIG_SMBIOS=y
>  CONFIG_HYPERV_TESTDEV=$(CONFIG_KVM)
>  CONFIG_PXB=y
> +CONFIG_ACPI_VMGENID=y
> diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
> index fd96345..d1d7432 100644
> --- a/default-configs/x86_64-softmmu.mak
> +++ b/default-configs/x86_64-softmmu.mak
> @@ -59,3 +59,4 @@ CONFIG_I82801B11=y
>  CONFIG_SMBIOS=y
>  CONFIG_HYPERV_TESTDEV=$(CONFIG_KVM)
>  CONFIG_PXB=y
> +CONFIG_ACPI_VMGENID=y
> diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
> index 6acf798..11c35bc 100644
> --- a/hw/acpi/Makefile.objs
> +++ b/hw/acpi/Makefile.objs
> @@ -5,6 +5,7 @@ common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o
>  common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o
>  common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o
>  common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
> +common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o
>  common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
>  
>  common-obj-y += acpi_interface.o
> diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c
> new file mode 100644
> index 0000000..c8465df
> --- /dev/null
> +++ b/hw/acpi/vmgenid.c
> @@ -0,0 +1,242 @@
> +/*
> + *  Virtual Machine Generation ID Device
> + *
> + *  Copyright (C) 2017 Skyport Systems.
> + *
> + *  Author: Ben Warren <ben@skyportsystems.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 "qemu/osdep.h"
> +#include "qmp-commands.h"
> +#include "hw/acpi/acpi.h"
> +#include "hw/acpi/aml-build.h"
> +#include "hw/acpi/vmgenid.h"
> +#include "hw/nvram/fw_cfg.h"
> +#include "sysemu/sysemu.h"
> +
> +void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid,
> +                        BIOSLinker *linker)
> +{
> +    Aml *ssdt, *dev, *scope, *method, *addr, *if_ctx;
> +    uint32_t vgia_offset;
> +    QemuUUID guid_le;
> +
> +    /* Fill in the GUID values.  These need to be converted to little-endian
> +     * first, since that's what the guest expects
> +     */
> +    g_array_set_size(guid, VMGENID_FW_CFG_SIZE - ARRAY_SIZE(guid_le.data));
> +    guid_le = vms->guid;
> +    qemu_uuid_bswap(&guid_le);
> +    /* The GUID is written at a fixed offset into the fw_cfg file
> +     * in order to implement the "OVMF SDT Header probe suppressor"
> +     * see docs/specs/vmgenid.txt for more details
> +     */
> +    g_array_insert_vals(guid, VMGENID_GUID_OFFSET, guid_le.data,
> +                        ARRAY_SIZE(guid_le.data));
> +
> +    /* Put this in a separate SSDT table */
> +    ssdt = init_aml_allocator();
> +
> +    /* Reserve space for header */
> +    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
> +
> +    /* Storage for the GUID address */
> +    vgia_offset = table_data->len +
> +        build_append_named_dword(ssdt->buf, "VGIA");
> +    scope = aml_scope("\\_SB");
> +    dev = aml_device("VGEN");
> +    aml_append(dev, aml_name_decl("_HID", aml_string("QEMUVGID")));
> +    aml_append(dev, aml_name_decl("_CID", aml_string("VM_Gen_Counter")));
> +    aml_append(dev, aml_name_decl("_DDN", aml_string("VM_Gen_Counter")));
> +
> +    /* Simple status method to check that address is linked and non-zero */
> +    method = aml_method("_STA", 0, AML_NOTSERIALIZED);
> +    addr = aml_local(0);
> +    aml_append(method, aml_store(aml_int(0xf), addr));
> +    if_ctx = aml_if(aml_equal(aml_name("VGIA"), aml_int(0)));
> +    aml_append(if_ctx, aml_store(aml_int(0), addr));
> +    aml_append(method, if_ctx);
> +    aml_append(method, aml_return(addr));
> +    aml_append(dev, method);
> +
> +    /* the ADDR method returns two 32-bit words representing the lower and
> +     * upper halves * of the physical address of the fw_cfg blob
> +     * (holding the GUID)
> +     */
> +    method = aml_method("ADDR", 0, AML_NOTSERIALIZED);
> +
> +    addr = aml_local(0);
> +    aml_append(method, aml_store(aml_package(2), addr));
> +
> +    aml_append(method, aml_store(aml_add(aml_name("VGIA"),
> +                                         aml_int(VMGENID_GUID_OFFSET), NULL),
> +                                 aml_index(addr, aml_int(0))));
> +    aml_append(method, aml_store(aml_int(0), aml_index(addr, aml_int(1))));
> +    aml_append(method, aml_return(addr));
> +
> +    aml_append(dev, method);
> +    aml_append(scope, dev);
> +    aml_append(ssdt, scope);
> +
> +    /* attach an ACPI notify */
> +    method = aml_method("\\_GPE._E05", 0, AML_NOTSERIALIZED);
> +    aml_append(method, aml_notify(aml_name("\\_SB.VGEN"), aml_int(0x80)));
> +    aml_append(ssdt, method);
> +
> +    g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len);
> +
> +    /* Allocate guest memory for the Data fw_cfg blob */
> +    bios_linker_loader_alloc(linker, VMGENID_GUID_FW_CFG_FILE, guid, 4096,
> +                             false /* page boundary, high memory */);
> +
> +    /* Patch address of GUID fw_cfg blob into the ADDR fw_cfg blob
> +     * so QEMU can write the GUID there.  The address is expected to be
> +     * < 4GB, but write 64 bits anyway.
> +     * The address that is patched in is offset in order to implement
> +     * the "OVMF SDT Header probe suppressor"
> +     * see docs/specs/vmgenid.txt for more details.
> +     */
> +    bios_linker_loader_write_pointer(linker,
> +        VMGENID_ADDR_FW_CFG_FILE, 0, sizeof(uint64_t),
> +        VMGENID_GUID_FW_CFG_FILE, VMGENID_GUID_OFFSET);
> +
> +    /* Patch address of GUID fw_cfg blob into the AML so OSPM can retrieve
> +     * and read it.  Note that while we provide storage for 64 bits, only
> +     * the least-signficant 32 get patched into AML.
> +     */
> +    bios_linker_loader_add_pointer(linker,
> +        ACPI_BUILD_TABLE_FILE, vgia_offset, sizeof(uint32_t),
> +        VMGENID_GUID_FW_CFG_FILE, 0);
> +
> +    build_header(linker, table_data,
> +        (void *)(table_data->data + table_data->len - ssdt->buf->len),
> +        "SSDT", ssdt->buf->len, 1, NULL, "VMGENID");
> +    free_aml_allocator();
> +}
> +
> +void vmgenid_add_fw_cfg(VmGenIdState *vms, FWCfgState *s, GArray *guid)
> +{
> +    /* Create a read-only fw_cfg file for GUID */
> +    fw_cfg_add_file(s, VMGENID_GUID_FW_CFG_FILE, guid->data,
> +                    VMGENID_FW_CFG_SIZE);
> +    /* Create a read-write fw_cfg file for Address */
> +    fw_cfg_add_file_callback(s, VMGENID_ADDR_FW_CFG_FILE, NULL, NULL,
> +                             vms->vmgenid_addr_le,
> +                             ARRAY_SIZE(vms->vmgenid_addr_le), false);
> +}
> +
> +static void vmgenid_update_guest(VmGenIdState *vms)
> +{
> +    Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, NULL);
> +    uint32_t vmgenid_addr;
> +    QemuUUID guid_le;
> +
> +    if (obj) {
> +        /* Write the GUID to guest memory */
> +        memcpy(&vmgenid_addr, vms->vmgenid_addr_le, sizeof(vmgenid_addr));
> +        vmgenid_addr = le32_to_cpu(vmgenid_addr);
> +        /* A zero value in vmgenid_addr means that BIOS has not yet written
> +         * the address
> +         */
> +        if (vmgenid_addr) {
> +            /* QemuUUID has the first three words as big-endian, and expect
> +             * that any GUIDs passed in will always be BE.  The guest,
> +             * however, will expect the fields to be little-endian.
> +             * Perform a byte swap immediately before writing.
> +             */
> +            guid_le = vms->guid;
> +            qemu_uuid_bswap(&guid_le);
> +            /* The GUID is written at a fixed offset into the fw_cfg file
> +             * in order to implement the "OVMF SDT Header probe suppressor"
> +             * see docs/specs/vmgenid.txt for more details.
> +             */
> +            cpu_physical_memory_write(vmgenid_addr, guid_le.data,
> +                                      sizeof(guid_le.data));
> +            /* Send _GPE.E05 event */
> +            acpi_send_event(DEVICE(obj), ACPI_VMGENID_CHANGE_STATUS);
> +        }
> +    }
> +}
> +
> +static void vmgenid_set_guid(Object *obj, const char *value, Error **errp)
> +{
> +    VmGenIdState *vms = VMGENID(obj);
> +
> +    if (!strcmp(value, "auto")) {
> +        qemu_uuid_generate(&vms->guid);
> +    } else if (qemu_uuid_parse(value, &vms->guid) < 0) {
> +        error_setg(errp, "'%s. %s': Failed to parse GUID string: %s",
> +                   object_get_typename(OBJECT(vms)), VMGENID_GUID, value);
> +        return;
> +    }
> +
> +    vmgenid_update_guest(vms);
> +}
> +
> +/* After restoring an image, we need to update the guest memory and notify
> + * it of a potential change to VM Generation ID
> + */
> +static int vmgenid_post_load(void *opaque, int version_id)
> +{
> +    VmGenIdState *vms = opaque;
> +    vmgenid_update_guest(vms);
> +    return 0;
> +}
> +
> +static const VMStateDescription vmstate_vmgenid = {
> +    .name = "vmgenid",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .post_load = vmgenid_post_load,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT8_ARRAY(vmgenid_addr_le, VmGenIdState, sizeof(uint64_t)),
> +        VMSTATE_END_OF_LIST()
> +    },
> +};
> +
> +static void vmgenid_handle_reset(void *opaque)
> +{
> +    VmGenIdState *vms = VMGENID(opaque);
> +    /* Clear the guest-allocated GUID address when the VM resets */
> +    memset(vms->vmgenid_addr_le, 0, ARRAY_SIZE(vms->vmgenid_addr_le));
> +}
> +
> +static void vmgenid_realize(DeviceState *dev, Error **errp)
> +{
> +    VmGenIdState *vms = VMGENID(dev);
> +    qemu_register_reset(vmgenid_handle_reset, vms);
> +}
> +
> +static void vmgenid_device_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->vmsd = &vmstate_vmgenid;
> +    dc->realize = vmgenid_realize;
> +    dc->hotpluggable = false;
> +
> +    object_class_property_add_str(klass, VMGENID_GUID, NULL,
> +                                  vmgenid_set_guid, NULL);
> +    object_class_property_set_description(klass, VMGENID_GUID,
> +                                    "Set Global Unique Identifier "
> +                                    "(big-endian) or auto for random value",
> +                                    NULL);
> +}
> +
> +static const TypeInfo vmgenid_device_info = {
> +    .name          = VMGENID_DEVICE,
> +    .parent        = TYPE_DEVICE,
> +    .instance_size = sizeof(VmGenIdState),
> +    .class_init    = vmgenid_device_class_init,
> +};
> +
> +static void vmgenid_register_types(void)
> +{
> +    type_register_static(&vmgenid_device_info);
> +}
> +
> +type_init(vmgenid_register_types)
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 1c928ab..db04cf5 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/acpi/vmgenid.h"
>  #include "sysemu/tpm_backend.h"
>  #include "hw/timer/mc146818rtc_regs.h"
>  #include "sysemu/numa.h"
> @@ -2610,6 +2611,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
>      size_t aml_len = 0;
>      GArray *tables_blob = tables->table_data;
>      AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
> +    Object *vmgenid_dev;
>  
>      acpi_get_pm_info(&pm);
>      acpi_get_misc_info(&misc);
> @@ -2653,6 +2655,13 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
>      acpi_add_table(table_offsets, tables_blob);
>      build_madt(tables_blob, tables->linker, pcms);
>  
> +    vmgenid_dev = find_vmgenid_dev();
> +    if (vmgenid_dev) {
> +        acpi_add_table(table_offsets, tables_blob);
> +        vmgenid_build_acpi(VMGENID(vmgenid_dev), tables_blob,
> +                           tables->vmgenid, tables->linker);
> +    }
> +
>      if (misc.has_hpet) {
>          acpi_add_table(table_offsets, tables_blob);
>          build_hpet(tables_blob, tables->linker);
> @@ -2823,6 +2832,7 @@ void acpi_setup(void)
>      PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
>      AcpiBuildTables tables;
>      AcpiBuildState *build_state;
> +    Object *vmgenid_dev;
>  
>      if (!pcms->fw_cfg) {
>          ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n");
> @@ -2859,6 +2869,12 @@ void acpi_setup(void)
>      fw_cfg_add_file(pcms->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
>                      tables.tcpalog->data, acpi_data_len(tables.tcpalog));
>  
> +    vmgenid_dev = find_vmgenid_dev();
> +    if (vmgenid_dev) {
> +        vmgenid_add_fw_cfg(VMGENID(vmgenid_dev), pcms->fw_cfg,
> +                           tables.vmgenid);
> +    }
> +
>      if (!pcmc->rsdp_in_ram) {
>          /*
>           * Keep for compatibility with old machine types.
> diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h
> index 71d3c48..3c2e4e9 100644
> --- a/include/hw/acpi/acpi_dev_interface.h
> +++ b/include/hw/acpi/acpi_dev_interface.h
> @@ -11,6 +11,7 @@ typedef enum {
>      ACPI_CPU_HOTPLUG_STATUS = 4,
>      ACPI_MEMORY_HOTPLUG_STATUS = 8,
>      ACPI_NVDIMM_HOTPLUG_STATUS = 16,
> +    ACPI_VMGENID_CHANGE_STATUS = 32,
>  } AcpiEventStatusBits;
>  
>  #define TYPE_ACPI_DEVICE_IF "acpi-device-interface"
> diff --git a/include/hw/acpi/vmgenid.h b/include/hw/acpi/vmgenid.h
> new file mode 100644
> index 0000000..db7fa0e
> --- /dev/null
> +++ b/include/hw/acpi/vmgenid.h
> @@ -0,0 +1,35 @@
> +#ifndef ACPI_VMGENID_H
> +#define ACPI_VMGENID_H
> +
> +#include "hw/acpi/bios-linker-loader.h"
> +#include "hw/qdev.h"
> +#include "qemu/uuid.h"
> +
> +#define VMGENID_DEVICE           "vmgenid"
> +#define VMGENID_GUID             "guid"
> +#define VMGENID_GUID_FW_CFG_FILE      "etc/vmgenid_guid"
> +#define VMGENID_ADDR_FW_CFG_FILE      "etc/vmgenid_addr"
> +
> +#define VMGENID_FW_CFG_SIZE      4096 /* Occupy a page of memory */
> +#define VMGENID_GUID_OFFSET      40   /* allow space for
> +                                       * OVMF SDT Header Probe Supressor
> +                                       */
> +
> +#define VMGENID(obj) OBJECT_CHECK(VmGenIdState, (obj), VMGENID_DEVICE)
> +
> +typedef struct VmGenIdState {
> +    DeviceClass parent_obj;
> +    QemuUUID guid;                /* The 128-bit GUID seen by the guest */
> +    uint8_t vmgenid_addr_le[8];   /* Address of the GUID (little-endian) */
> +} VmGenIdState;
> +
> +static inline Object *find_vmgenid_dev(void)
> +{
> +    return object_resolve_path_type("", VMGENID_DEVICE, NULL);
> +}
> +
> +void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid,
> +                        BIOSLinker *linker);
> +void vmgenid_add_fw_cfg(VmGenIdState *vms, FWCfgState *s, GArray *guid);
> +
> +#endif

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-17 10:43   ` Igor Mammedov
@ 2017-02-17 12:50     ` Laszlo Ersek
  2017-02-17 13:05       ` Igor Mammedov
  2017-02-20 10:23       ` Dr. David Alan Gilbert
  2017-02-17 15:33     ` Ben Warren
  1 sibling, 2 replies; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-17 12:50 UTC (permalink / raw)
  To: Igor Mammedov, ben; +Cc: qemu-devel, mst, Dr. David Alan Gilbert (git)

[-- Attachment #1: Type: text/plain, Size: 2225 bytes --]

CC Dave

On 02/17/17 11:43, Igor Mammedov wrote:
> On Thu, 16 Feb 2017 15:15:36 -0800
> ben@skyportsystems.com wrote:
> 
>> From: Ben Warren <ben@skyportsystems.com>
>>
>> This implements the VM Generation ID feature by passing a 128-bit
>> GUID to the guest via a fw_cfg blob.
>> Any time the GUID changes, an ACPI notify event is sent to the guest
>>
>> The user interface is a simple device with one parameter:
>>  - guid (string, must be "auto" or in UUID format
>>    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
> I've given it some testing with WS2012R2 and v4 patches for Seabios,
> 
> Windows is able to read initial GUID allocation and writeback
> seems to work somehow:
> 
> (qemu) info vm-generation-id 
> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
> 
> vmgenid client in Windows reads it as 2 following 64bit integers:
> 42d50e8bc109c09b:6cd1dcc90984339b
> 
> However update path/restore from snapshot doesn't
> here is as I've tested it:
> 
> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
> (qemu) info vm-generation-id 
> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
> (qemu) stop
> (qemu) migrate "exec:gzip -c > STATEFILE.gz" 
> (qemu) quit
> 
> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
> -incoming "exec: gzip -c -d STATEFILE.gz"
> (qemu) info vm-generation-id 
> 28b587fa-991b-4267-80d7-9cf28b746fe9
> 
> guest
>  1. doesn't get GPE notification that it must receive
>  2. vmgenid client in Windows reads the same value
>       42d50e8bc109c09b:6cd1dcc90984339b

Hmmm, I wonder if we need something like this, in vmgenid_post_load():

commit 90c647db8d59e47c9000affc0d81754eb346e939
Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
Date:   Fri Apr 15 12:41:30 2016 +0100

    Fix pflash migration

with the idea being that in a single device's post_load callback, we
shouldn't perform machine-wide actions (post_load is likely for fixing
up the device itself). If machine-wide actions are necessary, we should
temporarily register a "vm change state handler", and do the thing once
that handler is called (when the machine has been loaded fully and is
about to continue execution).

Can you please try the attached patch on top? (Build tested only.)

Thanks!
Laszlo

[-- Attachment #2: vmstate_change.diff --]
[-- Type: text/x-patch, Size: 1605 bytes --]

diff --git a/include/hw/acpi/vmgenid.h b/include/hw/acpi/vmgenid.h
index db7fa0e63303..a2ae450b1f56 100644
--- a/include/hw/acpi/vmgenid.h
+++ b/include/hw/acpi/vmgenid.h
@@ -4,6 +4,7 @@
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/qdev.h"
 #include "qemu/uuid.h"
+#include "sysemu/sysemu.h"
 
 #define VMGENID_DEVICE           "vmgenid"
 #define VMGENID_GUID             "guid"
@@ -21,6 +22,7 @@ typedef struct VmGenIdState {
     DeviceClass parent_obj;
     QemuUUID guid;                /* The 128-bit GUID seen by the guest */
     uint8_t vmgenid_addr_le[8];   /* Address of the GUID (little-endian) */
+    VMChangeStateEntry *vmstate;
 } VmGenIdState;
 
 static inline Object *find_vmgenid_dev(void)
diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c
index 9f97b722761b..0ae1d56ff297 100644
--- a/hw/acpi/vmgenid.c
+++ b/hw/acpi/vmgenid.c
@@ -177,10 +177,20 @@ static void vmgenid_set_guid(Object *obj, const char *value, Error **errp)
 /* After restoring an image, we need to update the guest memory and notify
  * it of a potential change to VM Generation ID
  */
+static void postload_update_guest_cb(void *opaque, int running, RunState state)
+{
+    VmGenIdState *vms = opaque;
+
+    qemu_del_vm_change_state_handler(vms->vmstate);
+    vms->vmstate = NULL;
+    vmgenid_update_guest(vms);
+}
+
 static int vmgenid_post_load(void *opaque, int version_id)
 {
     VmGenIdState *vms = opaque;
-    vmgenid_update_guest(vms);
+    vms->vmstate = qemu_add_vm_change_state_handler(postload_update_guest_cb,
+                                                    vms);
     return 0;
 }
 

^ permalink raw reply related	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-17 12:50     ` Laszlo Ersek
@ 2017-02-17 13:05       ` Igor Mammedov
  2017-02-17 13:41         ` Laszlo Ersek
  2017-02-20 10:23       ` Dr. David Alan Gilbert
  1 sibling, 1 reply; 53+ messages in thread
From: Igor Mammedov @ 2017-02-17 13:05 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: ben, qemu-devel, Dr. David Alan Gilbert (git), mst

On Fri, 17 Feb 2017 13:50:40 +0100
Laszlo Ersek <lersek@redhat.com> wrote:

> CC Dave
> 
> On 02/17/17 11:43, Igor Mammedov wrote:
> > On Thu, 16 Feb 2017 15:15:36 -0800
> > ben@skyportsystems.com wrote:
> > 
> >> From: Ben Warren <ben@skyportsystems.com>
> >>
> >> This implements the VM Generation ID feature by passing a 128-bit
> >> GUID to the guest via a fw_cfg blob.
> >> Any time the GUID changes, an ACPI notify event is sent to the guest
> >>
> >> The user interface is a simple device with one parameter:
> >>  - guid (string, must be "auto" or in UUID format
> >>    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
> > I've given it some testing with WS2012R2 and v4 patches for Seabios,
> > 
> > Windows is able to read initial GUID allocation and writeback
> > seems to work somehow:
> > 
> > (qemu) info vm-generation-id 
> > c109c09b-0e8b-42d5-9b33-8409c9dcd16c
> > 
> > vmgenid client in Windows reads it as 2 following 64bit integers:
> > 42d50e8bc109c09b:6cd1dcc90984339b
> > 
> > However update path/restore from snapshot doesn't
> > here is as I've tested it:
> > 
> > qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
> > (qemu) info vm-generation-id 
> > c109c09b-0e8b-42d5-9b33-8409c9dcd16c
> > (qemu) stop
> > (qemu) migrate "exec:gzip -c > STATEFILE.gz" 
> > (qemu) quit
> > 
> > qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
> > -incoming "exec: gzip -c -d STATEFILE.gz"
> > (qemu) info vm-generation-id 
> > 28b587fa-991b-4267-80d7-9cf28b746fe9
> > 
> > guest
> >  1. doesn't get GPE notification that it must receive
> >  2. vmgenid client in Windows reads the same value
> >       42d50e8bc109c09b:6cd1dcc90984339b
> 
> Hmmm, I wonder if we need something like this, in vmgenid_post_load():
> 
> commit 90c647db8d59e47c9000affc0d81754eb346e939
> Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
> Date:   Fri Apr 15 12:41:30 2016 +0100
> 
>     Fix pflash migration
> 
> with the idea being that in a single device's post_load callback, we
> shouldn't perform machine-wide actions (post_load is likely for fixing
> up the device itself). If machine-wide actions are necessary, we should
> temporarily register a "vm change state handler", and do the thing once
> that handler is called (when the machine has been loaded fully and is
> about to continue execution).
> 
> Can you please try the attached patch on top? (Build tested only.)
it doesn't help

> 
> Thanks!
> Laszlo

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-17 13:05       ` Igor Mammedov
@ 2017-02-17 13:41         ` Laszlo Ersek
  0 siblings, 0 replies; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-17 13:41 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: ben, qemu-devel, Dr. David Alan Gilbert (git), mst

On 02/17/17 14:05, Igor Mammedov wrote:
> On Fri, 17 Feb 2017 13:50:40 +0100
> Laszlo Ersek <lersek@redhat.com> wrote:
> 
>> CC Dave
>>
>> On 02/17/17 11:43, Igor Mammedov wrote:
>>> On Thu, 16 Feb 2017 15:15:36 -0800
>>> ben@skyportsystems.com wrote:
>>>
>>>> From: Ben Warren <ben@skyportsystems.com>
>>>>
>>>> This implements the VM Generation ID feature by passing a 128-bit
>>>> GUID to the guest via a fw_cfg blob.
>>>> Any time the GUID changes, an ACPI notify event is sent to the guest
>>>>
>>>> The user interface is a simple device with one parameter:
>>>>  - guid (string, must be "auto" or in UUID format
>>>>    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
>>> I've given it some testing with WS2012R2 and v4 patches for Seabios,
>>>
>>> Windows is able to read initial GUID allocation and writeback
>>> seems to work somehow:
>>>
>>> (qemu) info vm-generation-id 
>>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
>>>
>>> vmgenid client in Windows reads it as 2 following 64bit integers:
>>> 42d50e8bc109c09b:6cd1dcc90984339b
>>>
>>> However update path/restore from snapshot doesn't
>>> here is as I've tested it:
>>>
>>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
>>> (qemu) info vm-generation-id 
>>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
>>> (qemu) stop
>>> (qemu) migrate "exec:gzip -c > STATEFILE.gz" 
>>> (qemu) quit
>>>
>>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
>>> -incoming "exec: gzip -c -d STATEFILE.gz"
>>> (qemu) info vm-generation-id 
>>> 28b587fa-991b-4267-80d7-9cf28b746fe9
>>>
>>> guest
>>>  1. doesn't get GPE notification that it must receive
>>>  2. vmgenid client in Windows reads the same value
>>>       42d50e8bc109c09b:6cd1dcc90984339b
>>
>> Hmmm, I wonder if we need something like this, in vmgenid_post_load():
>>
>> commit 90c647db8d59e47c9000affc0d81754eb346e939
>> Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
>> Date:   Fri Apr 15 12:41:30 2016 +0100
>>
>>     Fix pflash migration
>>
>> with the idea being that in a single device's post_load callback, we
>> shouldn't perform machine-wide actions (post_load is likely for fixing
>> up the device itself). If machine-wide actions are necessary, we should
>> temporarily register a "vm change state handler", and do the thing once
>> that handler is called (when the machine has been loaded fully and is
>> about to continue execution).
>>
>> Can you please try the attached patch on top? (Build tested only.)
> it doesn't help

Thanks for trying! And, well, sh*t. :(

I guess it's time to resurrect the monitor command (temporarily, for
testing) so we can inject the SCI at will, without migration. I don't
want to burden you unreasonably, so I'll make an effort to try that myself.

Thanks!
Laszlo

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-17 10:43   ` Igor Mammedov
  2017-02-17 12:50     ` Laszlo Ersek
@ 2017-02-17 15:33     ` Ben Warren
  2017-02-17 16:03       ` Laszlo Ersek
  1 sibling, 1 reply; 53+ messages in thread
From: Ben Warren @ 2017-02-17 15:33 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel, lersek, mst

[-- Attachment #1: Type: text/plain, Size: 1935 bytes --]


> On Feb 17, 2017, at 2:43 AM, Igor Mammedov <imammedo@redhat.com> wrote:
> 
> On Thu, 16 Feb 2017 15:15:36 -0800
> ben@skyportsystems.com wrote:
> 
>> From: Ben Warren <ben@skyportsystems.com>
>> 
>> This implements the VM Generation ID feature by passing a 128-bit
>> GUID to the guest via a fw_cfg blob.
>> Any time the GUID changes, an ACPI notify event is sent to the guest
>> 
>> The user interface is a simple device with one parameter:
>> - guid (string, must be "auto" or in UUID format
>>   xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
> I've given it some testing with WS2012R2 and v4 patches for Seabios,
> 
> Windows is able to read initial GUID allocation and writeback
> seems to work somehow:
> 
> (qemu) info vm-generation-id 
> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
> 
> vmgenid client in Windows reads it as 2 following 64bit integers:
> 42d50e8bc109c09b:6cd1dcc90984339b
> 
> However update path/restore from snapshot doesn't
> here is as I've tested it:
> 
> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
> (qemu) info vm-generation-id 
> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
> (qemu) stop
> (qemu) migrate "exec:gzip -c > STATEFILE.gz" 
> (qemu) quit
> 
> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
> -incoming "exec: gzip -c -d STATEFILE.gz"
> (qemu) info vm-generation-id 
> 28b587fa-991b-4267-80d7-9cf28b746fe9
> 
> guest
> 1. doesn't get GPE notification that it must receive
> 2. vmgenid client in Windows reads the same value
>      42d50e8bc109c09b:6cd1dcc90984339b
> 
Strange, this was working for me, but with a slightly different test method:
I use virsh save/restore
While I do later testing with Windows, during development I use a Linux kernel module I wrote that keeps track of GUID and notifications.  I’m happy to share this with you if interested.

I’ll dig into this morning.

—Ben
<snip>

[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 3583 bytes --]

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-17 15:33     ` Ben Warren
@ 2017-02-17 16:03       ` Laszlo Ersek
  2017-02-17 18:34         ` Ben Warren
  2017-02-17 20:07         ` Laszlo Ersek
  0 siblings, 2 replies; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-17 16:03 UTC (permalink / raw)
  To: Ben Warren, Igor Mammedov; +Cc: qemu-devel, mst

On 02/17/17 16:33, Ben Warren wrote:
> 
>> On Feb 17, 2017, at 2:43 AM, Igor Mammedov <imammedo@redhat.com
>> <mailto:imammedo@redhat.com>> wrote:
>>
>> On Thu, 16 Feb 2017 15:15:36 -0800
>> ben@skyportsystems.com <mailto:ben@skyportsystems.com> wrote:
>>
>>> From: Ben Warren <ben@skyportsystems.com <mailto:ben@skyportsystems.com>>
>>>
>>> This implements the VM Generation ID feature by passing a 128-bit
>>> GUID to the guest via a fw_cfg blob.
>>> Any time the GUID changes, an ACPI notify event is sent to the guest
>>>
>>> The user interface is a simple device with one parameter:
>>> - guid (string, must be "auto" or in UUID format
>>>   xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
>> I've given it some testing with WS2012R2 and v4 patches for Seabios,
>>
>> Windows is able to read initial GUID allocation and writeback
>> seems to work somehow:
>>
>> (qemu) info vm-generation-id
>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
>>
>> vmgenid client in Windows reads it as 2 following 64bit integers:
>> 42d50e8bc109c09b:6cd1dcc90984339b
>>
>> However update path/restore from snapshot doesn't
>> here is as I've tested it:
>>
>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
>> (qemu) info vm-generation-id
>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
>> (qemu) stop
>> (qemu) migrate "exec:gzip -c > STATEFILE.gz"
>> (qemu) quit
>>
>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
>> -incoming "exec: gzip -c -d STATEFILE.gz"
>> (qemu) info vm-generation-id
>> 28b587fa-991b-4267-80d7-9cf28b746fe9
>>
>> guest
>> 1. doesn't get GPE notification that it must receive
>> 2. vmgenid client in Windows reads the same value
>>      42d50e8bc109c09b:6cd1dcc90984339b
>>
> Strange, this was working for me, but with a slightly different test method:
> 
>   * I use virsh save/restore

Awesome, this actually what I should try. All my guests are managed by
libvirt (with the occasional <qemu:arg>, for development), and direct
QEMU monitor commands such as

  virsh qemu-monitor-command ovmf.rhel7 --hmp 'info vm-generation-id'

only work for me if they are reasonably non-intrusive.

>   * While I do later testing with Windows, during development I use a
>     Linux kernel module I wrote that keeps track of GUID and
>     notifications.  I’m happy to share this with you if interested.

Please do. If you have a public git repo somewhere, that would be
awesome. (Bonus points if the module builds out-of-tree, if the
kernel-devel package is installed.)

NB: while the set-id monitor command was part of the series, I did test
it to the extent that I checked the SCI ("ACPI interrupt") count in the
guest, in /proc/interrupts. I did see it increase, so minimally the SCI
injection was fine.

Thanks!
Laszlo

> I’ll dig into this morning.
> 
> —Ben
> <snip>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-17 16:03       ` Laszlo Ersek
@ 2017-02-17 18:34         ` Ben Warren
  2017-02-17 19:00           ` Michael S. Tsirkin
  2017-02-17 20:42           ` Laszlo Ersek
  2017-02-17 20:07         ` Laszlo Ersek
  1 sibling, 2 replies; 53+ messages in thread
From: Ben Warren @ 2017-02-17 18:34 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: Igor Mammedov, qemu-devel, mst

[-- Attachment #1: Type: text/plain, Size: 3543 bytes --]


> On Feb 17, 2017, at 8:03 AM, Laszlo Ersek <lersek@redhat.com> wrote:
> 
> On 02/17/17 16:33, Ben Warren wrote:
>> 
>>> On Feb 17, 2017, at 2:43 AM, Igor Mammedov <imammedo@redhat.com <mailto:imammedo@redhat.com>
>>> <mailto:imammedo@redhat.com <mailto:imammedo@redhat.com>>> wrote:
>>> 
>>> On Thu, 16 Feb 2017 15:15:36 -0800
>>> ben@skyportsystems.com <mailto:ben@skyportsystems.com> <mailto:ben@skyportsystems.com <mailto:ben@skyportsystems.com>> wrote:
>>> 
>>>> From: Ben Warren <ben@skyportsystems.com <mailto:ben@skyportsystems.com> <mailto:ben@skyportsystems.com <mailto:ben@skyportsystems.com>>>
>>>> 
>>>> This implements the VM Generation ID feature by passing a 128-bit
>>>> GUID to the guest via a fw_cfg blob.
>>>> Any time the GUID changes, an ACPI notify event is sent to the guest
>>>> 
>>>> The user interface is a simple device with one parameter:
>>>> - guid (string, must be "auto" or in UUID format
>>>>  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
>>> I've given it some testing with WS2012R2 and v4 patches for Seabios,
>>> 
>>> Windows is able to read initial GUID allocation and writeback
>>> seems to work somehow:
>>> 
>>> (qemu) info vm-generation-id
>>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
>>> 
>>> vmgenid client in Windows reads it as 2 following 64bit integers:
>>> 42d50e8bc109c09b:6cd1dcc90984339b
>>> 
>>> However update path/restore from snapshot doesn't
>>> here is as I've tested it:
>>> 
>>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
>>> (qemu) info vm-generation-id
>>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
>>> (qemu) stop
>>> (qemu) migrate "exec:gzip -c > STATEFILE.gz"
>>> (qemu) quit
>>> 
>>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
>>> -incoming "exec: gzip -c -d STATEFILE.gz"
>>> (qemu) info vm-generation-id
>>> 28b587fa-991b-4267-80d7-9cf28b746fe9
>>> 
>>> guest
>>> 1. doesn't get GPE notification that it must receive
>>> 2. vmgenid client in Windows reads the same value
>>>     42d50e8bc109c09b:6cd1dcc90984339b
>>> 
>> Strange, this was working for me, but with a slightly different test method:
>> 
>>  * I use virsh save/restore
> 
> Awesome, this actually what I should try. All my guests are managed by
> libvirt (with the occasional <qemu:arg>, for development), and direct
> QEMU monitor commands such as
> 
>  virsh qemu-monitor-command ovmf.rhel7 --hmp 'info vm-generation-id'
> 
> only work for me if they are reasonably non-intrusive.
> 
>>  * While I do later testing with Windows, during development I use a
>>    Linux kernel module I wrote that keeps track of GUID and
>>    notifications.  I’m happy to share this with you if interested.
> 
> Please do. If you have a public git repo somewhere, that would be
> awesome. (Bonus points if the module builds out-of-tree, if the
> kernel-devel package is installed.)
> 
Here you go:
https://github.com/ben-skyportsystems/vmgenid-test <https://github.com/ben-skyportsystems/vmgenid-test>

I don’t know if something like this would ever be accepted into the Linux kernel, but it has been invaluable to me, and I’d like to see it somewhere better.

> NB: while the set-id monitor command was part of the series, I did test
> it to the extent that I checked the SCI ("ACPI interrupt") count in the
> guest, in /proc/interrupts. I did see it increase, so minimally the SCI
> injection was fine.
> 
> Thanks!
> Laszlo
> 
>> I’ll dig into this morning.
>> 
>> —Ben
>> <snip>


[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 3583 bytes --]

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-17 18:34         ` Ben Warren
@ 2017-02-17 19:00           ` Michael S. Tsirkin
  2017-02-17 20:42           ` Laszlo Ersek
  1 sibling, 0 replies; 53+ messages in thread
From: Michael S. Tsirkin @ 2017-02-17 19:00 UTC (permalink / raw)
  To: Ben Warren; +Cc: Laszlo Ersek, Igor Mammedov, qemu-devel

On Fri, Feb 17, 2017 at 10:34:29AM -0800, Ben Warren wrote:
> 
>     On Feb 17, 2017, at 8:03 AM, Laszlo Ersek <lersek@redhat.com> wrote:
> 
>     On 02/17/17 16:33, Ben Warren wrote:
> 
> 
> 
>             On Feb 17, 2017, at 2:43 AM, Igor Mammedov <imammedo@redhat.com
>             <mailto:imammedo@redhat.com>> wrote:
> 
>             On Thu, 16 Feb 2017 15:15:36 -0800
>             ben@skyportsystems.com <mailto:ben@skyportsystems.com> wrote:
> 
> 
>                 From: Ben Warren <ben@skyportsystems.com <
>                 mailto:ben@skyportsystems.com>>
> 
>                 This implements the VM Generation ID feature by passing a
>                 128-bit
>                 GUID to the guest via a fw_cfg blob.
>                 Any time the GUID changes, an ACPI notify event is sent to the
>                 guest
> 
>                 The user interface is a simple device with one parameter:
>                 - guid (string, must be "auto" or in UUID format
>                  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
> 
>             I've given it some testing with WS2012R2 and v4 patches for
>             Seabios,
> 
>             Windows is able to read initial GUID allocation and writeback
>             seems to work somehow:
> 
>             (qemu) info vm-generation-id
>             c109c09b-0e8b-42d5-9b33-8409c9dcd16c
> 
>             vmgenid client in Windows reads it as 2 following 64bit integers:
>             42d50e8bc109c09b:6cd1dcc90984339b
> 
>             However update path/restore from snapshot doesn't
>             here is as I've tested it:
> 
>             qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor
>             stdio
>             (qemu) info vm-generation-id
>             c109c09b-0e8b-42d5-9b33-8409c9dcd16c
>             (qemu) stop
>             (qemu) migrate "exec:gzip -c > STATEFILE.gz"
>             (qemu) quit
> 
>             qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor
>             stdio
>             -incoming "exec: gzip -c -d STATEFILE.gz"
>             (qemu) info vm-generation-id
>             28b587fa-991b-4267-80d7-9cf28b746fe9
> 
>             guest
>             1. doesn't get GPE notification that it must receive
>             2. vmgenid client in Windows reads the same value
>                 42d50e8bc109c09b:6cd1dcc90984339b
> 
> 
>         Strange, this was working for me, but with a slightly different test
>         method:
> 
>          * I use virsh save/restore
> 
> 
>     Awesome, this actually what I should try. All my guests are managed by
>     libvirt (with the occasional <qemu:arg>, for development), and direct
>     QEMU monitor commands such as
> 
>      virsh qemu-monitor-command ovmf.rhel7 --hmp 'info vm-generation-id'
> 
>     only work for me if they are reasonably non-intrusive.
> 
> 
>          * While I do later testing with Windows, during development I use a
>            Linux kernel module I wrote that keeps track of GUID and
>            notifications.  I’m happy to share this with you if interested.
> 
> 
>     Please do. If you have a public git repo somewhere, that would be
>     awesome. (Bonus points if the module builds out-of-tree, if the
>     kernel-devel package is installed.)
> 
> 
> Here you go:
> https://github.com/ben-skyportsystems/vmgenid-test
> 
> I don’t know if something like this would ever be accepted into the Linux
> kernel, but it has been invaluable to me, and I’d like to see it somewhere
> better.

I think the main issue here is that there's no blocking
interface to wait for change events.



Also ioremap_nocache is definitely the wrong thing to do
since the spec says
	It must not be in the same 4-kilobyte page as any memory that is
	expected to be mapped by a page table entry with caching disabled.

Finally, I think it makes sense to add an mmap call to this driver.
Basically add some kind of interface telling guest that gen id does not
share a 4K page with any other structure. Maybe just a special HID
value?  Or a special method we can test for.  Then it's safe for guest
to map this page read-only into userspace memory. It should have an
interface to report the offset to userspace. Userspace can then get the
ID without a system call by doing

ptr = mmap(...)
offset = ioctl(... GET_OFFSET ...)
guid = *(ptr + offset)

Windows does not seem to have this ability but it might be
a significant performance enhancement IMHO.

> 
>     NB: while the set-id monitor command was part of the series, I did test
>     it to the extent that I checked the SCI ("ACPI interrupt") count in the
>     guest, in /proc/interrupts. I did see it increase, so minimally the SCI
>     injection was fine.
> 
>     Thanks!
>     Laszlo
> 
> 
>         I’ll dig into this morning.
> 
>         —Ben
>         <snip>
> 
> 

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-17 16:03       ` Laszlo Ersek
  2017-02-17 18:34         ` Ben Warren
@ 2017-02-17 20:07         ` Laszlo Ersek
  2017-02-18  0:15           ` Ben Warren
  1 sibling, 1 reply; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-17 20:07 UTC (permalink / raw)
  To: Ben Warren, Igor Mammedov; +Cc: qemu-devel, mst

On 02/17/17 17:03, Laszlo Ersek wrote:
> On 02/17/17 16:33, Ben Warren wrote:
>>
>>> On Feb 17, 2017, at 2:43 AM, Igor Mammedov <imammedo@redhat.com
>>> <mailto:imammedo@redhat.com>> wrote:
>>>
>>> On Thu, 16 Feb 2017 15:15:36 -0800
>>> ben@skyportsystems.com <mailto:ben@skyportsystems.com> wrote:
>>>
>>>> From: Ben Warren <ben@skyportsystems.com <mailto:ben@skyportsystems.com>>
>>>>
>>>> This implements the VM Generation ID feature by passing a 128-bit
>>>> GUID to the guest via a fw_cfg blob.
>>>> Any time the GUID changes, an ACPI notify event is sent to the guest
>>>>
>>>> The user interface is a simple device with one parameter:
>>>> - guid (string, must be "auto" or in UUID format
>>>>   xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
>>> I've given it some testing with WS2012R2 and v4 patches for Seabios,
>>>
>>> Windows is able to read initial GUID allocation and writeback
>>> seems to work somehow:
>>>
>>> (qemu) info vm-generation-id
>>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
>>>
>>> vmgenid client in Windows reads it as 2 following 64bit integers:
>>> 42d50e8bc109c09b:6cd1dcc90984339b
>>>
>>> However update path/restore from snapshot doesn't
>>> here is as I've tested it:
>>>
>>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
>>> (qemu) info vm-generation-id
>>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
>>> (qemu) stop
>>> (qemu) migrate "exec:gzip -c > STATEFILE.gz"
>>> (qemu) quit
>>>
>>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
>>> -incoming "exec: gzip -c -d STATEFILE.gz"
>>> (qemu) info vm-generation-id
>>> 28b587fa-991b-4267-80d7-9cf28b746fe9
>>>
>>> guest
>>> 1. doesn't get GPE notification that it must receive
>>> 2. vmgenid client in Windows reads the same value
>>>      42d50e8bc109c09b:6cd1dcc90984339b
>>>
>> Strange, this was working for me, but with a slightly different test method:
>>
>>   * I use virsh save/restore
> 
> Awesome, this actually what I should try. All my guests are managed by
> libvirt (with the occasional <qemu:arg>, for development), and direct
> QEMU monitor commands such as
> 
>   virsh qemu-monitor-command ovmf.rhel7 --hmp 'info vm-generation-id'
> 
> only work for me if they are reasonably non-intrusive.
> 
>>   * While I do later testing with Windows, during development I use a
>>     Linux kernel module I wrote that keeps track of GUID and
>>     notifications.  I’m happy to share this with you if interested.
> 
> Please do. If you have a public git repo somewhere, that would be
> awesome. (Bonus points if the module builds out-of-tree, if the
> kernel-devel package is installed.)
> 
> NB: while the set-id monitor command was part of the series, I did test
> it to the extent that I checked the SCI ("ACPI interrupt") count in the
> guest, in /proc/interrupts. I did see it increase, so minimally the SCI
> injection was fine.

So, I did some testing with a RHEL-7 guest. I passed '-device
vmgenid=auto' to QEMU using the <qemu:arg> element in the domain XML.

(1) I started the guest normally, and grepped /proc/interrupts for
"acpi". Zero interrupts on either VCPU.

(2) Dumped the guest RAM to a file with "virsh dump ... --memory-only",
opened it with crash, and listed the 16 GUID bytes at the offset that
the firmware (OVMF) reported at startup.

(3) cycled through "virsh managedsave" and "virsh start"

(4) grepped /proc/interrupts again for "acpi". One interrupt had been
delivered to one of the VCPUs, all others were zero.

(5) Repeated step (2). The bytes listed this time were different.

(6) Issued "virsh qemu-monitor-command ovmf.rhel7 --hmp 'info
vm-generation-id", and compared the output against the bytes dumped
(with crash) from guest memory, in step 5. They were a match.

So, to me it seems like the SCI is injected, and the memory contents are
changed.

---*---

Windows Server 2012 R2 test:

(7) booted the guest similarly with '-device vmgenid=auto' via
<qemu:arg> in the domain XML.

(8) Initial check from the host side:

$ virsh qemu-monitor-command ovmf.win2012r2.q35 \
    --hmp 'info vm-generation-id'
a3f7c334-7dc4-4694-8b8f-abf52abb072f

(9) Verifying the same from within, using Vadim's program (note: I
logged into the VM with ssh, using Cygwin's SSHD in the guest):

$ ./vmgenid.exe
VmCounterValue: 46947dc4a3f7c334:2f07bb2af5ab8f8b
0x34 0xc3 0xf7 0xa3 0xc4 0x7d 0x94 0x46 0x8b 0x8f 0xab 0xf5 0x2a 0xbb
0x07 0x2f

This is a match, so the initial setup works. (Look only at the raw byte
dump in the second line -- it matches the Little Endian UUID
representation as specified in the SMBIOS spec!)

(10) Logged out of the guest (with ssh), cycled through "virsh
managedsave" and "virsh start" for the domain, logged back in.

(11) in the guest:

$ ./vmgenid.exe
VmCounterValue: 4a12296b382162da:6c00d1a52699b7bd
0xda 0x62 0x21 0x38 0x6b 0x29 0x12 0x4a 0xbd 0xb7 0x99 0x26 0xa5 0xd1
0x00 0x6c

(12) on the host:

$ virsh qemu-monitor-command ovmf.win2012r2.q35 \
      --hmp 'info vm-generation-id'
382162da-296b-4a12-bdb7-9926a5d1006c

This is again a match. (Again, look only at the raw byte dump from
vmgenid.exe under (11), and consider the BE/LE conversion for the first
three segments!)

(13) Logged out of the guest with ssh, and started Vadim's other program
(vmgenid_wait.exe), this time from a normal CMD window on the GUI. The
program started, reproduced the above output (seen under (11)), and then
went to sleep (waiting).

(14) cycled through "virsh managedsave" and "virsh start" for the domain.

(15) The domain resumed, and Vadim's vmgenid_wait.exe woke up, printing
(manual transcript):

VmCounterValue changed to: 495ba7807ed37772:195d0cff681f7a7

Please refer to the following screenshot:

http://people.redhat.com/~lersek/vmgenid-dd1f68c5-89b0-4458-84fa-de9e3d23f4cb/Screenshot_ovmf.win2012r2.q35_2017-02-17_20:34:41.png

(16) on the host:

$ virsh qemu-monitor-command ovmf.win2012r2.q35 \
      --hmp 'info vm-generation-id'

7ed37772-a780-495b-a7f7-81f6cfd09501

This is again a match. It is not easy to see, because Vadim's
"vmgenid_wait.exe" does not print the raw byte dump after it wakes up;
the raw byte dump is only printed before it goes to sleep. After wakeup,
it only dumps the composed values. Somewhat more confusingly, the 64-bit
hex integers are not zero padded, we'll have to make up for that manually.

So here goes:

   [A]      [B]  [C]  [D]  [E]
   7ed37772-a780-495b-a7f7-81f6cfd09501 (from the host)

   [C]  [B]  [A]        [E']         [D']
   495b a780 7ed37772 : 0195d0cff681 f7a7 (from vmgenid_wait.exe)
                        ^
                        zero padding added manually

The parts marked with an apostrophe (') are reversed, byte-wise.

So, I'm going to have to declare this "working by design".

Confirming my earlier Tested-by (same patches as before):

Tested-by: Laszlo Ersek <lersek@redhat.com>

What could be the difference between Igor's setup and mine? Perhaps the
BIOS? (Again, I used OVMF.)

The "managedsave" command of virsh boils down to (see
"src/qemu/qemu_driver.c" in the libvirt source):

qemuDomainManagedSave()
  qemuDomainSaveInternal()
    qemuProcessStopCPUs()
    qemuDomainSaveMemory()
      qemuDomainSaveHeader()
      qemuMigrationToFile()
        qemuMonitorMigrateToFd()
          ...
    qemuProcessStop()

I capture all traffic between libvirt and the QEMU monitor, and between
libvirt and the QEMU guest agent, in the libvirt log file, as a rule, so
I can paste the relevant lines:

Libvirt sending the file descriptor to QEMU:

2017-02-17 19:31:54.305+0000: 16586: debug :
qemuMonitorJSONCommandWithFd:296 : Send command
'{"execute":"getfd","arguments":{"fdname":"migrate"},"id":"libvirt-30"}'
for write with FD 26

Libvirt starting the migration:

2017-02-17 19:31:54.306+0000: 16586: debug :
qemuMonitorJSONCommandWithFd:296 : Send command
'{"execute":"migrate","arguments":{"detach":true,"blk":false,"inc":false,"uri":"fd:migrate"},"id":"libvirt-31"}'
for write with FD -1

Then loading it:

2017-02-17 19:32:02.083+0000: 16585: debug :
qemuMonitorJSONCommandWithFd:296 : Send command
'{"execute":"migrate-incoming","arguments":{"uri":"fd:25"},"id":"libvirt-17"}'
for write with FD -1

I don't have the slightest idea why it failed for Igor -- I can only
suspect the SeaBIOS patches.

Note that in the SeaBIOS discussion, Ben mentioned that he wasn't
actually seeing the fw_cfg writes in QEMU on the S3 resume path, despite
SeaBIOS attempting them. So, perhaps, is there a bug in the latest
SeaBIOS patches that prevent fw_cfg writes completely, even on the
normal boot path? That would be consistent with Igor's results: the
initial download works (hence the first GUID can be seen), but then the
update does not work (because QEMU has not received the address).

Thanks
Laszlo

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-17 18:34         ` Ben Warren
  2017-02-17 19:00           ` Michael S. Tsirkin
@ 2017-02-17 20:42           ` Laszlo Ersek
  1 sibling, 0 replies; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-17 20:42 UTC (permalink / raw)
  To: Ben Warren; +Cc: Igor Mammedov, qemu-devel, mst

On 02/17/17 19:34, Ben Warren wrote:
> 
>> On Feb 17, 2017, at 8:03 AM, Laszlo Ersek <lersek@redhat.com
>> <mailto:lersek@redhat.com>> wrote:
>>
>> On 02/17/17 16:33, Ben Warren wrote:
>>>
>>>> On Feb 17, 2017, at 2:43 AM, Igor Mammedov <imammedo@redhat.com
>>>> <mailto:imammedo@redhat.com>
>>>> <mailto:imammedo@redhat.com>> wrote:
>>>>
>>>> On Thu, 16 Feb 2017 15:15:36 -0800
>>>> ben@skyportsystems.com
>>>> <mailto:ben@skyportsystems.com> <mailto:ben@skyportsystems.com> wrote:
>>>>
>>>>> From: Ben Warren <ben@skyportsystems.com
>>>>> <mailto:ben@skyportsystems.com> <mailto:ben@skyportsystems.com>>
>>>>>
>>>>> This implements the VM Generation ID feature by passing a 128-bit
>>>>> GUID to the guest via a fw_cfg blob.
>>>>> Any time the GUID changes, an ACPI notify event is sent to the guest
>>>>>
>>>>> The user interface is a simple device with one parameter:
>>>>> - guid (string, must be "auto" or in UUID format
>>>>>  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
>>>> I've given it some testing with WS2012R2 and v4 patches for Seabios,
>>>>
>>>> Windows is able to read initial GUID allocation and writeback
>>>> seems to work somehow:
>>>>
>>>> (qemu) info vm-generation-id
>>>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
>>>>
>>>> vmgenid client in Windows reads it as 2 following 64bit integers:
>>>> 42d50e8bc109c09b:6cd1dcc90984339b
>>>>
>>>> However update path/restore from snapshot doesn't
>>>> here is as I've tested it:
>>>>
>>>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
>>>> (qemu) info vm-generation-id
>>>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
>>>> (qemu) stop
>>>> (qemu) migrate "exec:gzip -c > STATEFILE.gz"
>>>> (qemu) quit
>>>>
>>>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
>>>> -incoming "exec: gzip -c -d STATEFILE.gz"
>>>> (qemu) info vm-generation-id
>>>> 28b587fa-991b-4267-80d7-9cf28b746fe9
>>>>
>>>> guest
>>>> 1. doesn't get GPE notification that it must receive
>>>> 2. vmgenid client in Windows reads the same value
>>>>     42d50e8bc109c09b:6cd1dcc90984339b
>>>>
>>> Strange, this was working for me, but with a slightly different test
>>> method:
>>>
>>>  * I use virsh save/restore
>>
>> Awesome, this actually what I should try. All my guests are managed by
>> libvirt (with the occasional <qemu:arg>, for development), and direct
>> QEMU monitor commands such as
>>
>>  virsh qemu-monitor-command ovmf.rhel7 --hmp 'info vm-generation-id'
>>
>> only work for me if they are reasonably non-intrusive.
>>
>>>  * While I do later testing with Windows, during development I use a
>>>    Linux kernel module I wrote that keeps track of GUID and
>>>    notifications.  I’m happy to share this with you if interested.
>>
>> Please do. If you have a public git repo somewhere, that would be
>> awesome. (Bonus points if the module builds out-of-tree, if the
>> kernel-devel package is installed.)
>>
> Here you go:
> https://github.com/ben-skyportsystems/vmgenid-test

Ah, thanks -- I apologize, I stopped refreshing my incoming email while
I was testing and writing up the results. I'll stash this for later though.

Thanks!
Laszlo

> I don’t know if something like this would ever be accepted into the
> Linux kernel, but it has been invaluable to me, and I’d like to see it
> somewhere better.
> 
>> NB: while the set-id monitor command was part of the series, I did test
>> it to the extent that I checked the SCI ("ACPI interrupt") count in the
>> guest, in /proc/interrupts. I did see it increase, so minimally the SCI
>> injection was fine.
>>
>> Thanks!
>> Laszlo
>>
>>> I’ll dig into this morning.
>>>
>>> —Ben
>>> <snip>
> 

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-17 20:07         ` Laszlo Ersek
@ 2017-02-18  0:15           ` Ben Warren
  0 siblings, 0 replies; 53+ messages in thread
From: Ben Warren @ 2017-02-18  0:15 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: Igor Mammedov, qemu-devel, mst

[-- Attachment #1: Type: text/plain, Size: 12342 bytes --]


> On Feb 17, 2017, at 12:07 PM, Laszlo Ersek <lersek@redhat.com> wrote:
> 
> On 02/17/17 17:03, Laszlo Ersek wrote:
>> On 02/17/17 16:33, Ben Warren wrote:
>>> 
>>>> On Feb 17, 2017, at 2:43 AM, Igor Mammedov <imammedo@redhat.com
>>>> <mailto:imammedo@redhat.com>> wrote:
>>>> 
>>>> On Thu, 16 Feb 2017 15:15:36 -0800
>>>> ben@skyportsystems.com <mailto:ben@skyportsystems.com> wrote:
>>>> 
>>>>> From: Ben Warren <ben@skyportsystems.com <mailto:ben@skyportsystems.com>>
>>>>> 
>>>>> This implements the VM Generation ID feature by passing a 128-bit
>>>>> GUID to the guest via a fw_cfg blob.
>>>>> Any time the GUID changes, an ACPI notify event is sent to the guest
>>>>> 
>>>>> The user interface is a simple device with one parameter:
>>>>> - guid (string, must be "auto" or in UUID format
>>>>>  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
>>>> I've given it some testing with WS2012R2 and v4 patches for Seabios,
>>>> 
>>>> Windows is able to read initial GUID allocation and writeback
>>>> seems to work somehow:
>>>> 
>>>> (qemu) info vm-generation-id
>>>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
>>>> 
>>>> vmgenid client in Windows reads it as 2 following 64bit integers:
>>>> 42d50e8bc109c09b:6cd1dcc90984339b
>>>> 
>>>> However update path/restore from snapshot doesn't
>>>> here is as I've tested it:
>>>> 
>>>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
>>>> (qemu) info vm-generation-id
>>>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
>>>> (qemu) stop
>>>> (qemu) migrate "exec:gzip -c > STATEFILE.gz"
>>>> (qemu) quit
>>>> 
>>>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
>>>> -incoming "exec: gzip -c -d STATEFILE.gz"
>>>> (qemu) info vm-generation-id
>>>> 28b587fa-991b-4267-80d7-9cf28b746fe9
>>>> 
>>>> guest
>>>> 1. doesn't get GPE notification that it must receive
>>>> 2. vmgenid client in Windows reads the same value
>>>>     42d50e8bc109c09b:6cd1dcc90984339b
>>>> 
>>> Strange, this was working for me, but with a slightly different test method:
>>> 
>>>  * I use virsh save/restore
>> 
>> Awesome, this actually what I should try. All my guests are managed by
>> libvirt (with the occasional <qemu:arg>, for development), and direct
>> QEMU monitor commands such as
>> 
>>  virsh qemu-monitor-command ovmf.rhel7 --hmp 'info vm-generation-id'
>> 
>> only work for me if they are reasonably non-intrusive.
>> 
>>>  * While I do later testing with Windows, during development I use a
>>>    Linux kernel module I wrote that keeps track of GUID and
>>>    notifications.  I’m happy to share this with you if interested.
>> 
>> Please do. If you have a public git repo somewhere, that would be
>> awesome. (Bonus points if the module builds out-of-tree, if the
>> kernel-devel package is installed.)
>> 
>> NB: while the set-id monitor command was part of the series, I did test
>> it to the extent that I checked the SCI ("ACPI interrupt") count in the
>> guest, in /proc/interrupts. I did see it increase, so minimally the SCI
>> injection was fine.
> 
> So, I did some testing with a RHEL-7 guest. I passed '-device
> vmgenid=auto' to QEMU using the <qemu:arg> element in the domain XML.
> 
> (1) I started the guest normally, and grepped /proc/interrupts for
> "acpi". Zero interrupts on either VCPU.
> 
> (2) Dumped the guest RAM to a file with "virsh dump ... --memory-only",
> opened it with crash, and listed the 16 GUID bytes at the offset that
> the firmware (OVMF) reported at startup.
> 
> (3) cycled through "virsh managedsave" and "virsh start"
> 
> (4) grepped /proc/interrupts again for "acpi". One interrupt had been
> delivered to one of the VCPUs, all others were zero.
> 
> (5) Repeated step (2). The bytes listed this time were different.
> 
> (6) Issued "virsh qemu-monitor-command ovmf.rhel7 --hmp 'info
> vm-generation-id", and compared the output against the bytes dumped
> (with crash) from guest memory, in step 5. They were a match.
> 
> So, to me it seems like the SCI is injected, and the memory contents are
> changed.
> 
> ---*---
> 
> Windows Server 2012 R2 test:
> 
> (7) booted the guest similarly with '-device vmgenid=auto' via
> <qemu:arg> in the domain XML.
> 
> (8) Initial check from the host side:
> 
> $ virsh qemu-monitor-command ovmf.win2012r2.q35 \
>    --hmp 'info vm-generation-id'
> a3f7c334-7dc4-4694-8b8f-abf52abb072f
> 
> (9) Verifying the same from within, using Vadim's program (note: I
> logged into the VM with ssh, using Cygwin's SSHD in the guest):
> 
> $ ./vmgenid.exe
> VmCounterValue: 46947dc4a3f7c334:2f07bb2af5ab8f8b
> 0x34 0xc3 0xf7 0xa3 0xc4 0x7d 0x94 0x46 0x8b 0x8f 0xab 0xf5 0x2a 0xbb
> 0x07 0x2f
> 
> This is a match, so the initial setup works. (Look only at the raw byte
> dump in the second line -- it matches the Little Endian UUID
> representation as specified in the SMBIOS spec!)
> 
> (10) Logged out of the guest (with ssh), cycled through "virsh
> managedsave" and "virsh start" for the domain, logged back in.
> 
> (11) in the guest:
> 
> $ ./vmgenid.exe
> VmCounterValue: 4a12296b382162da:6c00d1a52699b7bd
> 0xda 0x62 0x21 0x38 0x6b 0x29 0x12 0x4a 0xbd 0xb7 0x99 0x26 0xa5 0xd1
> 0x00 0x6c
> 
> (12) on the host:
> 
> $ virsh qemu-monitor-command ovmf.win2012r2.q35 \
>      --hmp 'info vm-generation-id'
> 382162da-296b-4a12-bdb7-9926a5d1006c
> 
> This is again a match. (Again, look only at the raw byte dump from
> vmgenid.exe under (11), and consider the BE/LE conversion for the first
> three segments!)
> 
> (13) Logged out of the guest with ssh, and started Vadim's other program
> (vmgenid_wait.exe), this time from a normal CMD window on the GUI. The
> program started, reproduced the above output (seen under (11)), and then
> went to sleep (waiting).
> 
> (14) cycled through "virsh managedsave" and "virsh start" for the domain.
> 
> (15) The domain resumed, and Vadim's vmgenid_wait.exe woke up, printing
> (manual transcript):
> 
> VmCounterValue changed to: 495ba7807ed37772:195d0cff681f7a7
> 
> Please refer to the following screenshot:
> 
> http://people.redhat.com/~lersek/vmgenid-dd1f68c5-89b0-4458-84fa-de9e3d23f4cb/Screenshot_ovmf.win2012r2.q35_2017-02-17_20:34:41.png
> 
> (16) on the host:
> 
> $ virsh qemu-monitor-command ovmf.win2012r2.q35 \
>      --hmp 'info vm-generation-id'
> 
> 7ed37772-a780-495b-a7f7-81f6cfd09501
> 
> This is again a match. It is not easy to see, because Vadim's
> "vmgenid_wait.exe" does not print the raw byte dump after it wakes up;
> the raw byte dump is only printed before it goes to sleep. After wakeup,
> it only dumps the composed values. Somewhat more confusingly, the 64-bit
> hex integers are not zero padded, we'll have to make up for that manually.
> 
> So here goes:
> 
>   [A]      [B]  [C]  [D]  [E]
>   7ed37772-a780-495b-a7f7-81f6cfd09501 (from the host)
> 
>   [C]  [B]  [A]        [E']         [D']
>   495b a780 7ed37772 : 0195d0cff681 f7a7 (from vmgenid_wait.exe)
>                        ^
>                        zero padding added manually
> 
> The parts marked with an apostrophe (') are reversed, byte-wise.
> 
> So, I'm going to have to declare this "working by design".
> 
> Confirming my earlier Tested-by (same patches as before):
> 
> Tested-by: Laszlo Ersek <lersek@redhat.com>
> 
> What could be the difference between Igor's setup and mine? Perhaps the
> BIOS? (Again, I used OVMF.)
> 
> The "managedsave" command of virsh boils down to (see
> "src/qemu/qemu_driver.c" in the libvirt source):
> 
> qemuDomainManagedSave()
>  qemuDomainSaveInternal()
>    qemuProcessStopCPUs()
>    qemuDomainSaveMemory()
>      qemuDomainSaveHeader()
>      qemuMigrationToFile()
>        qemuMonitorMigrateToFd()
>          ...
>    qemuProcessStop()
> 
> I capture all traffic between libvirt and the QEMU monitor, and between
> libvirt and the QEMU guest agent, in the libvirt log file, as a rule, so
> I can paste the relevant lines:
> 
> Libvirt sending the file descriptor to QEMU:
> 
> 2017-02-17 19:31:54.305+0000: 16586: debug :
> qemuMonitorJSONCommandWithFd:296 : Send command
> '{"execute":"getfd","arguments":{"fdname":"migrate"},"id":"libvirt-30"}'
> for write with FD 26
> 
> Libvirt starting the migration:
> 
> 2017-02-17 19:31:54.306+0000: 16586: debug :
> qemuMonitorJSONCommandWithFd:296 : Send command
> '{"execute":"migrate","arguments":{"detach":true,"blk":false,"inc":false,"uri":"fd:migrate"},"id":"libvirt-31"}'
> for write with FD -1
> 
> Then loading it:
> 
> 2017-02-17 19:32:02.083+0000: 16585: debug :
> qemuMonitorJSONCommandWithFd:296 : Send command
> '{"execute":"migrate-incoming","arguments":{"uri":"fd:25"},"id":"libvirt-17"}'
> for write with FD -1
> 
> I don't have the slightest idea why it failed for Igor -- I can only
> suspect the SeaBIOS patches.
> 
> Note that in the SeaBIOS discussion, Ben mentioned that he wasn't
> actually seeing the fw_cfg writes in QEMU on the S3 resume path, despite
> SeaBIOS attempting them. So, perhaps, is there a bug in the latest
> SeaBIOS patches that prevent fw_cfg writes completely, even on the
> normal boot path? That would be consistent with Igor's results: the
> initial download works (hence the first GUID can be seen), but then the
> update does not work (because QEMU has not received the address).
> 
> Thanks
> Laszlo

My functional testing was also successful.  I did make the one SeaBIOS change suggested by Laszlo, which I’ll post in a minute as v5.

In my case, I used a Windows 2012R2 VM that is a fully-joined Active Directory Domain Controller, so was able to query some VM Generation ID-derived data via power shell.  This use case is the reason why VM Generation ID exists in the first place.
We manage the VM using libvirt with this extra snippet in the domain XML:

  <qemu:commandline>
    <qemu:arg value='-device'/>
    <qemu:arg value='vmgenid,guid=auto'/>
  </qemu:commandline>

The commands I used within Windows are:

1.  repadmin /showrepl
	This shows the replication state of the Domain Controller, most importantly printing the “DSA invocation ID”.  This number is derived from VM Generation ID, and changes whenever Active Directory considers its local data dirty.  It’s an indicator the Windows detected a change in VM Generation ID.

2.  (Get-ADObject <x500 stuff> -server <domain controller> -property meds-generationid).’msds-generationid’
	This gets the least-significant 64 bits of the VM Generation ID GUID
	
	http://blogs.metcorpconsulting.com/tech/?p=1594


Initial State:
=========

virsh # qemu-monitor-command --hmp 20 info vm-generation-id
d43edc6c-9686-4bf3-8621-2a4be879eb22

PS C:\Users\bran> (Get-ADObject "cn=whiteharbor,ou=Domain Controllers,DC=thenorth,dc=ws" -server whiteharbor.thenorth.ws
 -property msds-generationid).'msds-generationid'
108
220
62
212
134
150
243
75

***
NOTE:  108,220,62,212,212,134,150,243,75 == 6c,dc,3e,d4,86,96,f3,4b  ==> The GUID shown in HMP in Little-endian format!
***

PS C:\Users\bran> repadmin /showrepl

Repadmin: running command /showrepl against full DC localhost
Default-First-Site-Name\WHITEHARBOR
DSA Options: IS_GC
Site Options: (none)
DSA object GUID: 3dcfed54-28d4-448e-9087-140dd251e1b4
DSA invocationID: 56ca3644-8bc3-4dd8-9860-df0b3f5ce06f

Reboot within Windows:
==================

Nothing changed


After virsh save, virsh restore:
=======================

virsh # qemu-monitor-command --hmp 22 info vm-generation-id
573a0dbc-6eca-49fd-a632-f4f1e016502a

PS C:\Users\bran> (Get-ADObject "cn=whiteharbor,ou=Domain Controllers,DC=thenorth,dc=ws" -server whiteharbor.thenorth.ws
 -property msds-generationid).'msds-generationid'
188
13
58
87
202
110
253
73
PS C:\Users\bran> repadmin /showrepl

Repadmin: running command /showrepl against full DC localhost
Default-First-Site-Name\WHITEHARBOR
DSA Options: IS_GC
Site Options: (none)
DSA object GUID: 3dcfed54-28d4-448e-9087-140dd251e1b4
DSA invocationID: 7b6dda08-d23b-4ca2-982d-774f9c214442


I’m satisfied that the current patches work and don’t really understand Igor’s failure, other than maybe the SeaBIOS difference.

regards,
Ben



[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 3583 bytes --]

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-17 12:50     ` Laszlo Ersek
  2017-02-17 13:05       ` Igor Mammedov
@ 2017-02-20 10:23       ` Dr. David Alan Gilbert
  2017-02-20 10:40         ` Laszlo Ersek
  2017-02-20 20:00         ` Eric Blake
  1 sibling, 2 replies; 53+ messages in thread
From: Dr. David Alan Gilbert @ 2017-02-20 10:23 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: Igor Mammedov, ben, qemu-devel, mst

* Laszlo Ersek (lersek@redhat.com) wrote:
> CC Dave

This isn't an area I really understand; but if I'm
reading this right then 
   vmgenid is stored in fw_cfg?
   fw_cfg isn't migrated

So why should any changes to it get migrated, except if it's already
been read by the guest (and if the guest reads it again aftwards what's
it expected to read?)

Dave

> On 02/17/17 11:43, Igor Mammedov wrote:
> > On Thu, 16 Feb 2017 15:15:36 -0800
> > ben@skyportsystems.com wrote:
> > 
> >> From: Ben Warren <ben@skyportsystems.com>
> >>
> >> This implements the VM Generation ID feature by passing a 128-bit
> >> GUID to the guest via a fw_cfg blob.
> >> Any time the GUID changes, an ACPI notify event is sent to the guest
> >>
> >> The user interface is a simple device with one parameter:
> >>  - guid (string, must be "auto" or in UUID format
> >>    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
> > I've given it some testing with WS2012R2 and v4 patches for Seabios,
> > 
> > Windows is able to read initial GUID allocation and writeback
> > seems to work somehow:
> > 
> > (qemu) info vm-generation-id 
> > c109c09b-0e8b-42d5-9b33-8409c9dcd16c
> > 
> > vmgenid client in Windows reads it as 2 following 64bit integers:
> > 42d50e8bc109c09b:6cd1dcc90984339b
> > 
> > However update path/restore from snapshot doesn't
> > here is as I've tested it:
> > 
> > qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
> > (qemu) info vm-generation-id 
> > c109c09b-0e8b-42d5-9b33-8409c9dcd16c
> > (qemu) stop
> > (qemu) migrate "exec:gzip -c > STATEFILE.gz" 
> > (qemu) quit
> > 
> > qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
> > -incoming "exec: gzip -c -d STATEFILE.gz"
> > (qemu) info vm-generation-id 
> > 28b587fa-991b-4267-80d7-9cf28b746fe9
> > 
> > guest
> >  1. doesn't get GPE notification that it must receive
> >  2. vmgenid client in Windows reads the same value
> >       42d50e8bc109c09b:6cd1dcc90984339b
> 
> Hmmm, I wonder if we need something like this, in vmgenid_post_load():
> 
> commit 90c647db8d59e47c9000affc0d81754eb346e939
> Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
> Date:   Fri Apr 15 12:41:30 2016 +0100
> 
>     Fix pflash migration
> 
> with the idea being that in a single device's post_load callback, we
> shouldn't perform machine-wide actions (post_load is likely for fixing
> up the device itself). If machine-wide actions are necessary, we should
> temporarily register a "vm change state handler", and do the thing once
> that handler is called (when the machine has been loaded fully and is
> about to continue execution).
> 
> Can you please try the attached patch on top? (Build tested only.)
> 
> Thanks!
> Laszlo

> diff --git a/include/hw/acpi/vmgenid.h b/include/hw/acpi/vmgenid.h
> index db7fa0e63303..a2ae450b1f56 100644
> --- a/include/hw/acpi/vmgenid.h
> +++ b/include/hw/acpi/vmgenid.h
> @@ -4,6 +4,7 @@
>  #include "hw/acpi/bios-linker-loader.h"
>  #include "hw/qdev.h"
>  #include "qemu/uuid.h"
> +#include "sysemu/sysemu.h"
>  
>  #define VMGENID_DEVICE           "vmgenid"
>  #define VMGENID_GUID             "guid"
> @@ -21,6 +22,7 @@ typedef struct VmGenIdState {
>      DeviceClass parent_obj;
>      QemuUUID guid;                /* The 128-bit GUID seen by the guest */
>      uint8_t vmgenid_addr_le[8];   /* Address of the GUID (little-endian) */
> +    VMChangeStateEntry *vmstate;
>  } VmGenIdState;
>  
>  static inline Object *find_vmgenid_dev(void)
> diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c
> index 9f97b722761b..0ae1d56ff297 100644
> --- a/hw/acpi/vmgenid.c
> +++ b/hw/acpi/vmgenid.c
> @@ -177,10 +177,20 @@ static void vmgenid_set_guid(Object *obj, const char *value, Error **errp)
>  /* After restoring an image, we need to update the guest memory and notify
>   * it of a potential change to VM Generation ID
>   */
> +static void postload_update_guest_cb(void *opaque, int running, RunState state)
> +{
> +    VmGenIdState *vms = opaque;
> +
> +    qemu_del_vm_change_state_handler(vms->vmstate);
> +    vms->vmstate = NULL;
> +    vmgenid_update_guest(vms);
> +}
> +
>  static int vmgenid_post_load(void *opaque, int version_id)
>  {
>      VmGenIdState *vms = opaque;
> -    vmgenid_update_guest(vms);
> +    vms->vmstate = qemu_add_vm_change_state_handler(postload_update_guest_cb,
> +                                                    vms);
>      return 0;
>  }
>  

--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-20 10:23       ` Dr. David Alan Gilbert
@ 2017-02-20 10:40         ` Laszlo Ersek
  2017-02-20 11:00           ` Dr. David Alan Gilbert
  2017-02-20 20:00         ` Eric Blake
  1 sibling, 1 reply; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-20 10:40 UTC (permalink / raw)
  To: Dr. David Alan Gilbert; +Cc: Igor Mammedov, ben, qemu-devel, mst

On 02/20/17 11:23, Dr. David Alan Gilbert wrote:
> * Laszlo Ersek (lersek@redhat.com) wrote:
>> CC Dave
> 
> This isn't an area I really understand; but if I'm
> reading this right then 
>    vmgenid is stored in fw_cfg?
>    fw_cfg isn't migrated
> 
> So why should any changes to it get migrated, except if it's already
> been read by the guest (and if the guest reads it again aftwards what's
> it expected to read?)

This is what we have here:
- QEMU formats read-only fw_cfg blob with GUID
- guest downloads blob, places it in guest RAM
- guest tells QEMU the guest-side address of the blob
- during migration, guest RAM is transferred
- after migration, in the device's post_load callback, QEMU overwrites
  the GUID in guest RAM with a different value, and injects an SCI

I CC'd you for the following reason: Igor reported that he didn't see
either the fresh GUID or the SCI in the guest, on the target host, after
migration. I figured that perhaps there was an ordering issue between
RAM loading and post_load execution on the target host, and so I
proposed to delay the RAM overwrite + SCI injection a bit more;
following the pattern seen in your commit 90c647db8d59.

However, since then, both Ben and myself tested the code with migration
(using "virsh save" (Ben) and "virsh managedsave" (myself)), with
Windows and Linux guests, and it works for us; there seems to be no
ordering issue with the current code (= overwrite RAM + inject SCI in
the post_load callback()).

For now we don't understand why it doesn't work for Igor (Igor used
exec/gzip migration to/from a local file using direct QEMU monitor
commands / options, no libvirt). And, copying the pattern seen in your
commit 90c647db8d59 didn't help in his case (while it wasn't even
necessary for success in Ben's and my testing).

So it seems that delaying the deed with
qemu_add_vm_change_state_handler() is neither needed nor effective in
this case; but then we still don't know why it doesn't work for Igor.

Thanks
Laszlo

> 
> Dave
> 
>> On 02/17/17 11:43, Igor Mammedov wrote:
>>> On Thu, 16 Feb 2017 15:15:36 -0800
>>> ben@skyportsystems.com wrote:
>>>
>>>> From: Ben Warren <ben@skyportsystems.com>
>>>>
>>>> This implements the VM Generation ID feature by passing a 128-bit
>>>> GUID to the guest via a fw_cfg blob.
>>>> Any time the GUID changes, an ACPI notify event is sent to the guest
>>>>
>>>> The user interface is a simple device with one parameter:
>>>>  - guid (string, must be "auto" or in UUID format
>>>>    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
>>> I've given it some testing with WS2012R2 and v4 patches for Seabios,
>>>
>>> Windows is able to read initial GUID allocation and writeback
>>> seems to work somehow:
>>>
>>> (qemu) info vm-generation-id 
>>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
>>>
>>> vmgenid client in Windows reads it as 2 following 64bit integers:
>>> 42d50e8bc109c09b:6cd1dcc90984339b
>>>
>>> However update path/restore from snapshot doesn't
>>> here is as I've tested it:
>>>
>>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
>>> (qemu) info vm-generation-id 
>>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
>>> (qemu) stop
>>> (qemu) migrate "exec:gzip -c > STATEFILE.gz" 
>>> (qemu) quit
>>>
>>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
>>> -incoming "exec: gzip -c -d STATEFILE.gz"
>>> (qemu) info vm-generation-id 
>>> 28b587fa-991b-4267-80d7-9cf28b746fe9
>>>
>>> guest
>>>  1. doesn't get GPE notification that it must receive
>>>  2. vmgenid client in Windows reads the same value
>>>       42d50e8bc109c09b:6cd1dcc90984339b
>>
>> Hmmm, I wonder if we need something like this, in vmgenid_post_load():
>>
>> commit 90c647db8d59e47c9000affc0d81754eb346e939
>> Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
>> Date:   Fri Apr 15 12:41:30 2016 +0100
>>
>>     Fix pflash migration
>>
>> with the idea being that in a single device's post_load callback, we
>> shouldn't perform machine-wide actions (post_load is likely for fixing
>> up the device itself). If machine-wide actions are necessary, we should
>> temporarily register a "vm change state handler", and do the thing once
>> that handler is called (when the machine has been loaded fully and is
>> about to continue execution).
>>
>> Can you please try the attached patch on top? (Build tested only.)
>>
>> Thanks!
>> Laszlo
> 
>> diff --git a/include/hw/acpi/vmgenid.h b/include/hw/acpi/vmgenid.h
>> index db7fa0e63303..a2ae450b1f56 100644
>> --- a/include/hw/acpi/vmgenid.h
>> +++ b/include/hw/acpi/vmgenid.h
>> @@ -4,6 +4,7 @@
>>  #include "hw/acpi/bios-linker-loader.h"
>>  #include "hw/qdev.h"
>>  #include "qemu/uuid.h"
>> +#include "sysemu/sysemu.h"
>>  
>>  #define VMGENID_DEVICE           "vmgenid"
>>  #define VMGENID_GUID             "guid"
>> @@ -21,6 +22,7 @@ typedef struct VmGenIdState {
>>      DeviceClass parent_obj;
>>      QemuUUID guid;                /* The 128-bit GUID seen by the guest */
>>      uint8_t vmgenid_addr_le[8];   /* Address of the GUID (little-endian) */
>> +    VMChangeStateEntry *vmstate;
>>  } VmGenIdState;
>>  
>>  static inline Object *find_vmgenid_dev(void)
>> diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c
>> index 9f97b722761b..0ae1d56ff297 100644
>> --- a/hw/acpi/vmgenid.c
>> +++ b/hw/acpi/vmgenid.c
>> @@ -177,10 +177,20 @@ static void vmgenid_set_guid(Object *obj, const char *value, Error **errp)
>>  /* After restoring an image, we need to update the guest memory and notify
>>   * it of a potential change to VM Generation ID
>>   */
>> +static void postload_update_guest_cb(void *opaque, int running, RunState state)
>> +{
>> +    VmGenIdState *vms = opaque;
>> +
>> +    qemu_del_vm_change_state_handler(vms->vmstate);
>> +    vms->vmstate = NULL;
>> +    vmgenid_update_guest(vms);
>> +}
>> +
>>  static int vmgenid_post_load(void *opaque, int version_id)
>>  {
>>      VmGenIdState *vms = opaque;
>> -    vmgenid_update_guest(vms);
>> +    vms->vmstate = qemu_add_vm_change_state_handler(postload_update_guest_cb,
>> +                                                    vms);
>>      return 0;
>>  }
>>  
> 
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
> 

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-20 10:40         ` Laszlo Ersek
@ 2017-02-20 11:00           ` Dr. David Alan Gilbert
  2017-02-20 11:38             ` Laszlo Ersek
  0 siblings, 1 reply; 53+ messages in thread
From: Dr. David Alan Gilbert @ 2017-02-20 11:00 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: Igor Mammedov, ben, qemu-devel, mst

* Laszlo Ersek (lersek@redhat.com) wrote:
> On 02/20/17 11:23, Dr. David Alan Gilbert wrote:
> > * Laszlo Ersek (lersek@redhat.com) wrote:
> >> CC Dave
> > 
> > This isn't an area I really understand; but if I'm
> > reading this right then 
> >    vmgenid is stored in fw_cfg?
> >    fw_cfg isn't migrated
> > 
> > So why should any changes to it get migrated, except if it's already
> > been read by the guest (and if the guest reads it again aftwards what's
> > it expected to read?)
> 
> This is what we have here:
> - QEMU formats read-only fw_cfg blob with GUID
> - guest downloads blob, places it in guest RAM
> - guest tells QEMU the guest-side address of the blob
> - during migration, guest RAM is transferred
> - after migration, in the device's post_load callback, QEMU overwrites
>   the GUID in guest RAM with a different value, and injects an SCI
> 
> I CC'd you for the following reason: Igor reported that he didn't see
> either the fresh GUID or the SCI in the guest, on the target host, after
> migration. I figured that perhaps there was an ordering issue between
> RAM loading and post_load execution on the target host, and so I
> proposed to delay the RAM overwrite + SCI injection a bit more;
> following the pattern seen in your commit 90c647db8d59.
> 
> However, since then, both Ben and myself tested the code with migration
> (using "virsh save" (Ben) and "virsh managedsave" (myself)), with
> Windows and Linux guests, and it works for us; there seems to be no
> ordering issue with the current code (= overwrite RAM + inject SCI in
> the post_load callback()).
> 
> For now we don't understand why it doesn't work for Igor (Igor used
> exec/gzip migration to/from a local file using direct QEMU monitor
> commands / options, no libvirt). And, copying the pattern seen in your
> commit 90c647db8d59 didn't help in his case (while it wasn't even
> necessary for success in Ben's and my testing).

One thing I noticed in Igor's test was that he did a 'stop' on the source
before the migate, and so it's probably still paused on the destination
after the migration is loaded, so anything the guest needs to do might
not have happened until it's started.

You say;
   'guest tells QEMU the guest-side address of the blob'
how is that stored/migrated/etc ?


> So it seems that delaying the deed with
> qemu_add_vm_change_state_handler() is neither needed nor effective in
> this case; but then we still don't know why it doesn't work for Igor.

Nod.

Dave

> 
> Thanks
> Laszlo
> 
> > 
> > Dave
> > 
> >> On 02/17/17 11:43, Igor Mammedov wrote:
> >>> On Thu, 16 Feb 2017 15:15:36 -0800
> >>> ben@skyportsystems.com wrote:
> >>>
> >>>> From: Ben Warren <ben@skyportsystems.com>
> >>>>
> >>>> This implements the VM Generation ID feature by passing a 128-bit
> >>>> GUID to the guest via a fw_cfg blob.
> >>>> Any time the GUID changes, an ACPI notify event is sent to the guest
> >>>>
> >>>> The user interface is a simple device with one parameter:
> >>>>  - guid (string, must be "auto" or in UUID format
> >>>>    xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
> >>> I've given it some testing with WS2012R2 and v4 patches for Seabios,
> >>>
> >>> Windows is able to read initial GUID allocation and writeback
> >>> seems to work somehow:
> >>>
> >>> (qemu) info vm-generation-id 
> >>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
> >>>
> >>> vmgenid client in Windows reads it as 2 following 64bit integers:
> >>> 42d50e8bc109c09b:6cd1dcc90984339b
> >>>
> >>> However update path/restore from snapshot doesn't
> >>> here is as I've tested it:
> >>>
> >>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
> >>> (qemu) info vm-generation-id 
> >>> c109c09b-0e8b-42d5-9b33-8409c9dcd16c
> >>> (qemu) stop
> >>> (qemu) migrate "exec:gzip -c > STATEFILE.gz" 
> >>> (qemu) quit
> >>>
> >>> qemu-system-x86_64 -device vmgenid,id=testvgid,guid=auto -monitor stdio
> >>> -incoming "exec: gzip -c -d STATEFILE.gz"
> >>> (qemu) info vm-generation-id 
> >>> 28b587fa-991b-4267-80d7-9cf28b746fe9
> >>>
> >>> guest
> >>>  1. doesn't get GPE notification that it must receive
> >>>  2. vmgenid client in Windows reads the same value
> >>>       42d50e8bc109c09b:6cd1dcc90984339b
> >>
> >> Hmmm, I wonder if we need something like this, in vmgenid_post_load():
> >>
> >> commit 90c647db8d59e47c9000affc0d81754eb346e939
> >> Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
> >> Date:   Fri Apr 15 12:41:30 2016 +0100
> >>
> >>     Fix pflash migration
> >>
> >> with the idea being that in a single device's post_load callback, we
> >> shouldn't perform machine-wide actions (post_load is likely for fixing
> >> up the device itself). If machine-wide actions are necessary, we should
> >> temporarily register a "vm change state handler", and do the thing once
> >> that handler is called (when the machine has been loaded fully and is
> >> about to continue execution).
> >>
> >> Can you please try the attached patch on top? (Build tested only.)
> >>
> >> Thanks!
> >> Laszlo
> > 
> >> diff --git a/include/hw/acpi/vmgenid.h b/include/hw/acpi/vmgenid.h
> >> index db7fa0e63303..a2ae450b1f56 100644
> >> --- a/include/hw/acpi/vmgenid.h
> >> +++ b/include/hw/acpi/vmgenid.h
> >> @@ -4,6 +4,7 @@
> >>  #include "hw/acpi/bios-linker-loader.h"
> >>  #include "hw/qdev.h"
> >>  #include "qemu/uuid.h"
> >> +#include "sysemu/sysemu.h"
> >>  
> >>  #define VMGENID_DEVICE           "vmgenid"
> >>  #define VMGENID_GUID             "guid"
> >> @@ -21,6 +22,7 @@ typedef struct VmGenIdState {
> >>      DeviceClass parent_obj;
> >>      QemuUUID guid;                /* The 128-bit GUID seen by the guest */
> >>      uint8_t vmgenid_addr_le[8];   /* Address of the GUID (little-endian) */
> >> +    VMChangeStateEntry *vmstate;
> >>  } VmGenIdState;
> >>  
> >>  static inline Object *find_vmgenid_dev(void)
> >> diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c
> >> index 9f97b722761b..0ae1d56ff297 100644
> >> --- a/hw/acpi/vmgenid.c
> >> +++ b/hw/acpi/vmgenid.c
> >> @@ -177,10 +177,20 @@ static void vmgenid_set_guid(Object *obj, const char *value, Error **errp)
> >>  /* After restoring an image, we need to update the guest memory and notify
> >>   * it of a potential change to VM Generation ID
> >>   */
> >> +static void postload_update_guest_cb(void *opaque, int running, RunState state)
> >> +{
> >> +    VmGenIdState *vms = opaque;
> >> +
> >> +    qemu_del_vm_change_state_handler(vms->vmstate);
> >> +    vms->vmstate = NULL;
> >> +    vmgenid_update_guest(vms);
> >> +}
> >> +
> >>  static int vmgenid_post_load(void *opaque, int version_id)
> >>  {
> >>      VmGenIdState *vms = opaque;
> >> -    vmgenid_update_guest(vms);
> >> +    vms->vmstate = qemu_add_vm_change_state_handler(postload_update_guest_cb,
> >> +                                                    vms);
> >>      return 0;
> >>  }
> >>  
> > 
> > --
> > Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
> > 
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-20 11:00           ` Dr. David Alan Gilbert
@ 2017-02-20 11:38             ` Laszlo Ersek
  2017-02-20 12:32               ` Dr. David Alan Gilbert
  2017-02-20 13:13               ` Igor Mammedov
  0 siblings, 2 replies; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-20 11:38 UTC (permalink / raw)
  To: Dr. David Alan Gilbert; +Cc: Igor Mammedov, ben, qemu-devel, mst

On 02/20/17 12:00, Dr. David Alan Gilbert wrote:
> * Laszlo Ersek (lersek@redhat.com) wrote:
>> On 02/20/17 11:23, Dr. David Alan Gilbert wrote:
>>> * Laszlo Ersek (lersek@redhat.com) wrote:
>>>> CC Dave
>>>
>>> This isn't an area I really understand; but if I'm
>>> reading this right then 
>>>    vmgenid is stored in fw_cfg?
>>>    fw_cfg isn't migrated
>>>
>>> So why should any changes to it get migrated, except if it's already
>>> been read by the guest (and if the guest reads it again aftwards what's
>>> it expected to read?)
>>
>> This is what we have here:
>> - QEMU formats read-only fw_cfg blob with GUID
>> - guest downloads blob, places it in guest RAM
>> - guest tells QEMU the guest-side address of the blob
>> - during migration, guest RAM is transferred
>> - after migration, in the device's post_load callback, QEMU overwrites
>>   the GUID in guest RAM with a different value, and injects an SCI
>>
>> I CC'd you for the following reason: Igor reported that he didn't see
>> either the fresh GUID or the SCI in the guest, on the target host, after
>> migration. I figured that perhaps there was an ordering issue between
>> RAM loading and post_load execution on the target host, and so I
>> proposed to delay the RAM overwrite + SCI injection a bit more;
>> following the pattern seen in your commit 90c647db8d59.
>>
>> However, since then, both Ben and myself tested the code with migration
>> (using "virsh save" (Ben) and "virsh managedsave" (myself)), with
>> Windows and Linux guests, and it works for us; there seems to be no
>> ordering issue with the current code (= overwrite RAM + inject SCI in
>> the post_load callback()).
>>
>> For now we don't understand why it doesn't work for Igor (Igor used
>> exec/gzip migration to/from a local file using direct QEMU monitor
>> commands / options, no libvirt). And, copying the pattern seen in your
>> commit 90c647db8d59 didn't help in his case (while it wasn't even
>> necessary for success in Ben's and my testing).
> 
> One thing I noticed in Igor's test was that he did a 'stop' on the source
> before the migate, and so it's probably still paused on the destination
> after the migration is loaded, so anything the guest needs to do might
> not have happened until it's started.

Interesting! I hope Igor can double-check this!

In the virsh docs, before doing my tests, I read that "managedsave"
optionally took --running or --paused:

    Normally, starting a managed save will decide between running or
    paused based on the state the domain was in when the save was done;
    passing either the --running or --paused flag will allow overriding
    which state the start should use.

I didn't pass any such flag ultimately, and I didn't stop the guests
before the managedsave. Indeed they continued execution right after
being loaded with "virsh start".

(Side point: managedsave is awesome. :) )

> 
> You say;
>    'guest tells QEMU the guest-side address of the blob'
> how is that stored/migrated/etc ?

It is a uint8_t[8] array (little endian representation), linked into
another (writeable) fw_cfg entry, and it's migrated explicitly (it has a
descriptor in the device's vmstate descriptor). The post_load callback
relies on this array being restored before the migration infrastructure
calls post_load.

Thanks
Laszlo

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-20 11:38             ` Laszlo Ersek
@ 2017-02-20 12:32               ` Dr. David Alan Gilbert
  2017-02-20 15:35                 ` Laszlo Ersek
  2017-02-20 13:13               ` Igor Mammedov
  1 sibling, 1 reply; 53+ messages in thread
From: Dr. David Alan Gilbert @ 2017-02-20 12:32 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: Igor Mammedov, ben, qemu-devel, mst

* Laszlo Ersek (lersek@redhat.com) wrote:
> On 02/20/17 12:00, Dr. David Alan Gilbert wrote:
> > * Laszlo Ersek (lersek@redhat.com) wrote:
> >> On 02/20/17 11:23, Dr. David Alan Gilbert wrote:
> >>> * Laszlo Ersek (lersek@redhat.com) wrote:
> >>>> CC Dave
> >>>
> >>> This isn't an area I really understand; but if I'm
> >>> reading this right then 
> >>>    vmgenid is stored in fw_cfg?
> >>>    fw_cfg isn't migrated
> >>>
> >>> So why should any changes to it get migrated, except if it's already
> >>> been read by the guest (and if the guest reads it again aftwards what's
> >>> it expected to read?)
> >>
> >> This is what we have here:
> >> - QEMU formats read-only fw_cfg blob with GUID
> >> - guest downloads blob, places it in guest RAM
> >> - guest tells QEMU the guest-side address of the blob
> >> - during migration, guest RAM is transferred
> >> - after migration, in the device's post_load callback, QEMU overwrites
> >>   the GUID in guest RAM with a different value, and injects an SCI
> >>
> >> I CC'd you for the following reason: Igor reported that he didn't see
> >> either the fresh GUID or the SCI in the guest, on the target host, after
> >> migration. I figured that perhaps there was an ordering issue between
> >> RAM loading and post_load execution on the target host, and so I
> >> proposed to delay the RAM overwrite + SCI injection a bit more;
> >> following the pattern seen in your commit 90c647db8d59.
> >>
> >> However, since then, both Ben and myself tested the code with migration
> >> (using "virsh save" (Ben) and "virsh managedsave" (myself)), with
> >> Windows and Linux guests, and it works for us; there seems to be no
> >> ordering issue with the current code (= overwrite RAM + inject SCI in
> >> the post_load callback()).
> >>
> >> For now we don't understand why it doesn't work for Igor (Igor used
> >> exec/gzip migration to/from a local file using direct QEMU monitor
> >> commands / options, no libvirt). And, copying the pattern seen in your
> >> commit 90c647db8d59 didn't help in his case (while it wasn't even
> >> necessary for success in Ben's and my testing).
> > 
> > One thing I noticed in Igor's test was that he did a 'stop' on the source
> > before the migate, and so it's probably still paused on the destination
> > after the migration is loaded, so anything the guest needs to do might
> > not have happened until it's started.
> 
> Interesting! I hope Igor can double-check this!
> 
> In the virsh docs, before doing my tests, I read that "managedsave"
> optionally took --running or --paused:
> 
>     Normally, starting a managed save will decide between running or
>     paused based on the state the domain was in when the save was done;
>     passing either the --running or --paused flag will allow overriding
>     which state the start should use.
> 
> I didn't pass any such flag ultimately, and I didn't stop the guests
> before the managedsave. Indeed they continued execution right after
> being loaded with "virsh start".
> 
> (Side point: managedsave is awesome. :) )

If I've followed the bread crumbs correctly, I think managedsave
is just using a migrate to fd anyway, so the same code.

> > 
> > You say;
> >    'guest tells QEMU the guest-side address of the blob'
> > how is that stored/migrated/etc ?
> 
> It is a uint8_t[8] array (little endian representation), linked into
> another (writeable) fw_cfg entry, and it's migrated explicitly (it has a
> descriptor in the device's vmstate descriptor). The post_load callback
> relies on this array being restored before the migration infrastructure
> calls post_load.

RAM normally comes back before other devices, so you should be OK;
although we frequently have problems with devices reading from RAM
during device init before migration has started, or writing to it
after migration has finished on the source.

Dave

> 
> Thanks
> Laszlo
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-20 11:38             ` Laszlo Ersek
  2017-02-20 12:32               ` Dr. David Alan Gilbert
@ 2017-02-20 13:13               ` Igor Mammedov
  2017-02-20 13:28                 ` Laszlo Ersek
  1 sibling, 1 reply; 53+ messages in thread
From: Igor Mammedov @ 2017-02-20 13:13 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: Dr. David Alan Gilbert, qemu-devel, ben, mst

On Mon, 20 Feb 2017 12:38:06 +0100
Laszlo Ersek <lersek@redhat.com> wrote:

> On 02/20/17 12:00, Dr. David Alan Gilbert wrote:
> > * Laszlo Ersek (lersek@redhat.com) wrote:  
> >> On 02/20/17 11:23, Dr. David Alan Gilbert wrote:  
> >>> * Laszlo Ersek (lersek@redhat.com) wrote:  
> >>>> CC Dave  
> >>>
> >>> This isn't an area I really understand; but if I'm
> >>> reading this right then 
> >>>    vmgenid is stored in fw_cfg?
> >>>    fw_cfg isn't migrated
> >>>
> >>> So why should any changes to it get migrated, except if it's already
> >>> been read by the guest (and if the guest reads it again aftwards what's
> >>> it expected to read?)  
> >>
> >> This is what we have here:
> >> - QEMU formats read-only fw_cfg blob with GUID
> >> - guest downloads blob, places it in guest RAM
> >> - guest tells QEMU the guest-side address of the blob
> >> - during migration, guest RAM is transferred
> >> - after migration, in the device's post_load callback, QEMU overwrites
> >>   the GUID in guest RAM with a different value, and injects an SCI
> >>
> >> I CC'd you for the following reason: Igor reported that he didn't see
> >> either the fresh GUID or the SCI in the guest, on the target host, after
> >> migration. I figured that perhaps there was an ordering issue between
> >> RAM loading and post_load execution on the target host, and so I
> >> proposed to delay the RAM overwrite + SCI injection a bit more;
> >> following the pattern seen in your commit 90c647db8d59.
> >>
> >> However, since then, both Ben and myself tested the code with migration
> >> (using "virsh save" (Ben) and "virsh managedsave" (myself)), with
> >> Windows and Linux guests, and it works for us; there seems to be no
> >> ordering issue with the current code (= overwrite RAM + inject SCI in
> >> the post_load callback()).
> >>
> >> For now we don't understand why it doesn't work for Igor (Igor used
> >> exec/gzip migration to/from a local file using direct QEMU monitor
> >> commands / options, no libvirt). And, copying the pattern seen in your
> >> commit 90c647db8d59 didn't help in his case (while it wasn't even
> >> necessary for success in Ben's and my testing).  
> > 
> > One thing I noticed in Igor's test was that he did a 'stop' on the source
> > before the migate, and so it's probably still paused on the destination
> > after the migration is loaded, so anything the guest needs to do might
> > not have happened until it's started.  
> 
> Interesting! I hope Igor can double-check this!
I've retested v7, and it reliably fails (vmgenid_wait doesn't see change)
then I tested v8(qemu) + (seabios v5/v4) with the same steps as before
and it appears to work as expected, i.e. vmgenid_wait reports GUID
change after executing 'continue' monitor command so something
has been fixed in v8.


> 
> In the virsh docs, before doing my tests, I read that "managedsave"
> optionally took --running or --paused:
> 
>     Normally, starting a managed save will decide between running or
>     paused based on the state the domain was in when the save was done;
>     passing either the --running or --paused flag will allow overriding
>     which state the start should use.
> 
> I didn't pass any such flag ultimately, and I didn't stop the guests
> before the managedsave. Indeed they continued execution right after
> being loaded with "virsh start".
> 
> (Side point: managedsave is awesome. :) )
> 
> > 
> > You say;
> >    'guest tells QEMU the guest-side address of the blob'
> > how is that stored/migrated/etc ?  
> 
> It is a uint8_t[8] array (little endian representation), linked into
> another (writeable) fw_cfg entry, and it's migrated explicitly (it has a
> descriptor in the device's vmstate descriptor). The post_load callback
> relies on this array being restored before the migration infrastructure
> calls post_load.
> 
> Thanks
> Laszlo
> 

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-20 13:13               ` Igor Mammedov
@ 2017-02-20 13:28                 ` Laszlo Ersek
  2017-02-20 14:40                   ` Igor Mammedov
  0 siblings, 1 reply; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-20 13:28 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: Dr. David Alan Gilbert, qemu-devel, ben, mst

On 02/20/17 14:13, Igor Mammedov wrote:
> On Mon, 20 Feb 2017 12:38:06 +0100
> Laszlo Ersek <lersek@redhat.com> wrote:
> 
>> On 02/20/17 12:00, Dr. David Alan Gilbert wrote:
>>> * Laszlo Ersek (lersek@redhat.com) wrote:  
>>>> On 02/20/17 11:23, Dr. David Alan Gilbert wrote:  
>>>>> * Laszlo Ersek (lersek@redhat.com) wrote:  
>>>>>> CC Dave  
>>>>>
>>>>> This isn't an area I really understand; but if I'm
>>>>> reading this right then 
>>>>>    vmgenid is stored in fw_cfg?
>>>>>    fw_cfg isn't migrated
>>>>>
>>>>> So why should any changes to it get migrated, except if it's already
>>>>> been read by the guest (and if the guest reads it again aftwards what's
>>>>> it expected to read?)  
>>>>
>>>> This is what we have here:
>>>> - QEMU formats read-only fw_cfg blob with GUID
>>>> - guest downloads blob, places it in guest RAM
>>>> - guest tells QEMU the guest-side address of the blob
>>>> - during migration, guest RAM is transferred
>>>> - after migration, in the device's post_load callback, QEMU overwrites
>>>>   the GUID in guest RAM with a different value, and injects an SCI
>>>>
>>>> I CC'd you for the following reason: Igor reported that he didn't see
>>>> either the fresh GUID or the SCI in the guest, on the target host, after
>>>> migration. I figured that perhaps there was an ordering issue between
>>>> RAM loading and post_load execution on the target host, and so I
>>>> proposed to delay the RAM overwrite + SCI injection a bit more;
>>>> following the pattern seen in your commit 90c647db8d59.
>>>>
>>>> However, since then, both Ben and myself tested the code with migration
>>>> (using "virsh save" (Ben) and "virsh managedsave" (myself)), with
>>>> Windows and Linux guests, and it works for us; there seems to be no
>>>> ordering issue with the current code (= overwrite RAM + inject SCI in
>>>> the post_load callback()).
>>>>
>>>> For now we don't understand why it doesn't work for Igor (Igor used
>>>> exec/gzip migration to/from a local file using direct QEMU monitor
>>>> commands / options, no libvirt). And, copying the pattern seen in your
>>>> commit 90c647db8d59 didn't help in his case (while it wasn't even
>>>> necessary for success in Ben's and my testing).  
>>>
>>> One thing I noticed in Igor's test was that he did a 'stop' on the source
>>> before the migate, and so it's probably still paused on the destination
>>> after the migration is loaded, so anything the guest needs to do might
>>> not have happened until it's started.  
>>
>> Interesting! I hope Igor can double-check this!
> I've retested v7, and it reliably fails (vmgenid_wait doesn't see change)
> then I tested v8(qemu) + (seabios v5/v4) with the same steps as before
> and it appears to work as expected, i.e. vmgenid_wait reports GUID
> change after executing 'continue' monitor command so something
> has been fixed in v8.

Yes, I know what. Please see item (2) in this reply of mine, for v7 1/8:

msgid: <9e222b4c-c05d-8fd0-6c55-4b2e52cab7b0@redhat.com>
URL: https://www.mail-archive.com/qemu-devel@nongnu.org/msg430440.html

With that copy/paste bug in the code, the "src_offset" field of
WRITE_POINTER was not populated correctly. The BIOS would carry that out
faithfully, of course, but then later QEMU would write the fresh GUID to
an incorrect offset in the guest firmware allocated area -- the offset
wouldn't match the AML code (ADDR method), so the guest OS wouldn't see
the change.


If you scroll to the end of my message linked above, I wrote -- again,
for v7 --:

    I also tested this series (with the assignment under (2) fixed up,
    of course), as documented earlier in
<https://www.mail-archive.com/qemu-devel@nongnu.org/msg430075.html>
    (msgid  <678c203f-3768-7e65-6e48-6729473b6...@redhat.com>).

    Hence, with (1) and (2) fixed, you can also add

    Tested-by: Laszlo Ersek <ler...@redhat.com>

In other words, my positive testing for v7 was conditional on my *local*
(but reported, suggested) fix for bug (2) in v7 1/8. And that issue has
been fixed in v8.

... So, I guess we're all OK now. Can you confirm please?

Thanks!
Laszlo



> 
> 
>>
>> In the virsh docs, before doing my tests, I read that "managedsave"
>> optionally took --running or --paused:
>>
>>     Normally, starting a managed save will decide between running or
>>     paused based on the state the domain was in when the save was done;
>>     passing either the --running or --paused flag will allow overriding
>>     which state the start should use.
>>
>> I didn't pass any such flag ultimately, and I didn't stop the guests
>> before the managedsave. Indeed they continued execution right after
>> being loaded with "virsh start".
>>
>> (Side point: managedsave is awesome. :) )
>>
>>>
>>> You say;
>>>    'guest tells QEMU the guest-side address of the blob'
>>> how is that stored/migrated/etc ?  
>>
>> It is a uint8_t[8] array (little endian representation), linked into
>> another (writeable) fw_cfg entry, and it's migrated explicitly (it has a
>> descriptor in the device's vmstate descriptor). The post_load callback
>> relies on this array being restored before the migration infrastructure
>> calls post_load.
>>
>> Thanks
>> Laszlo
>>
> 

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-20 13:28                 ` Laszlo Ersek
@ 2017-02-20 14:40                   ` Igor Mammedov
  0 siblings, 0 replies; 53+ messages in thread
From: Igor Mammedov @ 2017-02-20 14:40 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: mst, Dr. David Alan Gilbert, ben, qemu-devel

On Mon, 20 Feb 2017 14:28:11 +0100
Laszlo Ersek <lersek@redhat.com> wrote:

> On 02/20/17 14:13, Igor Mammedov wrote:
> > On Mon, 20 Feb 2017 12:38:06 +0100
> > Laszlo Ersek <lersek@redhat.com> wrote:
[...]
> >> Interesting! I hope Igor can double-check this!  
> > I've retested v7, and it reliably fails (vmgenid_wait doesn't see change)
> > then I tested v8(qemu) + (seabios v5/v4) with the same steps as before
> > and it appears to work as expected, i.e. vmgenid_wait reports GUID
> > change after executing 'continue' monitor command so something
> > has been fixed in v8.  
> 
> Yes, I know what. Please see item (2) in this reply of mine, for v7 1/8:
> 
> msgid: <9e222b4c-c05d-8fd0-6c55-4b2e52cab7b0@redhat.com>
> URL: https://www.mail-archive.com/qemu-devel@nongnu.org/msg430440.html
> 
> With that copy/paste bug in the code, the "src_offset" field of
> WRITE_POINTER was not populated correctly. The BIOS would carry that out
> faithfully, of course, but then later QEMU would write the fresh GUID to
> an incorrect offset in the guest firmware allocated area -- the offset
> wouldn't match the AML code (ADDR method), so the guest OS wouldn't see
> the change.
> 
> 
> If you scroll to the end of my message linked above, I wrote -- again,
> for v7 --:
> 
>     I also tested this series (with the assignment under (2) fixed up,
>     of course), as documented earlier in
> <https://www.mail-archive.com/qemu-devel@nongnu.org/msg430075.html>
>     (msgid  <678c203f-3768-7e65-6e48-6729473b6...@redhat.com>).
> 
>     Hence, with (1) and (2) fixed, you can also add
> 
>     Tested-by: Laszlo Ersek <ler...@redhat.com>
> 
> In other words, my positive testing for v7 was conditional on my *local*
> (but reported, suggested) fix for bug (2) in v7 1/8. And that issue has
> been fixed in v8.
> 
> ... So, I guess we're all OK now. Can you confirm please?
Confirmed

> 
> Thanks!
> Laszlo
[...]

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 7/8] tests: Add unit tests for the VM Generation ID feature
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 7/8] tests: Add unit tests for the VM Generation ID feature ben
@ 2017-02-20 14:49   ` Igor Mammedov
  2017-04-21 10:14     ` Marc-André Lureau
  0 siblings, 1 reply; 53+ messages in thread
From: Igor Mammedov @ 2017-02-20 14:49 UTC (permalink / raw)
  To: ben; +Cc: qemu-devel, lersek, mst

On Thu, 16 Feb 2017 15:15:39 -0800
ben@skyportsystems.com wrote:

> From: Ben Warren <ben@skyportsystems.com>
> 
> The following tests are implemented:
> * test that a GUID passed in by command line is propagated to the guest.
>   Read the GUID from guest memory
> * test that the "auto" argument to the GUID generates a valid GUID, as
>   seen by the guest.
> * test that a GUID passed in can be queried from the monitor
> 
>   This patch is loosely based on a previous patch from:
>   Gal Hammer <ghammer@redhat.com>  and Igor Mammedov <imammedo@redhat.com>
> 
> Signed-off-by: Ben Warren <ben@skyportsystems.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  tests/Makefile.include |   2 +
>  tests/vmgenid-test.c   | 200 +++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 202 insertions(+)
>  create mode 100644 tests/vmgenid-test.c
> 
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index 143507e..8d36341 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -241,6 +241,7 @@ check-qtest-i386-y += tests/usb-hcd-xhci-test$(EXESUF)
>  gcov-files-i386-y += hw/usb/hcd-xhci.c
>  check-qtest-i386-y += tests/pc-cpu-test$(EXESUF)
>  check-qtest-i386-y += tests/q35-test$(EXESUF)
> +check-qtest-i386-y += tests/vmgenid-test$(EXESUF)
>  gcov-files-i386-y += hw/pci-host/q35.c
>  check-qtest-i386-$(CONFIG_VHOST_NET_TEST_i386) += tests/vhost-user-test$(EXESUF)
>  ifeq ($(CONFIG_VHOST_NET_TEST_i386),)
> @@ -726,6 +727,7 @@ tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o contrib/ivshmem-server/ivshmem
>  tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o contrib/libvhost-user/libvhost-user.o $(test-util-obj-y)
>  tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y)
>  tests/test-arm-mptimer$(EXESUF): tests/test-arm-mptimer.o
> +tests/vmgenid-test$(EXESUF): tests/vmgenid-test.o tests/acpi-utils.o
>  
>  tests/migration/stress$(EXESUF): tests/migration/stress.o
>  	$(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ,"LINK","$(TARGET_DIR)$@")
> diff --git a/tests/vmgenid-test.c b/tests/vmgenid-test.c
> new file mode 100644
> index 0000000..123beae
> --- /dev/null
> +++ b/tests/vmgenid-test.c
> @@ -0,0 +1,200 @@
> +/*
> + * QTest testcase for VM Generation ID
> + *
> + * Copyright (c) 2016 Red Hat, Inc.
> + * Copyright (c) 2017 Skyport Systems
> + *
> + * 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 <glib.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include "qemu/osdep.h"
> +#include "qemu/bitmap.h"
> +#include "qemu/uuid.h"
> +#include "hw/acpi/acpi-defs.h"
> +#include "acpi-utils.h"
> +#include "libqtest.h"
> +
> +#define VGID_GUID "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
> +#define VMGENID_GUID_OFFSET 40   /* allow space for
> +                                  * OVMF SDT Header Probe Supressor
> +                                  */
> +#define RSDP_ADDR_INVALID 0x100000 /* RSDP must be below this address */
> +#define RSDP_SLEEP_US     100000   /* Sleep for 100ms between tries */
> +#define RSDP_TRIES_MAX    100      /* Max total time is 10 seconds */
> +
> +typedef struct {
> +    AcpiTableHeader header;
> +    gchar name_op;
> +    gchar vgia[4];
> +    gchar val_op;
> +    uint32_t vgia_val;
> +} QEMU_PACKED VgidTable;
> +
> +static uint32_t acpi_find_vgia(void)
> +{
> +    uint32_t off;
> +    AcpiRsdpDescriptor rsdp_table;
> +    uint32_t rsdt;
> +    AcpiRsdtDescriptorRev1 rsdt_table;
> +    int tables_nr;
> +    uint32_t *tables;
> +    AcpiTableHeader ssdt_table;
> +    VgidTable vgid_table;
> +    int i;
> +
> +    /* Tables may take a short time to be set up by the guest */
> +    for (i = 0; i < RSDP_TRIES_MAX; i++) {
> +        off = acpi_find_rsdp_address();
> +        if (off < RSDP_ADDR_INVALID) {
> +            break;
> +        }
> +        g_usleep(RSDP_SLEEP_US);
> +    }
> +    g_assert_cmphex(off, <, RSDP_ADDR_INVALID);
> +
> +    acpi_parse_rsdp_table(off, &rsdp_table);
> +
> +    rsdt = rsdp_table.rsdt_physical_address;
> +    /* read the header */
> +    ACPI_READ_TABLE_HEADER(&rsdt_table, rsdt);
> +    ACPI_ASSERT_CMP(rsdt_table.signature, "RSDT");
> +
> +    /* compute the table entries in rsdt */
> +    tables_nr = (rsdt_table.length - sizeof(AcpiRsdtDescriptorRev1)) /
> +                sizeof(uint32_t);
> +    g_assert_cmpint(tables_nr, >, 0);
> +
> +    /* get the addresses of the tables pointed by rsdt */
> +    tables = g_new0(uint32_t, tables_nr);
> +    ACPI_READ_ARRAY_PTR(tables, tables_nr, rsdt);
> +
> +    for (i = 0; i < tables_nr; i++) {
> +        ACPI_READ_TABLE_HEADER(&ssdt_table, tables[i]);
> +        if (!strncmp((char *)ssdt_table.oem_table_id, "VMGENID", 7)) {
> +            /* the first entry in the table should be VGIA
> +             * That's all we need
> +             */
> +            ACPI_READ_FIELD(vgid_table.name_op, tables[i]);
> +            g_assert(vgid_table.name_op == 0x08);  /* name */
> +            ACPI_READ_ARRAY(vgid_table.vgia, tables[i]);
> +            g_assert(memcmp(vgid_table.vgia, "VGIA", 4) == 0);
> +            ACPI_READ_FIELD(vgid_table.val_op, tables[i]);
> +            g_assert(vgid_table.val_op == 0x0C);  /* dword */
> +            ACPI_READ_FIELD(vgid_table.vgia_val, tables[i]);
> +            /* The GUID is written at a fixed offset into the fw_cfg file
> +             * in order to implement the "OVMF SDT Header probe suppressor"
> +             * see docs/specs/vmgenid.txt for more details
> +             */
> +            return vgid_table.vgia_val + VMGENID_GUID_OFFSET;
> +        }
> +    }
> +    return 0;
> +}
> +
> +static void read_guid_from_memory(QemuUUID *guid)
> +{
> +    uint32_t vmgenid_addr;
> +    int i;
> +
> +    vmgenid_addr = acpi_find_vgia();
> +    g_assert(vmgenid_addr);
> +
> +    /* Read the GUID directly from guest memory */
> +    for (i = 0; i < 16; i++) {
> +        guid->data[i] = readb(vmgenid_addr + i);
> +    }
> +    /* The GUID is in little-endian format in the guest, while QEMU
> +     * uses big-endian.  Swap after reading.
> +     */
> +    qemu_uuid_bswap(guid);
> +}
> +
> +static void read_guid_from_monitor(QemuUUID *guid)
> +{
> +    QDict *rsp, *rsp_ret;
> +    const char *guid_str;
> +
> +    rsp = qmp("{ 'execute': 'query-vm-generation-id' }");
> +    if (qdict_haskey(rsp, "return")) {
> +        rsp_ret = qdict_get_qdict(rsp, "return");
> +        g_assert(qdict_haskey(rsp_ret, "guid"));
> +        guid_str = qdict_get_str(rsp_ret, "guid");
> +        g_assert(qemu_uuid_parse(guid_str, guid) == 0);
> +    }
> +    QDECREF(rsp);
> +}
> +
> +static void vmgenid_set_guid_test(void)
> +{
> +    QemuUUID expected, measured;
> +    gchar *cmd;
> +
> +    g_assert(qemu_uuid_parse(VGID_GUID, &expected) == 0);
> +
> +    cmd = g_strdup_printf("-machine accel=tcg -device vmgenid,id=testvgid,"
> +                          "guid=%s", VGID_GUID);
> +    qtest_start(cmd);
> +
> +    /* Read the GUID from accessing guest memory */
> +    read_guid_from_memory(&measured);
> +    g_assert(memcmp(measured.data, expected.data, sizeof(measured.data)) == 0);
> +
> +    qtest_quit(global_qtest);
> +    g_free(cmd);
> +}
> +
> +static void vmgenid_set_guid_auto_test(void)
> +{
> +    const char *cmd;
> +    QemuUUID measured;
> +
> +    cmd = "-machine accel=tcg -device vmgenid,id=testvgid," "guid=auto";
> +    qtest_start(cmd);
> +
> +    read_guid_from_memory(&measured);
> +
> +    /* Just check that the GUID is non-null */
> +    g_assert(!qemu_uuid_is_null(&measured));
> +
> +    qtest_quit(global_qtest);
> +}
> +
> +static void vmgenid_query_monitor_test(void)
> +{
> +    QemuUUID expected, measured;
> +    gchar *cmd;
> +
> +    g_assert(qemu_uuid_parse(VGID_GUID, &expected) == 0);
> +
> +    cmd = g_strdup_printf("-machine accel=tcg -device vmgenid,id=testvgid,"
> +                          "guid=%s", VGID_GUID);
> +    qtest_start(cmd);
> +
> +    /* Read the GUID via the monitor */
> +    read_guid_from_monitor(&measured);
> +    g_assert(memcmp(measured.data, expected.data, sizeof(measured.data)) == 0);
> +
> +    qtest_quit(global_qtest);
> +    g_free(cmd);
> +}
> +
> +int main(int argc, char **argv)
> +{
> +    int ret;
> +
> +    g_test_init(&argc, &argv, NULL);
> +
> +    qtest_add_func("/vmgenid/vmgenid/set-guid",
> +                   vmgenid_set_guid_test);
> +    qtest_add_func("/vmgenid/vmgenid/set-guid-auto",
> +                   vmgenid_set_guid_auto_test);
> +    qtest_add_func("/vmgenid/vmgenid/query-monitor",
> +                   vmgenid_query_monitor_test);
> +    ret = g_test_run();
> +
> +    return ret;
> +}

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 6/8] tests: Move reusable ACPI code into a utility file
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 6/8] tests: Move reusable ACPI code into a utility file ben
@ 2017-02-20 14:49   ` Igor Mammedov
  0 siblings, 0 replies; 53+ messages in thread
From: Igor Mammedov @ 2017-02-20 14:49 UTC (permalink / raw)
  To: ben; +Cc: qemu-devel, lersek, mst

On Thu, 16 Feb 2017 15:15:38 -0800
ben@skyportsystems.com wrote:

> From: Ben Warren <ben@skyportsystems.com>
> 
> Also usable by upcoming VM Generation ID tests
> 
> Signed-off-by: Ben Warren <ben@skyportsystems.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  MAINTAINERS              |   2 +
>  tests/Makefile.include   |   2 +-
>  tests/acpi-utils.c       |  65 +++++++++++++++++++++++
>  tests/acpi-utils.h       |  94 +++++++++++++++++++++++++++++++++
>  tests/bios-tables-test.c | 132 ++++++-----------------------------------------
>  5 files changed, 177 insertions(+), 118 deletions(-)
>  create mode 100644 tests/acpi-utils.c
>  create mode 100644 tests/acpi-utils.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index fb57d8e..81d4baf 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -909,6 +909,8 @@ F: hw/acpi/*
>  F: hw/smbios/*
>  F: hw/i386/acpi-build.[hc]
>  F: hw/arm/virt-acpi-build.c
> +F: tests/bios-tables-test.c
> +F: tests/acpi-utils.[hc]
>  
>  ppc4xx
>  M: Alexander Graf <agraf@suse.de>
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index 634394a..143507e 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -667,7 +667,7 @@ tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
>  tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y)
>  tests/boot-serial-test$(EXESUF): tests/boot-serial-test.o $(libqos-obj-y)
>  tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \
> -	tests/boot-sector.o $(libqos-obj-y)
> +	tests/boot-sector.o tests/acpi-utils.o $(libqos-obj-y)
>  tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y)
>  tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
>  tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y)
> diff --git a/tests/acpi-utils.c b/tests/acpi-utils.c
> new file mode 100644
> index 0000000..41dc1ea
> --- /dev/null
> +++ b/tests/acpi-utils.c
> @@ -0,0 +1,65 @@
> +/*
> + * ACPI Utility Functions
> + *
> + * Copyright (c) 2013 Red Hat Inc.
> + * Copyright (c) 2017 Skyport Systems
> + *
> + * Authors:
> + *  Michael S. Tsirkin <mst@redhat.com>,
> + *  Ben Warren <ben@skyportsystems.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 "qemu/osdep.h"
> +#include <glib/gstdio.h>
> +#include "qemu-common.h"
> +#include "hw/smbios/smbios.h"
> +#include "qemu/bitmap.h"
> +#include "acpi-utils.h"
> +#include "boot-sector.h"
> +
> +uint8_t acpi_calc_checksum(const uint8_t *data, int len)
> +{
> +    int i;
> +    uint8_t sum = 0;
> +
> +    for (i = 0; i < len; i++) {
> +        sum += data[i];
> +    }
> +
> +    return sum;
> +}
> +
> +uint32_t acpi_find_rsdp_address(void)
> +{
> +    uint32_t off;
> +
> +    /* RSDP location can vary across a narrow range */
> +    for (off = 0xf0000; off < 0x100000; off += 0x10) {
> +        uint8_t sig[] = "RSD PTR ";
> +        int i;
> +
> +        for (i = 0; i < sizeof sig - 1; ++i) {
> +            sig[i] = readb(off + i);
> +        }
> +
> +        if (!memcmp(sig, "RSD PTR ", sizeof sig)) {
> +            break;
> +        }
> +    }
> +    return off;
> +}
> +
> +void acpi_parse_rsdp_table(uint32_t addr, AcpiRsdpDescriptor *rsdp_table)
> +{
> +    ACPI_READ_FIELD(rsdp_table->signature, addr);
> +    ACPI_ASSERT_CMP64(rsdp_table->signature, "RSD PTR ");
> +
> +    ACPI_READ_FIELD(rsdp_table->checksum, addr);
> +    ACPI_READ_ARRAY(rsdp_table->oem_id, addr);
> +    ACPI_READ_FIELD(rsdp_table->revision, addr);
> +    ACPI_READ_FIELD(rsdp_table->rsdt_physical_address, addr);
> +    ACPI_READ_FIELD(rsdp_table->length, addr);
> +}
> diff --git a/tests/acpi-utils.h b/tests/acpi-utils.h
> new file mode 100644
> index 0000000..9f9a2d5
> --- /dev/null
> +++ b/tests/acpi-utils.h
> @@ -0,0 +1,94 @@
> +/*
> + * Utilities for working with ACPI tables
> + *
> + * Copyright (c) 2013 Red Hat Inc.
> + *
> + * Authors:
> + *  Michael S. Tsirkin <mst@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 TEST_ACPI_UTILS_H
> +#define TEST_ACPI_UTILS_H
> +
> +#include "hw/acpi/acpi-defs.h"
> +#include "libqtest.h"
> +
> +/* DSDT and SSDTs format */
> +typedef struct {
> +    AcpiTableHeader header;
> +    gchar *aml;            /* aml bytecode from guest */
> +    gsize aml_len;
> +    gchar *aml_file;
> +    gchar *asl;            /* asl code generated from aml */
> +    gsize asl_len;
> +    gchar *asl_file;
> +    bool tmp_files_retain;   /* do not delete the temp asl/aml */
> +} QEMU_PACKED AcpiSdtTable;
> +
> +#define ACPI_READ_FIELD(field, addr)           \
> +    do {                                       \
> +        switch (sizeof(field)) {               \
> +        case 1:                                \
> +            field = readb(addr);               \
> +            break;                             \
> +        case 2:                                \
> +            field = readw(addr);               \
> +            break;                             \
> +        case 4:                                \
> +            field = readl(addr);               \
> +            break;                             \
> +        case 8:                                \
> +            field = readq(addr);               \
> +            break;                             \
> +        default:                               \
> +            g_assert(false);                   \
> +        }                                      \
> +        addr += sizeof(field);                  \
> +    } while (0);
> +
> +#define ACPI_READ_ARRAY_PTR(arr, length, addr)  \
> +    do {                                        \
> +        int idx;                                \
> +        for (idx = 0; idx < length; ++idx) {    \
> +            ACPI_READ_FIELD(arr[idx], addr);    \
> +        }                                       \
> +    } while (0);
> +
> +#define ACPI_READ_ARRAY(arr, addr)                               \
> +    ACPI_READ_ARRAY_PTR(arr, sizeof(arr) / sizeof(arr[0]), addr)
> +
> +#define ACPI_READ_TABLE_HEADER(table, addr)                      \
> +    do {                                                         \
> +        ACPI_READ_FIELD((table)->signature, addr);               \
> +        ACPI_READ_FIELD((table)->length, addr);                  \
> +        ACPI_READ_FIELD((table)->revision, addr);                \
> +        ACPI_READ_FIELD((table)->checksum, addr);                \
> +        ACPI_READ_ARRAY((table)->oem_id, addr);                  \
> +        ACPI_READ_ARRAY((table)->oem_table_id, addr);            \
> +        ACPI_READ_FIELD((table)->oem_revision, addr);            \
> +        ACPI_READ_ARRAY((table)->asl_compiler_id, addr);         \
> +        ACPI_READ_FIELD((table)->asl_compiler_revision, addr);   \
> +    } while (0);
> +
> +#define ACPI_ASSERT_CMP(actual, expected) do { \
> +    uint32_t ACPI_ASSERT_CMP_le = cpu_to_le32(actual); \
> +    char ACPI_ASSERT_CMP_str[5] = {}; \
> +    memcpy(ACPI_ASSERT_CMP_str, &ACPI_ASSERT_CMP_le, 4); \
> +    g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
> +} while (0)
> +
> +#define ACPI_ASSERT_CMP64(actual, expected) do { \
> +    uint64_t ACPI_ASSERT_CMP_le = cpu_to_le64(actual); \
> +    char ACPI_ASSERT_CMP_str[9] = {}; \
> +    memcpy(ACPI_ASSERT_CMP_str, &ACPI_ASSERT_CMP_le, 8); \
> +    g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
> +} while (0)
> +
> +uint8_t acpi_calc_checksum(const uint8_t *data, int len);
> +uint32_t acpi_find_rsdp_address(void);
> +void acpi_parse_rsdp_table(uint32_t addr, AcpiRsdpDescriptor *rsdp_table);
> +
> +#endif  /* TEST_ACPI_UTILS_H */
> diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
> index 5404805..423a6f5 100644
> --- a/tests/bios-tables-test.c
> +++ b/tests/bios-tables-test.c
> @@ -13,10 +13,9 @@
>  #include "qemu/osdep.h"
>  #include <glib/gstdio.h>
>  #include "qemu-common.h"
> -#include "libqtest.h"
> -#include "hw/acpi/acpi-defs.h"
>  #include "hw/smbios/smbios.h"
>  #include "qemu/bitmap.h"
> +#include "acpi-utils.h"
>  #include "boot-sector.h"
>  
>  #define MACHINE_PC "pc"
> @@ -24,18 +23,6 @@
>  
>  #define ACPI_REBUILD_EXPECTED_AML "TEST_ACPI_REBUILD_AML"
>  
> -/* DSDT and SSDTs format */
> -typedef struct {
> -    AcpiTableHeader header;
> -    gchar *aml;            /* aml bytecode from guest */
> -    gsize aml_len;
> -    gchar *aml_file;
> -    gchar *asl;            /* asl code generated from aml */
> -    gsize asl_len;
> -    gchar *asl_file;
> -    bool tmp_files_retain;   /* do not delete the temp asl/aml */
> -} QEMU_PACKED AcpiSdtTable;
> -
>  typedef struct {
>      const char *machine;
>      const char *variant;
> @@ -53,65 +40,6 @@ typedef struct {
>      int required_struct_types_len;
>  } test_data;
>  
> -#define ACPI_READ_FIELD(field, addr)           \
> -    do {                                       \
> -        switch (sizeof(field)) {               \
> -        case 1:                                \
> -            field = readb(addr);               \
> -            break;                             \
> -        case 2:                                \
> -            field = readw(addr);               \
> -            break;                             \
> -        case 4:                                \
> -            field = readl(addr);               \
> -            break;                             \
> -        case 8:                                \
> -            field = readq(addr);               \
> -            break;                             \
> -        default:                               \
> -            g_assert(false);                   \
> -        }                                      \
> -        addr += sizeof(field);                  \
> -    } while (0);
> -
> -#define ACPI_READ_ARRAY_PTR(arr, length, addr)  \
> -    do {                                        \
> -        int idx;                                \
> -        for (idx = 0; idx < length; ++idx) {    \
> -            ACPI_READ_FIELD(arr[idx], addr);    \
> -        }                                       \
> -    } while (0);
> -
> -#define ACPI_READ_ARRAY(arr, addr)                               \
> -    ACPI_READ_ARRAY_PTR(arr, sizeof(arr)/sizeof(arr[0]), addr)
> -
> -#define ACPI_READ_TABLE_HEADER(table, addr)                      \
> -    do {                                                         \
> -        ACPI_READ_FIELD((table)->signature, addr);               \
> -        ACPI_READ_FIELD((table)->length, addr);                  \
> -        ACPI_READ_FIELD((table)->revision, addr);                \
> -        ACPI_READ_FIELD((table)->checksum, addr);                \
> -        ACPI_READ_ARRAY((table)->oem_id, addr);                  \
> -        ACPI_READ_ARRAY((table)->oem_table_id, addr);            \
> -        ACPI_READ_FIELD((table)->oem_revision, addr);            \
> -        ACPI_READ_ARRAY((table)->asl_compiler_id, addr);         \
> -        ACPI_READ_FIELD((table)->asl_compiler_revision, addr);   \
> -    } while (0);
> -
> -#define ACPI_ASSERT_CMP(actual, expected) do { \
> -    uint32_t ACPI_ASSERT_CMP_le = cpu_to_le32(actual); \
> -    char ACPI_ASSERT_CMP_str[5] = {}; \
> -    memcpy(ACPI_ASSERT_CMP_str, &ACPI_ASSERT_CMP_le, 4); \
> -    g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
> -} while (0)
> -
> -#define ACPI_ASSERT_CMP64(actual, expected) do { \
> -    uint64_t ACPI_ASSERT_CMP_le = cpu_to_le64(actual); \
> -    char ACPI_ASSERT_CMP_str[9] = {}; \
> -    memcpy(ACPI_ASSERT_CMP_str, &ACPI_ASSERT_CMP_le, 8); \
> -    g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
> -} while (0)
> -
>  static char disk[] = "tests/acpi-test-disk-XXXXXX";
>  static const char *data_dir = "tests/acpi-test-data";
>  #ifdef CONFIG_IASL
> @@ -147,36 +75,9 @@ static void free_test_data(test_data *data)
>      g_array_free(data->tables, false);
>  }
>  
> -static uint8_t acpi_checksum(const uint8_t *data, int len)
> -{
> -    int i;
> -    uint8_t sum = 0;
> -
> -    for (i = 0; i < len; i++) {
> -        sum += data[i];
> -    }
> -
> -    return sum;
> -}
> -
>  static void test_acpi_rsdp_address(test_data *data)
>  {
> -    uint32_t off;
> -
> -    /* OK, now find RSDP */
> -    for (off = 0xf0000; off < 0x100000; off += 0x10) {
> -        uint8_t sig[] = "RSD PTR ";
> -        int i;
> -
> -        for (i = 0; i < sizeof sig - 1; ++i) {
> -            sig[i] = readb(off + i);
> -        }
> -
> -        if (!memcmp(sig, "RSD PTR ", sizeof sig)) {
> -            break;
> -        }
> -    }
> -
> +    uint32_t off = acpi_find_rsdp_address();
>      g_assert_cmphex(off, <, 0x100000);
>      data->rsdp_addr = off;
>  }
> @@ -186,17 +87,10 @@ static void test_acpi_rsdp_table(test_data *data)
>      AcpiRsdpDescriptor *rsdp_table = &data->rsdp_table;
>      uint32_t addr = data->rsdp_addr;
>  
> -    ACPI_READ_FIELD(rsdp_table->signature, addr);
> -    ACPI_ASSERT_CMP64(rsdp_table->signature, "RSD PTR ");
> -
> -    ACPI_READ_FIELD(rsdp_table->checksum, addr);
> -    ACPI_READ_ARRAY(rsdp_table->oem_id, addr);
> -    ACPI_READ_FIELD(rsdp_table->revision, addr);
> -    ACPI_READ_FIELD(rsdp_table->rsdt_physical_address, addr);
> -    ACPI_READ_FIELD(rsdp_table->length, addr);
> +    acpi_parse_rsdp_table(addr, rsdp_table);
>  
>      /* rsdp checksum is not for the whole table, but for the first 20 bytes */
> -    g_assert(!acpi_checksum((uint8_t *)rsdp_table, 20));
> +    g_assert(!acpi_calc_checksum((uint8_t *)rsdp_table, 20));
>  }
>  
>  static void test_acpi_rsdt_table(test_data *data)
> @@ -220,8 +114,9 @@ static void test_acpi_rsdt_table(test_data *data)
>      tables = g_new0(uint32_t, tables_nr);
>      ACPI_READ_ARRAY_PTR(tables, tables_nr, addr);
>  
> -    checksum = acpi_checksum((uint8_t *)rsdt_table, rsdt_table->length) +
> -               acpi_checksum((uint8_t *)tables, tables_nr * sizeof(uint32_t));
> +    checksum = acpi_calc_checksum((uint8_t *)rsdt_table, rsdt_table->length) +
> +               acpi_calc_checksum((uint8_t *)tables,
> +                                  tables_nr * sizeof(uint32_t));
>      g_assert(!checksum);
>  
>     /* SSDT tables after FADT */
> @@ -279,7 +174,7 @@ static void test_acpi_fadt_table(test_data *data)
>      ACPI_READ_FIELD(fadt_table->flags, addr);
>  
>      ACPI_ASSERT_CMP(fadt_table->signature, "FACP");
> -    g_assert(!acpi_checksum((uint8_t *)fadt_table, fadt_table->length));
> +    g_assert(!acpi_calc_checksum((uint8_t *)fadt_table, fadt_table->length));
>  }
>  
>  static void test_acpi_facs_table(test_data *data)
> @@ -308,8 +203,10 @@ static void test_dst_table(AcpiSdtTable *sdt_table, uint32_t addr)
>      sdt_table->aml = g_malloc0(sdt_table->aml_len);
>      ACPI_READ_ARRAY_PTR(sdt_table->aml, sdt_table->aml_len, addr);
>  
> -    checksum = acpi_checksum((uint8_t *)sdt_table, sizeof(AcpiTableHeader)) +
> -               acpi_checksum((uint8_t *)sdt_table->aml, sdt_table->aml_len);
> +    checksum = acpi_calc_checksum((uint8_t *)sdt_table,
> +                                  sizeof(AcpiTableHeader)) +
> +               acpi_calc_checksum((uint8_t *)sdt_table->aml,
> +                                  sdt_table->aml_len);
>      g_assert(!checksum);
>  }
>  
> @@ -608,8 +505,9 @@ static bool smbios_ep_table_ok(test_data *data)
>          return false;
>      }
>      ACPI_READ_FIELD(ep_table->smbios_bcd_revision, addr);
> -    if (acpi_checksum((uint8_t *)ep_table, sizeof *ep_table) ||
> -        acpi_checksum((uint8_t *)ep_table + 0x10, sizeof *ep_table - 0x10)) {
> +    if (acpi_calc_checksum((uint8_t *)ep_table, sizeof *ep_table) ||
> +        acpi_calc_checksum((uint8_t *)ep_table + 0x10,
> +                           sizeof *ep_table - 0x10)) {
>          return false;
>      }
>      return true;

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 8/8] MAINTAINERS: Add VM Generation ID entries
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 8/8] MAINTAINERS: Add VM Generation ID entries ben
@ 2017-02-20 14:50   ` Igor Mammedov
  0 siblings, 0 replies; 53+ messages in thread
From: Igor Mammedov @ 2017-02-20 14:50 UTC (permalink / raw)
  To: ben; +Cc: qemu-devel, lersek, mst

On Thu, 16 Feb 2017 15:15:40 -0800
ben@skyportsystems.com wrote:

> From: Ben Warren <ben@skyportsystems.com>
> 
> Signed-off-by: Ben Warren <ben@skyportsystems.com>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>

> ---
>  MAINTAINERS | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 81d4baf..8f5dd35 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1125,6 +1125,15 @@ F: hw/nvram/chrp_nvram.c
>  F: include/hw/nvram/chrp_nvram.h
>  F: tests/prom-env-test.c
>  
> +VM Generation ID
> +M: Ben Warren <ben@skyportsystems.com>
> +S: Maintained
> +F: hw/acpi/vmgenid.c
> +F: include/hw/acpi/vmgenid.h
> +F: docs/specs/vmgenid.txt
> +F: tests/vmgenid-test.c
> +F: stubs/vmgenid.c
> +
>  Subsystems
>  ----------
>  Audio

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID
  2017-02-16 23:15 [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID ben
                   ` (7 preceding siblings ...)
  2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 8/8] MAINTAINERS: Add VM Generation ID entries ben
@ 2017-02-20 14:57 ` Igor Mammedov
  2017-02-20 15:41   ` Laszlo Ersek
  2017-02-21 12:20   ` Laszlo Ersek
  8 siblings, 2 replies; 53+ messages in thread
From: Igor Mammedov @ 2017-02-20 14:57 UTC (permalink / raw)
  To: ben; +Cc: qemu-devel, lersek, mst, Gerd Hoffmann, Kevin O'Connor

On Thu, 16 Feb 2017 15:15:32 -0800
ben@skyportsystems.com wrote:

> From: Ben Warren <ben@skyportsystems.com>
> 
> This patch set adds support for passing a GUID to Windows guests.  It is a
> re-implementation of previous patch sets written by Igor Mammedov et al, but
> this time passing the GUID data as a fw_cfg blob.
> 
> This patch set has dependencies on new guest functionality, in particular the
> support for a new linker-loader command and the ability to write back data
> to QEMU over a DMA link.  Work is in flight in both SeaBIOS and OVMF to support this.
> 
> v7->v8:
>     - Rebased to top of tree.
>     - Fixed two small bugs in "write pointer" function
>     - minor re-ordering of data in patches
>     - Fixed unit test by adding delays/retries to reading RSDP table
Michael,

series looks good for merging.
Patch
 [PATCH v8 7/8] tests: Add unit tests for the VM  Generation ID feature
needs updated seabios blob to make 'make check' happy
so we probably should merge/update seabios first
  [PATCH v5 0/5] QEMU: Add capability to write back fw_cfg address to QEMU

CCing Gerd and Kevin.

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-20 12:32               ` Dr. David Alan Gilbert
@ 2017-02-20 15:35                 ` Laszlo Ersek
  0 siblings, 0 replies; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-20 15:35 UTC (permalink / raw)
  To: Dr. David Alan Gilbert; +Cc: Igor Mammedov, ben, qemu-devel, mst

So Igor has now confirmed he's fine with v8 (thanks!), but I still
wanted to respond here:

On 02/20/17 13:32, Dr. David Alan Gilbert wrote:
> * Laszlo Ersek (lersek@redhat.com) wrote:
>> On 02/20/17 12:00, Dr. David Alan Gilbert wrote:
>>> * Laszlo Ersek (lersek@redhat.com) wrote:
>>>> On 02/20/17 11:23, Dr. David Alan Gilbert wrote:
>>>>> * Laszlo Ersek (lersek@redhat.com) wrote:
>>>>>> CC Dave
>>>>>
>>>>> This isn't an area I really understand; but if I'm
>>>>> reading this right then 
>>>>>    vmgenid is stored in fw_cfg?
>>>>>    fw_cfg isn't migrated
>>>>>
>>>>> So why should any changes to it get migrated, except if it's already
>>>>> been read by the guest (and if the guest reads it again aftwards what's
>>>>> it expected to read?)
>>>>
>>>> This is what we have here:
>>>> - QEMU formats read-only fw_cfg blob with GUID
>>>> - guest downloads blob, places it in guest RAM
>>>> - guest tells QEMU the guest-side address of the blob
>>>> - during migration, guest RAM is transferred
>>>> - after migration, in the device's post_load callback, QEMU overwrites
>>>>   the GUID in guest RAM with a different value, and injects an SCI
>>>>
>>>> I CC'd you for the following reason: Igor reported that he didn't see
>>>> either the fresh GUID or the SCI in the guest, on the target host, after
>>>> migration. I figured that perhaps there was an ordering issue between
>>>> RAM loading and post_load execution on the target host, and so I
>>>> proposed to delay the RAM overwrite + SCI injection a bit more;
>>>> following the pattern seen in your commit 90c647db8d59.
>>>>
>>>> However, since then, both Ben and myself tested the code with migration
>>>> (using "virsh save" (Ben) and "virsh managedsave" (myself)), with
>>>> Windows and Linux guests, and it works for us; there seems to be no
>>>> ordering issue with the current code (= overwrite RAM + inject SCI in
>>>> the post_load callback()).
>>>>
>>>> For now we don't understand why it doesn't work for Igor (Igor used
>>>> exec/gzip migration to/from a local file using direct QEMU monitor
>>>> commands / options, no libvirt). And, copying the pattern seen in your
>>>> commit 90c647db8d59 didn't help in his case (while it wasn't even
>>>> necessary for success in Ben's and my testing).
>>>
>>> One thing I noticed in Igor's test was that he did a 'stop' on the source
>>> before the migate, and so it's probably still paused on the destination
>>> after the migration is loaded, so anything the guest needs to do might
>>> not have happened until it's started.
>>
>> Interesting! I hope Igor can double-check this!
>>
>> In the virsh docs, before doing my tests, I read that "managedsave"
>> optionally took --running or --paused:
>>
>>     Normally, starting a managed save will decide between running or
>>     paused based on the state the domain was in when the save was done;
>>     passing either the --running or --paused flag will allow overriding
>>     which state the start should use.
>>
>> I didn't pass any such flag ultimately, and I didn't stop the guests
>> before the managedsave. Indeed they continued execution right after
>> being loaded with "virsh start".
>>
>> (Side point: managedsave is awesome. :) )
> 
> If I've followed the bread crumbs correctly, I think managedsave
> is just using a migrate to fd anyway, so the same code.

Yes, I agree.

My enthusiasm for "managedsave" is due to "virsh start"'s awareness as
to whether it should boot the guest from zero, or in-migrate it from the
"managed" saved state.

Plain "save" is much more risky for the admin to mess up (because it
needs specialized guest startup too).

Of course, I also find QEMU's migration feature awesome in the first
place. :)

> 
>>>
>>> You say;
>>>    'guest tells QEMU the guest-side address of the blob'
>>> how is that stored/migrated/etc ?
>>
>> It is a uint8_t[8] array (little endian representation), linked into
>> another (writeable) fw_cfg entry, and it's migrated explicitly (it has a
>> descriptor in the device's vmstate descriptor). The post_load callback
>> relies on this array being restored before the migration infrastructure
>> calls post_load.
> 
> RAM normally comes back before other devices, so you should be OK;
> although we frequently have problems with devices reading from RAM
> during device init before migration has started, or writing to it
> after migration has finished on the source.

Thanks; we should be fine then. (We only write to RAM in post_load.)

Laszlo

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID
  2017-02-20 14:57 ` [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID Igor Mammedov
@ 2017-02-20 15:41   ` Laszlo Ersek
  2017-02-20 15:45     ` Kevin O'Connor
  2017-02-20 18:10     ` Ben Warren
  2017-02-21 12:20   ` Laszlo Ersek
  1 sibling, 2 replies; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-20 15:41 UTC (permalink / raw)
  To: Igor Mammedov, ben, Gerd Hoffmann, Kevin O'Connor; +Cc: qemu-devel, mst

On 02/20/17 15:57, Igor Mammedov wrote:
> On Thu, 16 Feb 2017 15:15:32 -0800
> ben@skyportsystems.com wrote:
> 
>> From: Ben Warren <ben@skyportsystems.com>
>>
>> This patch set adds support for passing a GUID to Windows guests.  It is a
>> re-implementation of previous patch sets written by Igor Mammedov et al, but
>> this time passing the GUID data as a fw_cfg blob.
>>
>> This patch set has dependencies on new guest functionality, in particular the
>> support for a new linker-loader command and the ability to write back data
>> to QEMU over a DMA link.  Work is in flight in both SeaBIOS and OVMF to support this.
>>
>> v7->v8:
>>     - Rebased to top of tree.
>>     - Fixed two small bugs in "write pointer" function
>>     - minor re-ordering of data in patches
>>     - Fixed unit test by adding delays/retries to reading RSDP table
> Michael,
> 
> series looks good for merging.
> Patch
>  [PATCH v8 7/8] tests: Add unit tests for the VM  Generation ID feature
> needs updated seabios blob to make 'make check' happy
> so we probably should merge/update seabios first
>   [PATCH v5 0/5] QEMU: Add capability to write back fw_cfg address to QEMU
> 
> CCing Gerd and Kevin.
> 

That's sort of a circular dependency, as Kevin generally prefers to
merge SeaBIOS patches once the underlying QEMU code has been committed :)

For a total ordering, all QEMU patches except v8 7/8 could be merged in
QEMU, then the v5 SeaBIOS patches could be merged, then Gerd could
refresh the bundled SeaBIOS binaries, then QEMU patch v8 7/8 could be
merged.

I'm not actually suggesting that though, given that the soft freeze is
in about a week.

Kevin, can you please make an exception this time and merge the SeaBIOS
patches ahead of the QEMU patches?

Thanks!
Laszlo

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID
  2017-02-20 15:41   ` Laszlo Ersek
@ 2017-02-20 15:45     ` Kevin O'Connor
  2017-02-20 16:00       ` Laszlo Ersek
  2017-02-21  7:10       ` Gerd Hoffmann
  2017-02-20 18:10     ` Ben Warren
  1 sibling, 2 replies; 53+ messages in thread
From: Kevin O'Connor @ 2017-02-20 15:45 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: Igor Mammedov, ben, Gerd Hoffmann, qemu-devel, mst

On Mon, Feb 20, 2017 at 04:41:38PM +0100, Laszlo Ersek wrote:
> On 02/20/17 15:57, Igor Mammedov wrote:
> > On Thu, 16 Feb 2017 15:15:32 -0800
> > ben@skyportsystems.com wrote:
> > 
> >> From: Ben Warren <ben@skyportsystems.com>
> >>
> >> This patch set adds support for passing a GUID to Windows guests.  It is a
> >> re-implementation of previous patch sets written by Igor Mammedov et al, but
> >> this time passing the GUID data as a fw_cfg blob.
> >>
> >> This patch set has dependencies on new guest functionality, in particular the
> >> support for a new linker-loader command and the ability to write back data
> >> to QEMU over a DMA link.  Work is in flight in both SeaBIOS and OVMF to support this.
> >>
> >> v7->v8:
> >>     - Rebased to top of tree.
> >>     - Fixed two small bugs in "write pointer" function
> >>     - minor re-ordering of data in patches
> >>     - Fixed unit test by adding delays/retries to reading RSDP table
> > Michael,
> > 
> > series looks good for merging.
> > Patch
> >  [PATCH v8 7/8] tests: Add unit tests for the VM  Generation ID feature
> > needs updated seabios blob to make 'make check' happy
> > so we probably should merge/update seabios first
> >   [PATCH v5 0/5] QEMU: Add capability to write back fw_cfg address to QEMU
> > 
> > CCing Gerd and Kevin.
> > 
> 
> That's sort of a circular dependency, as Kevin generally prefers to
> merge SeaBIOS patches once the underlying QEMU code has been committed :)
> 
> For a total ordering, all QEMU patches except v8 7/8 could be merged in
> QEMU, then the v5 SeaBIOS patches could be merged, then Gerd could
> refresh the bundled SeaBIOS binaries, then QEMU patch v8 7/8 could be
> merged.
> 
> I'm not actually suggesting that though, given that the soft freeze is
> in about a week.
> 
> Kevin, can you please make an exception this time and merge the SeaBIOS
> patches ahead of the QEMU patches?

Yes.

Gerd - are you planning to backport this series to the stable branch?

-Kevin

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID
  2017-02-20 15:45     ` Kevin O'Connor
@ 2017-02-20 16:00       ` Laszlo Ersek
  2017-02-21  7:10       ` Gerd Hoffmann
  1 sibling, 0 replies; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-20 16:00 UTC (permalink / raw)
  To: Kevin O'Connor, Igor Mammedov, ben, mst
  Cc: Gerd Hoffmann, qemu-devel, Stefan Hajnoczi

On 02/20/17 16:45, Kevin O'Connor wrote:
> On Mon, Feb 20, 2017 at 04:41:38PM +0100, Laszlo Ersek wrote:
>> On 02/20/17 15:57, Igor Mammedov wrote:
>>> On Thu, 16 Feb 2017 15:15:32 -0800
>>> ben@skyportsystems.com wrote:
>>>
>>>> From: Ben Warren <ben@skyportsystems.com>
>>>>
>>>> This patch set adds support for passing a GUID to Windows guests.  It is a
>>>> re-implementation of previous patch sets written by Igor Mammedov et al, but
>>>> this time passing the GUID data as a fw_cfg blob.
>>>>
>>>> This patch set has dependencies on new guest functionality, in particular the
>>>> support for a new linker-loader command and the ability to write back data
>>>> to QEMU over a DMA link.  Work is in flight in both SeaBIOS and OVMF to support this.
>>>>
>>>> v7->v8:
>>>>     - Rebased to top of tree.
>>>>     - Fixed two small bugs in "write pointer" function
>>>>     - minor re-ordering of data in patches
>>>>     - Fixed unit test by adding delays/retries to reading RSDP table
>>> Michael,
>>>
>>> series looks good for merging.
>>> Patch
>>>  [PATCH v8 7/8] tests: Add unit tests for the VM  Generation ID feature
>>> needs updated seabios blob to make 'make check' happy
>>> so we probably should merge/update seabios first
>>>   [PATCH v5 0/5] QEMU: Add capability to write back fw_cfg address to QEMU
>>>
>>> CCing Gerd and Kevin.
>>>
>>
>> That's sort of a circular dependency, as Kevin generally prefers to
>> merge SeaBIOS patches once the underlying QEMU code has been committed :)
>>
>> For a total ordering, all QEMU patches except v8 7/8 could be merged in
>> QEMU, then the v5 SeaBIOS patches could be merged, then Gerd could
>> refresh the bundled SeaBIOS binaries, then QEMU patch v8 7/8 could be
>> merged.
>>
>> I'm not actually suggesting that though, given that the soft freeze is
>> in about a week.
>>
>> Kevin, can you please make an exception this time and merge the SeaBIOS
>> patches ahead of the QEMU patches?
> 
> Yes.

Thank you!

Ben, Igor or Michael -- can one of you please add a paragraph on VMGENID
to <http://wiki.qemu-project.org/ChangeLog/2.9>, later on?

(Ben, if you don't have an account yet, I think Stefan (CC'd) can give
you one.)

Thanks!
Laszlo

> 
> Gerd - are you planning to backport this series to the stable branch?
> 
> -Kevin
> 

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID
  2017-02-20 15:41   ` Laszlo Ersek
  2017-02-20 15:45     ` Kevin O'Connor
@ 2017-02-20 18:10     ` Ben Warren
  1 sibling, 0 replies; 53+ messages in thread
From: Ben Warren @ 2017-02-20 18:10 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Igor Mammedov, Gerd Hoffmann, Kevin O'Connor, qemu-devel, mst

[-- Attachment #1: Type: text/plain, Size: 2061 bytes --]


> On Feb 20, 2017, at 7:41 AM, Laszlo Ersek <lersek@redhat.com> wrote:
> 
> On 02/20/17 15:57, Igor Mammedov wrote:
>> On Thu, 16 Feb 2017 15:15:32 -0800
>> ben@skyportsystems.com wrote:
>> 
>>> From: Ben Warren <ben@skyportsystems.com>
>>> 
>>> This patch set adds support for passing a GUID to Windows guests.  It is a
>>> re-implementation of previous patch sets written by Igor Mammedov et al, but
>>> this time passing the GUID data as a fw_cfg blob.
>>> 
>>> This patch set has dependencies on new guest functionality, in particular the
>>> support for a new linker-loader command and the ability to write back data
>>> to QEMU over a DMA link.  Work is in flight in both SeaBIOS and OVMF to support this.
>>> 
>>> v7->v8:
>>>    - Rebased to top of tree.
>>>    - Fixed two small bugs in "write pointer" function
>>>    - minor re-ordering of data in patches
>>>    - Fixed unit test by adding delays/retries to reading RSDP table
>> Michael,
>> 
>> series looks good for merging.
>> Patch
>> [PATCH v8 7/8] tests: Add unit tests for the VM  Generation ID feature
>> needs updated seabios blob to make 'make check' happy
>> so we probably should merge/update seabios first
>>  [PATCH v5 0/5] QEMU: Add capability to write back fw_cfg address to QEMU
>> 
>> CCing Gerd and Kevin.
>> 
> 
> That's sort of a circular dependency, as Kevin generally prefers to
> merge SeaBIOS patches once the underlying QEMU code has been committed :)
> 
> For a total ordering, all QEMU patches except v8 7/8 could be merged in
> QEMU, then the v5 SeaBIOS patches could be merged, then Gerd could
> refresh the bundled SeaBIOS binaries, then QEMU patch v8 7/8 could be
> merged.
> 
> I'm not actually suggesting that though, given that the soft freeze is
> in about a week.
> 
> Kevin, can you please make an exception this time and merge the SeaBIOS
> patches ahead of the QEMU patches?
> 
There were some change requests for v5 SeaBIOS, so I’m planning on fixing them up and sending today.
> Thanks!
> Laszlo

—Ben

[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 3583 bytes --]

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-20 10:23       ` Dr. David Alan Gilbert
  2017-02-20 10:40         ` Laszlo Ersek
@ 2017-02-20 20:00         ` Eric Blake
  2017-02-20 20:19           ` Dr. David Alan Gilbert
  1 sibling, 1 reply; 53+ messages in thread
From: Eric Blake @ 2017-02-20 20:00 UTC (permalink / raw)
  To: Dr. David Alan Gilbert, Laszlo Ersek; +Cc: Igor Mammedov, qemu-devel, ben, mst

[-- Attachment #1: Type: text/plain, Size: 1275 bytes --]

On 02/20/2017 04:23 AM, Dr. David Alan Gilbert wrote:
> * Laszlo Ersek (lersek@redhat.com) wrote:
>> CC Dave
> 
> This isn't an area I really understand; but if I'm
> reading this right then 
>    vmgenid is stored in fw_cfg?
>    fw_cfg isn't migrated
> 
> So why should any changes to it get migrated, except if it's already
> been read by the guest (and if the guest reads it again aftwards what's
> it expected to read?)

Why are we expecting it to change on migration?  You want a new value
when you load state from disk (you don't know how many times the same
state has been loaded previously, so each load is effectively forking
the VM and you want a different value), but for a single live migration,
you aren't forking the VM and don't need a new generation ID.

I guess it all boils down to what command line you're using: if libvirt
is driving a live migration, it will request the same UUID in the
command line of the destination as what is on the source; while if
libvirt is loading from a [managed]save to restore state from a file, it
will either request a new UUID directly or request auto to let qemu
generate the new id.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-20 20:00         ` Eric Blake
@ 2017-02-20 20:19           ` Dr. David Alan Gilbert
  2017-02-20 20:45             ` Eric Blake
  2017-02-20 20:49             ` Laszlo Ersek
  0 siblings, 2 replies; 53+ messages in thread
From: Dr. David Alan Gilbert @ 2017-02-20 20:19 UTC (permalink / raw)
  To: Eric Blake; +Cc: Laszlo Ersek, Igor Mammedov, qemu-devel, ben, mst

* Eric Blake (eblake@redhat.com) wrote:
> On 02/20/2017 04:23 AM, Dr. David Alan Gilbert wrote:
> > * Laszlo Ersek (lersek@redhat.com) wrote:
> >> CC Dave
> > 
> > This isn't an area I really understand; but if I'm
> > reading this right then 
> >    vmgenid is stored in fw_cfg?
> >    fw_cfg isn't migrated
> > 
> > So why should any changes to it get migrated, except if it's already
> > been read by the guest (and if the guest reads it again aftwards what's
> > it expected to read?)
> 
> Why are we expecting it to change on migration?  You want a new value

I'm not; I was asking why a change made prior to migration would be
preserved across migration.


> when you load state from disk (you don't know how many times the same
> state has been loaded previously, so each load is effectively forking
> the VM and you want a different value), but for a single live migration,
> you aren't forking the VM and don't need a new generation ID.
> 
> I guess it all boils down to what command line you're using: if libvirt
> is driving a live migration, it will request the same UUID in the
> command line of the destination as what is on the source; while if
> libvirt is loading from a [managed]save to restore state from a file, it
> will either request a new UUID directly or request auto to let qemu
> generate the new id.

Hmm now I've lost it a bit; I thought we would preserve the value
transmitted from the source, not the value on the command line of the destination.

Dave

> 
> -- 
> Eric Blake   eblake redhat com    +1-919-301-3266
> Libvirt virtualization library http://libvirt.org
> 



--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-20 20:19           ` Dr. David Alan Gilbert
@ 2017-02-20 20:45             ` Eric Blake
  2017-02-20 20:55               ` Laszlo Ersek
  2017-02-20 20:49             ` Laszlo Ersek
  1 sibling, 1 reply; 53+ messages in thread
From: Eric Blake @ 2017-02-20 20:45 UTC (permalink / raw)
  To: Dr. David Alan Gilbert; +Cc: Laszlo Ersek, Igor Mammedov, qemu-devel, ben, mst

[-- Attachment #1: Type: text/plain, Size: 2250 bytes --]

On 02/20/2017 02:19 PM, Dr. David Alan Gilbert wrote:
> * Eric Blake (eblake@redhat.com) wrote:
>> On 02/20/2017 04:23 AM, Dr. David Alan Gilbert wrote:
>>> * Laszlo Ersek (lersek@redhat.com) wrote:
>>>> CC Dave
>>>
>>> This isn't an area I really understand; but if I'm
>>> reading this right then 
>>>    vmgenid is stored in fw_cfg?
>>>    fw_cfg isn't migrated
>>>
>>> So why should any changes to it get migrated, except if it's already
>>> been read by the guest (and if the guest reads it again aftwards what's
>>> it expected to read?)
>>
>> Why are we expecting it to change on migration?  You want a new value
> 
> I'm not; I was asking why a change made prior to migration would be
> preserved across migration.

Okay, so you're asking what happens if the source requests the vmgenid
device, and sets an id, but the destination of the migration does not
request anything - how does the guest on the destination see the same id
as was in place on the source at the time migration started.

> 
> 
>> when you load state from disk (you don't know how many times the same
>> state has been loaded previously, so each load is effectively forking
>> the VM and you want a different value), but for a single live migration,
>> you aren't forking the VM and don't need a new generation ID.
>>
>> I guess it all boils down to what command line you're using: if libvirt
>> is driving a live migration, it will request the same UUID in the
>> command line of the destination as what is on the source; while if
>> libvirt is loading from a [managed]save to restore state from a file, it
>> will either request a new UUID directly or request auto to let qemu
>> generate the new id.
> 
> Hmm now I've lost it a bit; I thought we would preserve the value
> transmitted from the source, not the value on the command line of the destination.

I guess I'm trying to figure out whether libvirt MUST read the current
id and explicitly tell the destination of migration to reuse that id, or
if libvirt can omit the id on migration and everything just works
because the id was migrated from the source.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-20 20:19           ` Dr. David Alan Gilbert
  2017-02-20 20:45             ` Eric Blake
@ 2017-02-20 20:49             ` Laszlo Ersek
  1 sibling, 0 replies; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-20 20:49 UTC (permalink / raw)
  To: Dr. David Alan Gilbert, Eric Blake; +Cc: Igor Mammedov, qemu-devel, ben, mst

On 02/20/17 21:19, Dr. David Alan Gilbert wrote:
> * Eric Blake (eblake@redhat.com) wrote:
>> On 02/20/2017 04:23 AM, Dr. David Alan Gilbert wrote:
>>> * Laszlo Ersek (lersek@redhat.com) wrote:
>>>> CC Dave
>>>
>>> This isn't an area I really understand; but if I'm
>>> reading this right then 
>>>    vmgenid is stored in fw_cfg?
>>>    fw_cfg isn't migrated
>>>
>>> So why should any changes to it get migrated, except if it's already
>>> been read by the guest (and if the guest reads it again aftwards what's
>>> it expected to read?)
>>
>> Why are we expecting it to change on migration?  You want a new value
> 
> I'm not; I was asking why a change made prior to migration would be
> preserved across migration.
> 
> 
>> when you load state from disk (you don't know how many times the same
>> state has been loaded previously, so each load is effectively forking
>> the VM and you want a different value), but for a single live migration,
>> you aren't forking the VM and don't need a new generation ID.
>>
>> I guess it all boils down to what command line you're using: if libvirt
>> is driving a live migration, it will request the same UUID in the
>> command line of the destination as what is on the source; while if
>> libvirt is loading from a [managed]save to restore state from a file, it
>> will either request a new UUID directly or request auto to let qemu
>> generate the new id.
> 
> Hmm now I've lost it a bit; I thought we would preserve the value
> transmitted from the source, not the value on the command line of the destination.

The are two relevant pieces of data here.

(a) the GUID in guest RAM
(b) the guest-phys address of the GUID, written back by the guest fw to
a guest-writeable fw_cfg file, to be dereferenced by QEMU, for updating
the GUID in guest RAM

For both live migration and restoring saved state from disk, (b) doesn't
change. It is also not exposed on the QEMU command line. (It is
configured by the guest firmware during initial boot.)

(a) is taken from the QEMU command line. It can be "auto" (and then QEMU
generates a random GUID), or a specific GUID string. This GUID is always
written to guest RAM (assuming (b) has been configured) in the vmgenid
device's post_load callback. However, whether the new GUID should be
different from the one already present in guest RAM is a separate question.

- For restoring state from disk, a different GUID (either generated by
libvirt, or by QEMU due to "auto") makes sense.

- For live migration, it makes sense for libvirt to pass in the same
GUID on the target host as was used on the source host. The guest RAM
update, and the ACPI interrupt (SCI), will occur on the target host, but
the GUID won't change effectively. (The VMGENID spec explicitly permits
spurious notifications, i.e., an SCI with no change to the GUID in RAM.)

Thanks
Laszlo

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-20 20:45             ` Eric Blake
@ 2017-02-20 20:55               ` Laszlo Ersek
  2017-02-21  1:43                 ` Michael S. Tsirkin
  0 siblings, 1 reply; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-20 20:55 UTC (permalink / raw)
  To: Eric Blake, Dr. David Alan Gilbert; +Cc: Igor Mammedov, qemu-devel, ben, mst

On 02/20/17 21:45, Eric Blake wrote:
> On 02/20/2017 02:19 PM, Dr. David Alan Gilbert wrote:
>> * Eric Blake (eblake@redhat.com) wrote:
>>> On 02/20/2017 04:23 AM, Dr. David Alan Gilbert wrote:
>>>> * Laszlo Ersek (lersek@redhat.com) wrote:
>>>>> CC Dave
>>>>
>>>> This isn't an area I really understand; but if I'm
>>>> reading this right then 
>>>>    vmgenid is stored in fw_cfg?
>>>>    fw_cfg isn't migrated
>>>>
>>>> So why should any changes to it get migrated, except if it's already
>>>> been read by the guest (and if the guest reads it again aftwards what's
>>>> it expected to read?)
>>>
>>> Why are we expecting it to change on migration?  You want a new value
>>
>> I'm not; I was asking why a change made prior to migration would be
>> preserved across migration.
> 
> Okay, so you're asking what happens if the source requests the vmgenid
> device, and sets an id, but the destination of the migration does not
> request anything

This should never happen, as it means different QEMU command lines on
source vs. target hosts. (Different as in "incorrectly different".)

Dave writes, "a change made prior to migration". Change made to what?

- the GUID cannot be changed via the monitor once QEMU has been started.
We dropped the monitor command for that, due to lack of a good use case,
and due to lifecycle complexities. We have figured out a way to make it
safe, but until there's a really convincing use case, we shouldn't add
that complexity.

- the address of the GUID is changed (the firmware programs it from
"zero" to an actual address, in a writeable fw_cfg file), and that piece
of info is explicitly migrated, as part of the vmgenid device's vmsd.

Thanks
Laszlo


> - how does the guest on the destination see the same id
> as was in place on the source at the time migration started.
> 
>>
>>
>>> when you load state from disk (you don't know how many times the same
>>> state has been loaded previously, so each load is effectively forking
>>> the VM and you want a different value), but for a single live migration,
>>> you aren't forking the VM and don't need a new generation ID.
>>>
>>> I guess it all boils down to what command line you're using: if libvirt
>>> is driving a live migration, it will request the same UUID in the
>>> command line of the destination as what is on the source; while if
>>> libvirt is loading from a [managed]save to restore state from a file, it
>>> will either request a new UUID directly or request auto to let qemu
>>> generate the new id.
>>
>> Hmm now I've lost it a bit; I thought we would preserve the value
>> transmitted from the source, not the value on the command line of the destination.
> 
> I guess I'm trying to figure out whether libvirt MUST read the current
> id and explicitly tell the destination of migration to reuse that id, or
> if libvirt can omit the id on migration and everything just works
> because the id was migrated from the source.
> 

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-20 20:55               ` Laszlo Ersek
@ 2017-02-21  1:43                 ` Michael S. Tsirkin
  2017-02-21  9:58                   ` Laszlo Ersek
  0 siblings, 1 reply; 53+ messages in thread
From: Michael S. Tsirkin @ 2017-02-21  1:43 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Eric Blake, Dr. David Alan Gilbert, Igor Mammedov, qemu-devel, ben

On Mon, Feb 20, 2017 at 09:55:40PM +0100, Laszlo Ersek wrote:
> On 02/20/17 21:45, Eric Blake wrote:
> > On 02/20/2017 02:19 PM, Dr. David Alan Gilbert wrote:
> >> * Eric Blake (eblake@redhat.com) wrote:
> >>> On 02/20/2017 04:23 AM, Dr. David Alan Gilbert wrote:
> >>>> * Laszlo Ersek (lersek@redhat.com) wrote:
> >>>>> CC Dave
> >>>>
> >>>> This isn't an area I really understand; but if I'm
> >>>> reading this right then 
> >>>>    vmgenid is stored in fw_cfg?
> >>>>    fw_cfg isn't migrated
> >>>>
> >>>> So why should any changes to it get migrated, except if it's already
> >>>> been read by the guest (and if the guest reads it again aftwards what's
> >>>> it expected to read?)
> >>>
> >>> Why are we expecting it to change on migration?  You want a new value
> >>
> >> I'm not; I was asking why a change made prior to migration would be
> >> preserved across migration.
> > 
> > Okay, so you're asking what happens if the source requests the vmgenid
> > device, and sets an id, but the destination of the migration does not
> > request anything
> 
> This should never happen, as it means different QEMU command lines on
> source vs. target hosts. (Different as in "incorrectly different".)
> 
> Dave writes, "a change made prior to migration". Change made to what?
> 
> - the GUID cannot be changed via the monitor once QEMU has been started.
> We dropped the monitor command for that, due to lack of a good use case,
> and due to lifecycle complexities. We have figured out a way to make it
> safe, but until there's a really convincing use case, we shouldn't add
> that complexity.

True but we might in the future, and it seems prudent to make
migration stream future-proof for that.

> - the address of the GUID is changed (the firmware programs it from
> "zero" to an actual address, in a writeable fw_cfg file), and that piece
> of info is explicitly migrated, as part of the vmgenid device's vmsd.
> 
> Thanks
> Laszlo
> 
> 
> > - how does the guest on the destination see the same id
> > as was in place on the source at the time migration started.
> > 
> >>
> >>
> >>> when you load state from disk (you don't know how many times the same
> >>> state has been loaded previously, so each load is effectively forking
> >>> the VM and you want a different value), but for a single live migration,
> >>> you aren't forking the VM and don't need a new generation ID.
> >>>
> >>> I guess it all boils down to what command line you're using: if libvirt
> >>> is driving a live migration, it will request the same UUID in the
> >>> command line of the destination as what is on the source; while if
> >>> libvirt is loading from a [managed]save to restore state from a file, it
> >>> will either request a new UUID directly or request auto to let qemu
> >>> generate the new id.
> >>
> >> Hmm now I've lost it a bit; I thought we would preserve the value
> >> transmitted from the source, not the value on the command line of the destination.
> > 
> > I guess I'm trying to figure out whether libvirt MUST read the current
> > id and explicitly tell the destination of migration to reuse that id, or
> > if libvirt can omit the id on migration and everything just works
> > because the id was migrated from the source.
> > 

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID
  2017-02-20 15:45     ` Kevin O'Connor
  2017-02-20 16:00       ` Laszlo Ersek
@ 2017-02-21  7:10       ` Gerd Hoffmann
  1 sibling, 0 replies; 53+ messages in thread
From: Gerd Hoffmann @ 2017-02-21  7:10 UTC (permalink / raw)
  To: Kevin O'Connor; +Cc: Laszlo Ersek, Igor Mammedov, ben, qemu-devel, mst

  Hi,

> Gerd - are you planning to backport this series to the stable branch?

Yes.  Unless we'll have a 1.11 release next week, which I doubt ;)

cheers,
  Gerd

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-21  1:43                 ` Michael S. Tsirkin
@ 2017-02-21  9:58                   ` Laszlo Ersek
  2017-02-21 14:14                     ` Michael S. Tsirkin
  0 siblings, 1 reply; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-21  9:58 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Eric Blake, Dr. David Alan Gilbert, Igor Mammedov, qemu-devel, ben

On 02/21/17 02:43, Michael S. Tsirkin wrote:
> On Mon, Feb 20, 2017 at 09:55:40PM +0100, Laszlo Ersek wrote:
>> On 02/20/17 21:45, Eric Blake wrote:
>>> On 02/20/2017 02:19 PM, Dr. David Alan Gilbert wrote:
>>>> * Eric Blake (eblake@redhat.com) wrote:
>>>>> On 02/20/2017 04:23 AM, Dr. David Alan Gilbert wrote:
>>>>>> * Laszlo Ersek (lersek@redhat.com) wrote:
>>>>>>> CC Dave
>>>>>>
>>>>>> This isn't an area I really understand; but if I'm
>>>>>> reading this right then 
>>>>>>    vmgenid is stored in fw_cfg?
>>>>>>    fw_cfg isn't migrated
>>>>>>
>>>>>> So why should any changes to it get migrated, except if it's already
>>>>>> been read by the guest (and if the guest reads it again aftwards what's
>>>>>> it expected to read?)
>>>>>
>>>>> Why are we expecting it to change on migration?  You want a new value
>>>>
>>>> I'm not; I was asking why a change made prior to migration would be
>>>> preserved across migration.
>>>
>>> Okay, so you're asking what happens if the source requests the vmgenid
>>> device, and sets an id, but the destination of the migration does not
>>> request anything
>>
>> This should never happen, as it means different QEMU command lines on
>> source vs. target hosts. (Different as in "incorrectly different".)
>>
>> Dave writes, "a change made prior to migration". Change made to what?
>>
>> - the GUID cannot be changed via the monitor once QEMU has been started.
>> We dropped the monitor command for that, due to lack of a good use case,
>> and due to lifecycle complexities. We have figured out a way to make it
>> safe, but until there's a really convincing use case, we shouldn't add
>> that complexity.
> 
> True but we might in the future, and it seems prudent to make
> migration stream future-proof for that.

It is already.

The monitor command, if we add it, can be implemented incrementally. I
described it as "approach (iii)" elsewhere in the thread. This is a more
detailed recap:

- introduce a new device property (internal only), such as
  "x-enable-set-vmgenid". Make it reflect whether a given machine type
  supports the monitor command.

- change the /etc/vmgenid_guid fw_cfg blob from callback-less to one
  with a selection callback

- add a new boolean latch to the vmgenid device, called
  "guid_blob_selected" or something similar

- the reset handler sets the latch to FALSE
  (NB: the reset handler already sets /etc/vmgenid_addr to zero)

- the select callback for /etc/vmgenid_guid sets the latch to TRUE

- the latch is added to the migration stream as a subsection *if*
  x-enable-set-vmgenid is TRUE

- the set-vmgenid monitor command checks all three of:
  x-enable-set-vmgenid, the latch, and the contents of
  /etc/vmgenid_addr:

  - if x-enable-set-vmgenid is FALSE, the monitor command returns
    QERR_UNSUPPORTED (this is a generic error class, with an
    "unsupported" error message). Otherwise,

  - if the latch is TRUE *and* /etc/vmgenid_addr is zero, then the
    guest firmware has executed (or started executing) ALLOCATE for
    /etc/vmgenid_guid, but it has not executed WRITE_POINTER yet.
    In this case updating the VMGENID from the monitor is unsafe
    (we cannot guarantee informing the guest successfully), so in this
    case the monitor command fails with ERROR_CLASS_DEVICE_NOT_ACTIVE.
    The caller should simply try a bit later. (By which time the
    firmware will likely have programmed /etc/vmgenid_addr.)

    Libvirt can recognize this error specifically, because it is not the
    generic error class. ERROR_CLASS_DEVICE_NOT_ACTIVE stands for
    "EAGAIN", practically, in this case.

  - Otherwise -- meaning latch is FALSE *or* /etc/vmgenid_addr is
    nonzero, that is, the guest has either not run ALLOCATE since
    reset, *or* it has, but it has also run WRITE_POINTER):

    - refresh the GUID within the fw_cfg blob for /etc/vmgenid_guid
      in-place -- the guest will see this whenever it runs ALLOCATE for
      /etc/vmgenid_guid, *AND*

    - if /etc/vmgenid_addr is not zero, then update the guest (that is,
      RAM write + SCI)

Thanks
Laszlo

> 
>> - the address of the GUID is changed (the firmware programs it from
>> "zero" to an actual address, in a writeable fw_cfg file), and that piece
>> of info is explicitly migrated, as part of the vmgenid device's vmsd.
>>
>> Thanks
>> Laszlo
>>
>>
>>> - how does the guest on the destination see the same id
>>> as was in place on the source at the time migration started.
>>>
>>>>
>>>>
>>>>> when you load state from disk (you don't know how many times the same
>>>>> state has been loaded previously, so each load is effectively forking
>>>>> the VM and you want a different value), but for a single live migration,
>>>>> you aren't forking the VM and don't need a new generation ID.
>>>>>
>>>>> I guess it all boils down to what command line you're using: if libvirt
>>>>> is driving a live migration, it will request the same UUID in the
>>>>> command line of the destination as what is on the source; while if
>>>>> libvirt is loading from a [managed]save to restore state from a file, it
>>>>> will either request a new UUID directly or request auto to let qemu
>>>>> generate the new id.
>>>>
>>>> Hmm now I've lost it a bit; I thought we would preserve the value
>>>> transmitted from the source, not the value on the command line of the destination.
>>>
>>> I guess I'm trying to figure out whether libvirt MUST read the current
>>> id and explicitly tell the destination of migration to reuse that id, or
>>> if libvirt can omit the id on migration and everything just works
>>> because the id was migrated from the source.
>>>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID
  2017-02-20 14:57 ` [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID Igor Mammedov
  2017-02-20 15:41   ` Laszlo Ersek
@ 2017-02-21 12:20   ` Laszlo Ersek
  1 sibling, 0 replies; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-21 12:20 UTC (permalink / raw)
  To: Igor Mammedov, ben; +Cc: Gerd Hoffmann, Kevin O'Connor, qemu-devel, mst

On 02/20/17 15:57, Igor Mammedov wrote:
> On Thu, 16 Feb 2017 15:15:32 -0800
> ben@skyportsystems.com wrote:
> 
>> From: Ben Warren <ben@skyportsystems.com>
>>
>> This patch set adds support for passing a GUID to Windows guests.  It is a
>> re-implementation of previous patch sets written by Igor Mammedov et al, but
>> this time passing the GUID data as a fw_cfg blob.
>>
>> This patch set has dependencies on new guest functionality, in particular the
>> support for a new linker-loader command and the ability to write back data
>> to QEMU over a DMA link.  Work is in flight in both SeaBIOS and OVMF to support this.
>>
>> v7->v8:
>>     - Rebased to top of tree.
>>     - Fixed two small bugs in "write pointer" function
>>     - minor re-ordering of data in patches
>>     - Fixed unit test by adding delays/retries to reading RSDP table
> Michael,
> 
> series looks good for merging.

The OVMF patches for WRITE_POINTER are now upstream.

Thanks
Laszlo

> Patch
>  [PATCH v8 7/8] tests: Add unit tests for the VM  Generation ID feature
> needs updated seabios blob to make 'make check' happy
> so we probably should merge/update seabios first
>   [PATCH v5 0/5] QEMU: Add capability to write back fw_cfg address to QEMU
> 
> CCing Gerd and Kevin.
> 

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-21  9:58                   ` Laszlo Ersek
@ 2017-02-21 14:14                     ` Michael S. Tsirkin
  2017-02-21 16:08                       ` Laszlo Ersek
  0 siblings, 1 reply; 53+ messages in thread
From: Michael S. Tsirkin @ 2017-02-21 14:14 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Eric Blake, Dr. David Alan Gilbert, Igor Mammedov, qemu-devel, ben

On Tue, Feb 21, 2017 at 10:58:05AM +0100, Laszlo Ersek wrote:
> On 02/21/17 02:43, Michael S. Tsirkin wrote:
> > On Mon, Feb 20, 2017 at 09:55:40PM +0100, Laszlo Ersek wrote:
> >> On 02/20/17 21:45, Eric Blake wrote:
> >>> On 02/20/2017 02:19 PM, Dr. David Alan Gilbert wrote:
> >>>> * Eric Blake (eblake@redhat.com) wrote:
> >>>>> On 02/20/2017 04:23 AM, Dr. David Alan Gilbert wrote:
> >>>>>> * Laszlo Ersek (lersek@redhat.com) wrote:
> >>>>>>> CC Dave
> >>>>>>
> >>>>>> This isn't an area I really understand; but if I'm
> >>>>>> reading this right then 
> >>>>>>    vmgenid is stored in fw_cfg?
> >>>>>>    fw_cfg isn't migrated
> >>>>>>
> >>>>>> So why should any changes to it get migrated, except if it's already
> >>>>>> been read by the guest (and if the guest reads it again aftwards what's
> >>>>>> it expected to read?)
> >>>>>
> >>>>> Why are we expecting it to change on migration?  You want a new value
> >>>>
> >>>> I'm not; I was asking why a change made prior to migration would be
> >>>> preserved across migration.
> >>>
> >>> Okay, so you're asking what happens if the source requests the vmgenid
> >>> device, and sets an id, but the destination of the migration does not
> >>> request anything
> >>
> >> This should never happen, as it means different QEMU command lines on
> >> source vs. target hosts. (Different as in "incorrectly different".)
> >>
> >> Dave writes, "a change made prior to migration". Change made to what?
> >>
> >> - the GUID cannot be changed via the monitor once QEMU has been started.
> >> We dropped the monitor command for that, due to lack of a good use case,
> >> and due to lifecycle complexities. We have figured out a way to make it
> >> safe, but until there's a really convincing use case, we shouldn't add
> >> that complexity.
> > 
> > True but we might in the future, and it seems prudent to make
> > migration stream future-proof for that.
> 
> It is already.
> 
> The monitor command, if we add it, can be implemented incrementally. I
> described it as "approach (iii)" elsewhere in the thread. This is a more
> detailed recap:
> 
> - introduce a new device property (internal only), such as
>   "x-enable-set-vmgenid". Make it reflect whether a given machine type
>   supports the monitor command.

This is the part we can avoid at no real cost just
by making sure the guid is migrated.


> - change the /etc/vmgenid_guid fw_cfg blob from callback-less to one
>   with a selection callback
> 
> - add a new boolean latch to the vmgenid device, called
>   "guid_blob_selected" or something similar
> 
> - the reset handler sets the latch to FALSE
>   (NB: the reset handler already sets /etc/vmgenid_addr to zero)
> 
> - the select callback for /etc/vmgenid_guid sets the latch to TRUE
> 
> - the latch is added to the migration stream as a subsection *if*
>   x-enable-set-vmgenid is TRUE
> 
> - the set-vmgenid monitor command checks all three of:
>   x-enable-set-vmgenid, the latch, and the contents of
>   /etc/vmgenid_addr:
> 
>   - if x-enable-set-vmgenid is FALSE, the monitor command returns
>     QERR_UNSUPPORTED (this is a generic error class, with an
>     "unsupported" error message). Otherwise,
> 
>   - if the latch is TRUE *and* /etc/vmgenid_addr is zero, then the
>     guest firmware has executed (or started executing) ALLOCATE for
>     /etc/vmgenid_guid, but it has not executed WRITE_POINTER yet.
>     In this case updating the VMGENID from the monitor is unsafe
>     (we cannot guarantee informing the guest successfully), so in this
>     case the monitor command fails with ERROR_CLASS_DEVICE_NOT_ACTIVE.
>     The caller should simply try a bit later. (By which time the
>     firmware will likely have programmed /etc/vmgenid_addr.)

This makes no sense to me. Just update it in qemu memory
and write when guest asks for it.


>     Libvirt can recognize this error specifically, because it is not the
>     generic error class. ERROR_CLASS_DEVICE_NOT_ACTIVE stands for
>     "EAGAIN", practically, in this case.
> 
>   - Otherwise -- meaning latch is FALSE *or* /etc/vmgenid_addr is
>     nonzero, that is, the guest has either not run ALLOCATE since
>     reset, *or* it has, but it has also run WRITE_POINTER):
> 
>     - refresh the GUID within the fw_cfg blob for /etc/vmgenid_guid
>       in-place -- the guest will see this whenever it runs ALLOCATE for
>       /etc/vmgenid_guid, *AND*
> 
>     - if /etc/vmgenid_addr is not zero, then update the guest (that is,
>       RAM write + SCI)
> 
> Thanks
> Laszlo

Seems way more painful than it has to be. Just migrate the guid
and then management can write it at any time.


> > 
> >> - the address of the GUID is changed (the firmware programs it from
> >> "zero" to an actual address, in a writeable fw_cfg file), and that piece
> >> of info is explicitly migrated, as part of the vmgenid device's vmsd.
> >>
> >> Thanks
> >> Laszlo
> >>
> >>
> >>> - how does the guest on the destination see the same id
> >>> as was in place on the source at the time migration started.
> >>>
> >>>>
> >>>>
> >>>>> when you load state from disk (you don't know how many times the same
> >>>>> state has been loaded previously, so each load is effectively forking
> >>>>> the VM and you want a different value), but for a single live migration,
> >>>>> you aren't forking the VM and don't need a new generation ID.
> >>>>>
> >>>>> I guess it all boils down to what command line you're using: if libvirt
> >>>>> is driving a live migration, it will request the same UUID in the
> >>>>> command line of the destination as what is on the source; while if
> >>>>> libvirt is loading from a [managed]save to restore state from a file, it
> >>>>> will either request a new UUID directly or request auto to let qemu
> >>>>> generate the new id.
> >>>>
> >>>> Hmm now I've lost it a bit; I thought we would preserve the value
> >>>> transmitted from the source, not the value on the command line of the destination.
> >>>
> >>> I guess I'm trying to figure out whether libvirt MUST read the current
> >>> id and explicitly tell the destination of migration to reuse that id, or
> >>> if libvirt can omit the id on migration and everything just works
> >>> because the id was migrated from the source.
> >>>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-21 14:14                     ` Michael S. Tsirkin
@ 2017-02-21 16:08                       ` Laszlo Ersek
  2017-02-21 16:17                         ` Michael S. Tsirkin
  0 siblings, 1 reply; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-21 16:08 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Eric Blake, Dr. David Alan Gilbert, Igor Mammedov, qemu-devel, ben

On 02/21/17 15:14, Michael S. Tsirkin wrote:
> On Tue, Feb 21, 2017 at 10:58:05AM +0100, Laszlo Ersek wrote:
>> On 02/21/17 02:43, Michael S. Tsirkin wrote:
>>> On Mon, Feb 20, 2017 at 09:55:40PM +0100, Laszlo Ersek wrote:
>>>> On 02/20/17 21:45, Eric Blake wrote:
>>>>> On 02/20/2017 02:19 PM, Dr. David Alan Gilbert wrote:
>>>>>> * Eric Blake (eblake@redhat.com) wrote:
>>>>>>> On 02/20/2017 04:23 AM, Dr. David Alan Gilbert wrote:
>>>>>>>> * Laszlo Ersek (lersek@redhat.com) wrote:
>>>>>>>>> CC Dave
>>>>>>>>
>>>>>>>> This isn't an area I really understand; but if I'm
>>>>>>>> reading this right then 
>>>>>>>>    vmgenid is stored in fw_cfg?
>>>>>>>>    fw_cfg isn't migrated
>>>>>>>>
>>>>>>>> So why should any changes to it get migrated, except if it's already
>>>>>>>> been read by the guest (and if the guest reads it again aftwards what's
>>>>>>>> it expected to read?)
>>>>>>>
>>>>>>> Why are we expecting it to change on migration?  You want a new value
>>>>>>
>>>>>> I'm not; I was asking why a change made prior to migration would be
>>>>>> preserved across migration.
>>>>>
>>>>> Okay, so you're asking what happens if the source requests the vmgenid
>>>>> device, and sets an id, but the destination of the migration does not
>>>>> request anything
>>>>
>>>> This should never happen, as it means different QEMU command lines on
>>>> source vs. target hosts. (Different as in "incorrectly different".)
>>>>
>>>> Dave writes, "a change made prior to migration". Change made to what?
>>>>
>>>> - the GUID cannot be changed via the monitor once QEMU has been started.
>>>> We dropped the monitor command for that, due to lack of a good use case,
>>>> and due to lifecycle complexities. We have figured out a way to make it
>>>> safe, but until there's a really convincing use case, we shouldn't add
>>>> that complexity.
>>>
>>> True but we might in the future, and it seems prudent to make
>>> migration stream future-proof for that.
>>
>> It is already.
>>
>> The monitor command, if we add it, can be implemented incrementally. I
>> described it as "approach (iii)" elsewhere in the thread. This is a more
>> detailed recap:
>>
>> - introduce a new device property (internal only), such as
>>   "x-enable-set-vmgenid". Make it reflect whether a given machine type
>>   supports the monitor command.
> 
> This is the part we can avoid at no real cost just
> by making sure the guid is migrated.
> 
> 
>> - change the /etc/vmgenid_guid fw_cfg blob from callback-less to one
>>   with a selection callback
>>
>> - add a new boolean latch to the vmgenid device, called
>>   "guid_blob_selected" or something similar
>>
>> - the reset handler sets the latch to FALSE
>>   (NB: the reset handler already sets /etc/vmgenid_addr to zero)
>>
>> - the select callback for /etc/vmgenid_guid sets the latch to TRUE
>>
>> - the latch is added to the migration stream as a subsection *if*
>>   x-enable-set-vmgenid is TRUE
>>
>> - the set-vmgenid monitor command checks all three of:
>>   x-enable-set-vmgenid, the latch, and the contents of
>>   /etc/vmgenid_addr:
>>
>>   - if x-enable-set-vmgenid is FALSE, the monitor command returns
>>     QERR_UNSUPPORTED (this is a generic error class, with an
>>     "unsupported" error message). Otherwise,
>>
>>   - if the latch is TRUE *and* /etc/vmgenid_addr is zero, then the
>>     guest firmware has executed (or started executing) ALLOCATE for
>>     /etc/vmgenid_guid, but it has not executed WRITE_POINTER yet.
>>     In this case updating the VMGENID from the monitor is unsafe
>>     (we cannot guarantee informing the guest successfully), so in this
>>     case the monitor command fails with ERROR_CLASS_DEVICE_NOT_ACTIVE.
>>     The caller should simply try a bit later. (By which time the
>>     firmware will likely have programmed /etc/vmgenid_addr.)
> 
> This makes no sense to me. Just update it in qemu memory
> and write when guest asks for it.

I designed the above (sorry if "designed" is a word too pompous for
this) quite explicitly to address your concern as to what would happen
if someone tried to massage the GUID via the monitor while the firmware
was between ALLOCATE and WRITE_POINTER.

Also, we don't know when the guest "asks" for the GUID (in guest RAM).
It just evaluates ADDR (maybe always, maybe only once, at guest driver
startup), and then it just looks at RAM whenever it wants to.

This is why this idea seeks to track the guest's state -- if the guest
is before ALLOCATE, it's okay to update the fw_cfg blob, if it is
between ALLOCATE and WRITE_POINTER, reject the monitor command
(temporarily), and if the guest is after WRITE_POINTER, update the RAM
and inject the SCI.

We cannot see *exactly* when the guest has just finished writing the
address. We have only select callbacks for fw_cfg items, not write
callbacks. And a select callback is no good for the address blob,
because it would be invoked *before* the guest writes the address.

We discussed these facts several days (weeks?) and several iterations
ago. The longer term remedy we came up was the above design. The shorter
term remedy was to drop the "set" monitor command, because we couldn't
figure out a management layer use case for that monitor command.

If you now (at v8) insist to future proof the design for a potential
"set" monitor command, that's exactly the same as if you were requiring
Ben to implement the monitor command right now. Except this is worse,
because we dropped the monitor command in v6 (from v5), and you didn't
protest.

> 
> 
>>     Libvirt can recognize this error specifically, because it is not the
>>     generic error class. ERROR_CLASS_DEVICE_NOT_ACTIVE stands for
>>     "EAGAIN", practically, in this case.
>>
>>   - Otherwise -- meaning latch is FALSE *or* /etc/vmgenid_addr is
>>     nonzero, that is, the guest has either not run ALLOCATE since
>>     reset, *or* it has, but it has also run WRITE_POINTER):
>>
>>     - refresh the GUID within the fw_cfg blob for /etc/vmgenid_guid
>>       in-place -- the guest will see this whenever it runs ALLOCATE for
>>       /etc/vmgenid_guid, *AND*
>>
>>     - if /etc/vmgenid_addr is not zero, then update the guest (that is,
>>       RAM write + SCI)
>>
>> Thanks
>> Laszlo
> 
> Seems way more painful than it has to be. Just migrate the guid
> and then management can write it at any time.

Yes, management would be able to do that, but we won't know when to
expose it to the guest. (Because, again, we don't exactly know when the
guest looks at the GUID in RAM, and if the address is not configured
yet, we cannot put the GUID anywhere in RAM.)

Do you intend to block v8 over this?

Thanks
Laszlo

> 
> 
>>>
>>>> - the address of the GUID is changed (the firmware programs it from
>>>> "zero" to an actual address, in a writeable fw_cfg file), and that piece
>>>> of info is explicitly migrated, as part of the vmgenid device's vmsd.
>>>>
>>>> Thanks
>>>> Laszlo
>>>>
>>>>
>>>>> - how does the guest on the destination see the same id
>>>>> as was in place on the source at the time migration started.
>>>>>
>>>>>>
>>>>>>
>>>>>>> when you load state from disk (you don't know how many times the same
>>>>>>> state has been loaded previously, so each load is effectively forking
>>>>>>> the VM and you want a different value), but for a single live migration,
>>>>>>> you aren't forking the VM and don't need a new generation ID.
>>>>>>>
>>>>>>> I guess it all boils down to what command line you're using: if libvirt
>>>>>>> is driving a live migration, it will request the same UUID in the
>>>>>>> command line of the destination as what is on the source; while if
>>>>>>> libvirt is loading from a [managed]save to restore state from a file, it
>>>>>>> will either request a new UUID directly or request auto to let qemu
>>>>>>> generate the new id.
>>>>>>
>>>>>> Hmm now I've lost it a bit; I thought we would preserve the value
>>>>>> transmitted from the source, not the value on the command line of the destination.
>>>>>
>>>>> I guess I'm trying to figure out whether libvirt MUST read the current
>>>>> id and explicitly tell the destination of migration to reuse that id, or
>>>>> if libvirt can omit the id on migration and everything just works
>>>>> because the id was migrated from the source.
>>>>>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-21 16:08                       ` Laszlo Ersek
@ 2017-02-21 16:17                         ` Michael S. Tsirkin
  2017-02-21 16:50                           ` Laszlo Ersek
  0 siblings, 1 reply; 53+ messages in thread
From: Michael S. Tsirkin @ 2017-02-21 16:17 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Eric Blake, Dr. David Alan Gilbert, Igor Mammedov, qemu-devel, ben

On Tue, Feb 21, 2017 at 05:08:40PM +0100, Laszlo Ersek wrote:
> On 02/21/17 15:14, Michael S. Tsirkin wrote:
> > On Tue, Feb 21, 2017 at 10:58:05AM +0100, Laszlo Ersek wrote:
> >> On 02/21/17 02:43, Michael S. Tsirkin wrote:
> >>> On Mon, Feb 20, 2017 at 09:55:40PM +0100, Laszlo Ersek wrote:
> >>>> On 02/20/17 21:45, Eric Blake wrote:
> >>>>> On 02/20/2017 02:19 PM, Dr. David Alan Gilbert wrote:
> >>>>>> * Eric Blake (eblake@redhat.com) wrote:
> >>>>>>> On 02/20/2017 04:23 AM, Dr. David Alan Gilbert wrote:
> >>>>>>>> * Laszlo Ersek (lersek@redhat.com) wrote:
> >>>>>>>>> CC Dave
> >>>>>>>>
> >>>>>>>> This isn't an area I really understand; but if I'm
> >>>>>>>> reading this right then 
> >>>>>>>>    vmgenid is stored in fw_cfg?
> >>>>>>>>    fw_cfg isn't migrated
> >>>>>>>>
> >>>>>>>> So why should any changes to it get migrated, except if it's already
> >>>>>>>> been read by the guest (and if the guest reads it again aftwards what's
> >>>>>>>> it expected to read?)
> >>>>>>>
> >>>>>>> Why are we expecting it to change on migration?  You want a new value
> >>>>>>
> >>>>>> I'm not; I was asking why a change made prior to migration would be
> >>>>>> preserved across migration.
> >>>>>
> >>>>> Okay, so you're asking what happens if the source requests the vmgenid
> >>>>> device, and sets an id, but the destination of the migration does not
> >>>>> request anything
> >>>>
> >>>> This should never happen, as it means different QEMU command lines on
> >>>> source vs. target hosts. (Different as in "incorrectly different".)
> >>>>
> >>>> Dave writes, "a change made prior to migration". Change made to what?
> >>>>
> >>>> - the GUID cannot be changed via the monitor once QEMU has been started.
> >>>> We dropped the monitor command for that, due to lack of a good use case,
> >>>> and due to lifecycle complexities. We have figured out a way to make it
> >>>> safe, but until there's a really convincing use case, we shouldn't add
> >>>> that complexity.
> >>>
> >>> True but we might in the future, and it seems prudent to make
> >>> migration stream future-proof for that.
> >>
> >> It is already.
> >>
> >> The monitor command, if we add it, can be implemented incrementally. I
> >> described it as "approach (iii)" elsewhere in the thread. This is a more
> >> detailed recap:
> >>
> >> - introduce a new device property (internal only), such as
> >>   "x-enable-set-vmgenid". Make it reflect whether a given machine type
> >>   supports the monitor command.
> > 
> > This is the part we can avoid at no real cost just
> > by making sure the guid is migrated.
> > 
> > 
> >> - change the /etc/vmgenid_guid fw_cfg blob from callback-less to one
> >>   with a selection callback
> >>
> >> - add a new boolean latch to the vmgenid device, called
> >>   "guid_blob_selected" or something similar
> >>
> >> - the reset handler sets the latch to FALSE
> >>   (NB: the reset handler already sets /etc/vmgenid_addr to zero)
> >>
> >> - the select callback for /etc/vmgenid_guid sets the latch to TRUE
> >>
> >> - the latch is added to the migration stream as a subsection *if*
> >>   x-enable-set-vmgenid is TRUE
> >>
> >> - the set-vmgenid monitor command checks all three of:
> >>   x-enable-set-vmgenid, the latch, and the contents of
> >>   /etc/vmgenid_addr:
> >>
> >>   - if x-enable-set-vmgenid is FALSE, the monitor command returns
> >>     QERR_UNSUPPORTED (this is a generic error class, with an
> >>     "unsupported" error message). Otherwise,
> >>
> >>   - if the latch is TRUE *and* /etc/vmgenid_addr is zero, then the
> >>     guest firmware has executed (or started executing) ALLOCATE for
> >>     /etc/vmgenid_guid, but it has not executed WRITE_POINTER yet.
> >>     In this case updating the VMGENID from the monitor is unsafe
> >>     (we cannot guarantee informing the guest successfully), so in this
> >>     case the monitor command fails with ERROR_CLASS_DEVICE_NOT_ACTIVE.
> >>     The caller should simply try a bit later. (By which time the
> >>     firmware will likely have programmed /etc/vmgenid_addr.)
> > 
> > This makes no sense to me. Just update it in qemu memory
> > and write when guest asks for it.
> 
> I designed the above (sorry if "designed" is a word too pompous for
> this) quite explicitly to address your concern as to what would happen
> if someone tried to massage the GUID via the monitor while the firmware
> was between ALLOCATE and WRITE_POINTER.
> 
> Also, we don't know when the guest "asks" for the GUID (in guest RAM).
> It just evaluates ADDR (maybe always, maybe only once, at guest driver
> startup), and then it just looks at RAM whenever it wants to.
> 
> This is why this idea seeks to track the guest's state -- if the guest
> is before ALLOCATE, it's okay to update the fw_cfg blob, if it is
> between ALLOCATE and WRITE_POINTER, reject the monitor command
> (temporarily), and if the guest is after WRITE_POINTER, update the RAM
> and inject the SCI.
> 
> We cannot see *exactly* when the guest has just finished writing the
> address. We have only select callbacks for fw_cfg items, not write
> callbacks. And a select callback is no good for the address blob,
> because it would be invoked *before* the guest writes the address.
> 
> We discussed these facts several days (weeks?) and several iterations
> ago. The longer term remedy we came up was the above design. The shorter
> term remedy was to drop the "set" monitor command, because we couldn't
> figure out a management layer use case for that monitor command.
> 
> If you now (at v8) insist to future proof the design for a potential
> "set" monitor command, that's exactly the same as if you were requiring
> Ben to implement the monitor command right now. Except this is worse,
> because we dropped the monitor command in v6 (from v5), and you didn't
> protest.

I'm merging this as-is but I think the concerns are overblown.
We have many fields which devices DMA into guest memory
and changing them is easy.

It should be a simple matter to update guid copy in
fw cfg blob, and *if we have the address*, DMA there
and send SCI.

Yes we don't know when does guest look at guid but that
is simply up to guest. It needs to look at it at the
right time.

So the implementation is really easy I think.

The real problem is that we will have migrated guid
and command line guid and which one wins if they conflict.
And that is IMO something we need to figure out now and
not later.




> > 
> > 
> >>     Libvirt can recognize this error specifically, because it is not the
> >>     generic error class. ERROR_CLASS_DEVICE_NOT_ACTIVE stands for
> >>     "EAGAIN", practically, in this case.
> >>
> >>   - Otherwise -- meaning latch is FALSE *or* /etc/vmgenid_addr is
> >>     nonzero, that is, the guest has either not run ALLOCATE since
> >>     reset, *or* it has, but it has also run WRITE_POINTER):
> >>
> >>     - refresh the GUID within the fw_cfg blob for /etc/vmgenid_guid
> >>       in-place -- the guest will see this whenever it runs ALLOCATE for
> >>       /etc/vmgenid_guid, *AND*
> >>
> >>     - if /etc/vmgenid_addr is not zero, then update the guest (that is,
> >>       RAM write + SCI)
> >>
> >> Thanks
> >> Laszlo
> > 
> > Seems way more painful than it has to be. Just migrate the guid
> > and then management can write it at any time.
> 
> Yes, management would be able to do that, but we won't know when to
> expose it to the guest. (Because, again, we don't exactly know when the
> guest looks at the GUID in RAM, and if the address is not configured
> yet, we cannot put the GUID anywhere in RAM.)
> 
> Do you intend to block v8 over this?
> 
> Thanks
> Laszlo
> 
> > 
> > 
> >>>
> >>>> - the address of the GUID is changed (the firmware programs it from
> >>>> "zero" to an actual address, in a writeable fw_cfg file), and that piece
> >>>> of info is explicitly migrated, as part of the vmgenid device's vmsd.
> >>>>
> >>>> Thanks
> >>>> Laszlo
> >>>>
> >>>>
> >>>>> - how does the guest on the destination see the same id
> >>>>> as was in place on the source at the time migration started.
> >>>>>
> >>>>>>
> >>>>>>
> >>>>>>> when you load state from disk (you don't know how many times the same
> >>>>>>> state has been loaded previously, so each load is effectively forking
> >>>>>>> the VM and you want a different value), but for a single live migration,
> >>>>>>> you aren't forking the VM and don't need a new generation ID.
> >>>>>>>
> >>>>>>> I guess it all boils down to what command line you're using: if libvirt
> >>>>>>> is driving a live migration, it will request the same UUID in the
> >>>>>>> command line of the destination as what is on the source; while if
> >>>>>>> libvirt is loading from a [managed]save to restore state from a file, it
> >>>>>>> will either request a new UUID directly or request auto to let qemu
> >>>>>>> generate the new id.
> >>>>>>
> >>>>>> Hmm now I've lost it a bit; I thought we would preserve the value
> >>>>>> transmitted from the source, not the value on the command line of the destination.
> >>>>>
> >>>>> I guess I'm trying to figure out whether libvirt MUST read the current
> >>>>> id and explicitly tell the destination of migration to reuse that id, or
> >>>>> if libvirt can omit the id on migration and everything just works
> >>>>> because the id was migrated from the source.
> >>>>>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support
  2017-02-21 16:17                         ` Michael S. Tsirkin
@ 2017-02-21 16:50                           ` Laszlo Ersek
  0 siblings, 0 replies; 53+ messages in thread
From: Laszlo Ersek @ 2017-02-21 16:50 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Eric Blake, Dr. David Alan Gilbert, Igor Mammedov, qemu-devel, ben

On 02/21/17 17:17, Michael S. Tsirkin wrote:
> On Tue, Feb 21, 2017 at 05:08:40PM +0100, Laszlo Ersek wrote:
>> On 02/21/17 15:14, Michael S. Tsirkin wrote:
>>> On Tue, Feb 21, 2017 at 10:58:05AM +0100, Laszlo Ersek wrote:
>>>> On 02/21/17 02:43, Michael S. Tsirkin wrote:
>>>>> On Mon, Feb 20, 2017 at 09:55:40PM +0100, Laszlo Ersek wrote:
>>>>>> On 02/20/17 21:45, Eric Blake wrote:
>>>>>>> On 02/20/2017 02:19 PM, Dr. David Alan Gilbert wrote:
>>>>>>>> * Eric Blake (eblake@redhat.com) wrote:
>>>>>>>>> On 02/20/2017 04:23 AM, Dr. David Alan Gilbert wrote:
>>>>>>>>>> * Laszlo Ersek (lersek@redhat.com) wrote:
>>>>>>>>>>> CC Dave
>>>>>>>>>>
>>>>>>>>>> This isn't an area I really understand; but if I'm
>>>>>>>>>> reading this right then 
>>>>>>>>>>    vmgenid is stored in fw_cfg?
>>>>>>>>>>    fw_cfg isn't migrated
>>>>>>>>>>
>>>>>>>>>> So why should any changes to it get migrated, except if it's already
>>>>>>>>>> been read by the guest (and if the guest reads it again aftwards what's
>>>>>>>>>> it expected to read?)
>>>>>>>>>
>>>>>>>>> Why are we expecting it to change on migration?  You want a new value
>>>>>>>>
>>>>>>>> I'm not; I was asking why a change made prior to migration would be
>>>>>>>> preserved across migration.
>>>>>>>
>>>>>>> Okay, so you're asking what happens if the source requests the vmgenid
>>>>>>> device, and sets an id, but the destination of the migration does not
>>>>>>> request anything
>>>>>>
>>>>>> This should never happen, as it means different QEMU command lines on
>>>>>> source vs. target hosts. (Different as in "incorrectly different".)
>>>>>>
>>>>>> Dave writes, "a change made prior to migration". Change made to what?
>>>>>>
>>>>>> - the GUID cannot be changed via the monitor once QEMU has been started.
>>>>>> We dropped the monitor command for that, due to lack of a good use case,
>>>>>> and due to lifecycle complexities. We have figured out a way to make it
>>>>>> safe, but until there's a really convincing use case, we shouldn't add
>>>>>> that complexity.
>>>>>
>>>>> True but we might in the future, and it seems prudent to make
>>>>> migration stream future-proof for that.
>>>>
>>>> It is already.
>>>>
>>>> The monitor command, if we add it, can be implemented incrementally. I
>>>> described it as "approach (iii)" elsewhere in the thread. This is a more
>>>> detailed recap:
>>>>
>>>> - introduce a new device property (internal only), such as
>>>>   "x-enable-set-vmgenid". Make it reflect whether a given machine type
>>>>   supports the monitor command.
>>>
>>> This is the part we can avoid at no real cost just
>>> by making sure the guid is migrated.
>>>
>>>
>>>> - change the /etc/vmgenid_guid fw_cfg blob from callback-less to one
>>>>   with a selection callback
>>>>
>>>> - add a new boolean latch to the vmgenid device, called
>>>>   "guid_blob_selected" or something similar
>>>>
>>>> - the reset handler sets the latch to FALSE
>>>>   (NB: the reset handler already sets /etc/vmgenid_addr to zero)
>>>>
>>>> - the select callback for /etc/vmgenid_guid sets the latch to TRUE
>>>>
>>>> - the latch is added to the migration stream as a subsection *if*
>>>>   x-enable-set-vmgenid is TRUE
>>>>
>>>> - the set-vmgenid monitor command checks all three of:
>>>>   x-enable-set-vmgenid, the latch, and the contents of
>>>>   /etc/vmgenid_addr:
>>>>
>>>>   - if x-enable-set-vmgenid is FALSE, the monitor command returns
>>>>     QERR_UNSUPPORTED (this is a generic error class, with an
>>>>     "unsupported" error message). Otherwise,
>>>>
>>>>   - if the latch is TRUE *and* /etc/vmgenid_addr is zero, then the
>>>>     guest firmware has executed (or started executing) ALLOCATE for
>>>>     /etc/vmgenid_guid, but it has not executed WRITE_POINTER yet.
>>>>     In this case updating the VMGENID from the monitor is unsafe
>>>>     (we cannot guarantee informing the guest successfully), so in this
>>>>     case the monitor command fails with ERROR_CLASS_DEVICE_NOT_ACTIVE.
>>>>     The caller should simply try a bit later. (By which time the
>>>>     firmware will likely have programmed /etc/vmgenid_addr.)
>>>
>>> This makes no sense to me. Just update it in qemu memory
>>> and write when guest asks for it.
>>
>> I designed the above (sorry if "designed" is a word too pompous for
>> this) quite explicitly to address your concern as to what would happen
>> if someone tried to massage the GUID via the monitor while the firmware
>> was between ALLOCATE and WRITE_POINTER.
>>
>> Also, we don't know when the guest "asks" for the GUID (in guest RAM).
>> It just evaluates ADDR (maybe always, maybe only once, at guest driver
>> startup), and then it just looks at RAM whenever it wants to.
>>
>> This is why this idea seeks to track the guest's state -- if the guest
>> is before ALLOCATE, it's okay to update the fw_cfg blob, if it is
>> between ALLOCATE and WRITE_POINTER, reject the monitor command
>> (temporarily), and if the guest is after WRITE_POINTER, update the RAM
>> and inject the SCI.
>>
>> We cannot see *exactly* when the guest has just finished writing the
>> address. We have only select callbacks for fw_cfg items, not write
>> callbacks. And a select callback is no good for the address blob,
>> because it would be invoked *before* the guest writes the address.
>>
>> We discussed these facts several days (weeks?) and several iterations
>> ago. The longer term remedy we came up was the above design. The shorter
>> term remedy was to drop the "set" monitor command, because we couldn't
>> figure out a management layer use case for that monitor command.
>>
>> If you now (at v8) insist to future proof the design for a potential
>> "set" monitor command, that's exactly the same as if you were requiring
>> Ben to implement the monitor command right now. Except this is worse,
>> because we dropped the monitor command in v6 (from v5), and you didn't
>> protest.
> 
> I'm merging this as-is

Thank you!

> but I think the concerns are overblown.
> We have many fields which devices DMA into guest memory
> and changing them is easy.
> 
> It should be a simple matter to update guid copy in
> fw cfg blob, and *if we have the address*, DMA there
> and send SCI.

I think this was more or less what Ben's v5 did, and (again, as far as I
recall) you were concerned about its safety:

msgid: <20170206201249-mutt-send-email-mst@kernel.org>
URL: https://www.mail-archive.com/qemu-devel@nongnu.org/msg427927.html

msgid: <20170206210237-mutt-send-email-mst@kernel.org>
URL: https://www.mail-archive.com/qemu-devel@nongnu.org/msg427935.html

Again, at that point I "invented" the above elaborate design *only* to
address your concern. If you are not concerned any longer (or, if you
had never had this exact concern, I just misunderstood you), then I'm
fine dropping all of the above -- I definitely don't strive to implement
(or request) the above out of my own initiative.

Please see item (5) in the following message:

msgid: <14f224ed-08e2-cbad-9d1d-8f559cd399a6@redhat.com>
URL: https://www.mail-archive.com/qemu-devel@nongnu.org/msg428296.html

The design above is just "approach (iii)" expanded with more details,
from under said item (5). You didn't react there, and I thought you were
okay with the idea.

Then Ben went on to drop the "set" monitor command in v6, and you didn't
comment on that either -- so I assumed you were okay with that too.

> 
> Yes we don't know when does guest look at guid but that
> is simply up to guest. It needs to look at it at the
> right time.
> 
> So the implementation is really easy I think.

That's for the best!

> 
> The real problem is that we will have migrated guid
> and command line guid and which one wins if they conflict.
> And that is IMO something we need to figure out now and
> not later.

Neither Ben nor myself seem to know when the management layer would want
to call the "set" monitor command, and youor question is really hard to
answer without that knowledge.

(Under my proposal, the question does not really exist, because the GUID
set last on the source host needs not be migrated except as part of
guest RAM, and it's always the command line GUID on the target host that
takes precedence after migration and gets written into guest RAM.)

In other words, it is for libvirt / users / etc to say why they would
want to set GUID-A with the monitor command on the source host, *and*
then start up QEMU on the target host with GUID-B on the command line.

... Either way, I would let GUID-B take effect.

Thanks
Laszlo

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 7/8] tests: Add unit tests for the VM Generation ID feature
  2017-02-20 14:49   ` Igor Mammedov
@ 2017-04-21 10:14     ` Marc-André Lureau
  2017-04-21 17:59       ` Ben Warren
  0 siblings, 1 reply; 53+ messages in thread
From: Marc-André Lureau @ 2017-04-21 10:14 UTC (permalink / raw)
  To: Igor Mammedov, ben; +Cc: lersek, qemu-devel, mst

Hi,

Was this patch intentionally dropped from the series?

On Mon, Feb 20, 2017 at 7:12 PM Igor Mammedov <imammedo@redhat.com> wrote:

> On Thu, 16 Feb 2017 15:15:39 -0800
> ben@skyportsystems.com wrote:
>
> > From: Ben Warren <ben@skyportsystems.com>
> >
> > The following tests are implemented:
> > * test that a GUID passed in by command line is propagated to the guest.
> >   Read the GUID from guest memory
> > * test that the "auto" argument to the GUID generates a valid GUID, as
> >   seen by the guest.
> > * test that a GUID passed in can be queried from the monitor
> >
> >   This patch is loosely based on a previous patch from:
> >   Gal Hammer <ghammer@redhat.com>  and Igor Mammedov <
> imammedo@redhat.com>
> >
> > Signed-off-by: Ben Warren <ben@skyportsystems.com>
> Reviewed-by: Igor Mammedov <imammedo@redhat.com>
>
> > ---
> >  tests/Makefile.include |   2 +
> >  tests/vmgenid-test.c   | 200
> +++++++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 202 insertions(+)
> >  create mode 100644 tests/vmgenid-test.c
> >
> > diff --git a/tests/Makefile.include b/tests/Makefile.include
> > index 143507e..8d36341 100644
> > --- a/tests/Makefile.include
> > +++ b/tests/Makefile.include
> > @@ -241,6 +241,7 @@ check-qtest-i386-y +=
> tests/usb-hcd-xhci-test$(EXESUF)
> >  gcov-files-i386-y += hw/usb/hcd-xhci.c
> >  check-qtest-i386-y += tests/pc-cpu-test$(EXESUF)
> >  check-qtest-i386-y += tests/q35-test$(EXESUF)
> > +check-qtest-i386-y += tests/vmgenid-test$(EXESUF)
> >  gcov-files-i386-y += hw/pci-host/q35.c
> >  check-qtest-i386-$(CONFIG_VHOST_NET_TEST_i386) +=
> tests/vhost-user-test$(EXESUF)
> >  ifeq ($(CONFIG_VHOST_NET_TEST_i386),)
> > @@ -726,6 +727,7 @@ tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o
> contrib/ivshmem-server/ivshmem
> >  tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o
> contrib/libvhost-user/libvhost-user.o $(test-util-obj-y)
> >  tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y)
> >  tests/test-arm-mptimer$(EXESUF): tests/test-arm-mptimer.o
> > +tests/vmgenid-test$(EXESUF): tests/vmgenid-test.o tests/acpi-utils.o
> >
> >  tests/migration/stress$(EXESUF): tests/migration/stress.o
> >       $(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@
> $< ,"LINK","$(TARGET_DIR)$@")
> > diff --git a/tests/vmgenid-test.c b/tests/vmgenid-test.c
> > new file mode 100644
> > index 0000000..123beae
> > --- /dev/null
> > +++ b/tests/vmgenid-test.c
> > @@ -0,0 +1,200 @@
> > +/*
> > + * QTest testcase for VM Generation ID
> > + *
> > + * Copyright (c) 2016 Red Hat, Inc.
> > + * Copyright (c) 2017 Skyport Systems
> > + *
> > + * 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 <glib.h>
> > +#include <string.h>
> > +#include <unistd.h>
> > +#include "qemu/osdep.h"
> > +#include "qemu/bitmap.h"
> > +#include "qemu/uuid.h"
> > +#include "hw/acpi/acpi-defs.h"
> > +#include "acpi-utils.h"
> > +#include "libqtest.h"
> > +
> > +#define VGID_GUID "324e6eaf-d1d1-4bf6-bf41-b9bb6c91fb87"
> > +#define VMGENID_GUID_OFFSET 40   /* allow space for
> > +                                  * OVMF SDT Header Probe Supressor
> > +                                  */
> > +#define RSDP_ADDR_INVALID 0x100000 /* RSDP must be below this address */
> > +#define RSDP_SLEEP_US     100000   /* Sleep for 100ms between tries */
> > +#define RSDP_TRIES_MAX    100      /* Max total time is 10 seconds */
> > +
> > +typedef struct {
> > +    AcpiTableHeader header;
> > +    gchar name_op;
> > +    gchar vgia[4];
> > +    gchar val_op;
> > +    uint32_t vgia_val;
> > +} QEMU_PACKED VgidTable;
> > +
> > +static uint32_t acpi_find_vgia(void)
> > +{
> > +    uint32_t off;
> > +    AcpiRsdpDescriptor rsdp_table;
> > +    uint32_t rsdt;
> > +    AcpiRsdtDescriptorRev1 rsdt_table;
> > +    int tables_nr;
> > +    uint32_t *tables;
> > +    AcpiTableHeader ssdt_table;
> > +    VgidTable vgid_table;
> > +    int i;
> > +
> > +    /* Tables may take a short time to be set up by the guest */
> > +    for (i = 0; i < RSDP_TRIES_MAX; i++) {
> > +        off = acpi_find_rsdp_address();
> > +        if (off < RSDP_ADDR_INVALID) {
> > +            break;
> > +        }
> > +        g_usleep(RSDP_SLEEP_US);
> > +    }
> > +    g_assert_cmphex(off, <, RSDP_ADDR_INVALID);
> > +
> > +    acpi_parse_rsdp_table(off, &rsdp_table);
> > +
> > +    rsdt = rsdp_table.rsdt_physical_address;
> > +    /* read the header */
> > +    ACPI_READ_TABLE_HEADER(&rsdt_table, rsdt);
> > +    ACPI_ASSERT_CMP(rsdt_table.signature, "RSDT");
> > +
> > +    /* compute the table entries in rsdt */
> > +    tables_nr = (rsdt_table.length - sizeof(AcpiRsdtDescriptorRev1)) /
> > +                sizeof(uint32_t);
> > +    g_assert_cmpint(tables_nr, >, 0);
> > +
> > +    /* get the addresses of the tables pointed by rsdt */
> > +    tables = g_new0(uint32_t, tables_nr);
> > +    ACPI_READ_ARRAY_PTR(tables, tables_nr, rsdt);
> > +
> > +    for (i = 0; i < tables_nr; i++) {
> > +        ACPI_READ_TABLE_HEADER(&ssdt_table, tables[i]);
> > +        if (!strncmp((char *)ssdt_table.oem_table_id, "VMGENID", 7)) {
> > +            /* the first entry in the table should be VGIA
> > +             * That's all we need
> > +             */
> > +            ACPI_READ_FIELD(vgid_table.name_op, tables[i]);
> > +            g_assert(vgid_table.name_op == 0x08);  /* name */
> > +            ACPI_READ_ARRAY(vgid_table.vgia, tables[i]);
> > +            g_assert(memcmp(vgid_table.vgia, "VGIA", 4) == 0);
> > +            ACPI_READ_FIELD(vgid_table.val_op, tables[i]);
> > +            g_assert(vgid_table.val_op == 0x0C);  /* dword */
> > +            ACPI_READ_FIELD(vgid_table.vgia_val, tables[i]);
> > +            /* The GUID is written at a fixed offset into the fw_cfg
> file
> > +             * in order to implement the "OVMF SDT Header probe
> suppressor"
> > +             * see docs/specs/vmgenid.txt for more details
> > +             */
> > +            return vgid_table.vgia_val + VMGENID_GUID_OFFSET;
> > +        }
> > +    }
> > +    return 0;
> > +}
> > +
> > +static void read_guid_from_memory(QemuUUID *guid)
> > +{
> > +    uint32_t vmgenid_addr;
> > +    int i;
> > +
> > +    vmgenid_addr = acpi_find_vgia();
> > +    g_assert(vmgenid_addr);
> > +
> > +    /* Read the GUID directly from guest memory */
> > +    for (i = 0; i < 16; i++) {
> > +        guid->data[i] = readb(vmgenid_addr + i);
> > +    }
> > +    /* The GUID is in little-endian format in the guest, while QEMU
> > +     * uses big-endian.  Swap after reading.
> > +     */
> > +    qemu_uuid_bswap(guid);
> > +}
> > +
> > +static void read_guid_from_monitor(QemuUUID *guid)
> > +{
> > +    QDict *rsp, *rsp_ret;
> > +    const char *guid_str;
> > +
> > +    rsp = qmp("{ 'execute': 'query-vm-generation-id' }");
> > +    if (qdict_haskey(rsp, "return")) {
> > +        rsp_ret = qdict_get_qdict(rsp, "return");
> > +        g_assert(qdict_haskey(rsp_ret, "guid"));
> > +        guid_str = qdict_get_str(rsp_ret, "guid");
> > +        g_assert(qemu_uuid_parse(guid_str, guid) == 0);
> > +    }
> > +    QDECREF(rsp);
> > +}
> > +
> > +static void vmgenid_set_guid_test(void)
> > +{
> > +    QemuUUID expected, measured;
> > +    gchar *cmd;
> > +
> > +    g_assert(qemu_uuid_parse(VGID_GUID, &expected) == 0);
> > +
> > +    cmd = g_strdup_printf("-machine accel=tcg -device
> vmgenid,id=testvgid,"
> > +                          "guid=%s", VGID_GUID);
> > +    qtest_start(cmd);
> > +
> > +    /* Read the GUID from accessing guest memory */
> > +    read_guid_from_memory(&measured);
> > +    g_assert(memcmp(measured.data, expected.data,
> sizeof(measured.data)) == 0);
> > +
> > +    qtest_quit(global_qtest);
> > +    g_free(cmd);
> > +}
> > +
> > +static void vmgenid_set_guid_auto_test(void)
> > +{
> > +    const char *cmd;
> > +    QemuUUID measured;
> > +
> > +    cmd = "-machine accel=tcg -device vmgenid,id=testvgid," "guid=auto";
> > +    qtest_start(cmd);
> > +
> > +    read_guid_from_memory(&measured);
> > +
> > +    /* Just check that the GUID is non-null */
> > +    g_assert(!qemu_uuid_is_null(&measured));
> > +
> > +    qtest_quit(global_qtest);
> > +}
> > +
> > +static void vmgenid_query_monitor_test(void)
> > +{
> > +    QemuUUID expected, measured;
> > +    gchar *cmd;
> > +
> > +    g_assert(qemu_uuid_parse(VGID_GUID, &expected) == 0);
> > +
> > +    cmd = g_strdup_printf("-machine accel=tcg -device
> vmgenid,id=testvgid,"
> > +                          "guid=%s", VGID_GUID);
> > +    qtest_start(cmd);
> > +
> > +    /* Read the GUID via the monitor */
> > +    read_guid_from_monitor(&measured);
> > +    g_assert(memcmp(measured.data, expected.data,
> sizeof(measured.data)) == 0);
> > +
> > +    qtest_quit(global_qtest);
> > +    g_free(cmd);
> > +}
> > +
> > +int main(int argc, char **argv)
> > +{
> > +    int ret;
> > +
> > +    g_test_init(&argc, &argv, NULL);
> > +
> > +    qtest_add_func("/vmgenid/vmgenid/set-guid",
> > +                   vmgenid_set_guid_test);
> > +    qtest_add_func("/vmgenid/vmgenid/set-guid-auto",
> > +                   vmgenid_set_guid_auto_test);
> > +    qtest_add_func("/vmgenid/vmgenid/query-monitor",
> > +                   vmgenid_query_monitor_test);
> > +    ret = g_test_run();
> > +
> > +    return ret;
> > +}
>
>
> --
Marc-André Lureau

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 7/8] tests: Add unit tests for the VM Generation ID feature
  2017-04-21 10:14     ` Marc-André Lureau
@ 2017-04-21 17:59       ` Ben Warren
  2017-04-24 12:28         ` Laszlo Ersek
  0 siblings, 1 reply; 53+ messages in thread
From: Ben Warren @ 2017-04-21 17:59 UTC (permalink / raw)
  To: Marc-André Lureau; +Cc: Igor Mammedov, lersek, qemu-devel, mst

Hi,

> On Apr 21, 2017, at 3:14 AM, Marc-André Lureau <marcandre.lureau@gmail.com> wrote:
> 
> Hi,
> 
> Was this patch intentionally dropped from the series?
> 

Good question.  I thought the whole patch series was pulled in, but it looks like this one was not.  I guess we’ll see what Michael has to say.

—Ben
<snip>
> 
> 
> -- 
> Marc-André Lureau

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Qemu-devel] [PATCH v8 7/8] tests: Add unit tests for the VM Generation ID feature
  2017-04-21 17:59       ` Ben Warren
@ 2017-04-24 12:28         ` Laszlo Ersek
  0 siblings, 0 replies; 53+ messages in thread
From: Laszlo Ersek @ 2017-04-24 12:28 UTC (permalink / raw)
  To: Ben Warren, Marc-André Lureau; +Cc: Igor Mammedov, qemu-devel, mst

On 04/21/17 19:59, Ben Warren wrote:
> Hi,
> 
>> On Apr 21, 2017, at 3:14 AM, Marc-André Lureau <marcandre.lureau@gmail.com> wrote:
>>
>> Hi,
>>
>> Was this patch intentionally dropped from the series?
>>
> 
> Good question.  I thought the whole patch series was pulled in, but it looks like this one was not.  I guess we’ll see what Michael has to say.

Unfortunately, the patch was lost due to a race condition in maintenance.

(1) The VMGENID unit test, added in this patch, can only succeed if the
SeaBIOS binary bundled with QEMU contains VMGENID patches as well. When
this v8 patch series was originally posted (Feb 16th), the SeaBIOS
binary bundled with QEMU wasn't ready for this patch. So the patch was
delayed / postponed.

(2) For that reason, Michael sent the PULL req with the *rest* of the
patches, on March 1st:

http://mid.mail-archive.com/1488435591-17882-1-git-send-email-mst@redhat.com

(3) Gerd updated the SeaBIOS binary meanwhile, to a revision that
contained Ben's matching bios patches:

$ git log v2.8.0..v2.9.0 -- pc-bios/bios.bin

commit 8779fccbef0c2e97fd6564ddf9f1df9fc724f2f0
Author: Gerd Hoffmann <kraxel@redhat.com>
Date:   Tue Feb 28 09:52:32 2017 +0100

    seabios: update to 1.10.2 release

    git shortlog rel-1.10.1..rel-1.10.2
    ===================================

    Ben Warren (5):
          QEMU DMA: Add DMA write capability
          romfile-loader: Switch to using named structs
          QEMU fw_cfg: Add command to write back address of file
          QEMU fw_cfg: Add functions for accessing files by key
          QEMU fw_cfg: Write fw_cfg back on S3 resume

    Kevin O'Connor (1):
          ps2port: Disable keyboard/mouse prior to resetting ps2 controller

    Ladi Prosek (1):
          ahci: Set upper 32-bit registers to zero

    Paul Menzel (1):
          vgasrc: Increase debug level

    Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>

(4) In the end, the BIOS update commit, and the VMGENID v8 commits, are
*not* in an ancestor/descandant relationship either way -- they are
siblings:

  $ git-contains 42697d88de6b 8779fccbef0c
  42697d88de6b [42697d88de6b MAINTAINERS: Add VM Generation ID entries]
  NEITHER CONTAINS NOR IS CONTAINED BY
  8779fccbef0c [8779fccbef0c seabios: update to 1.10.2 release]

And then the patch missed v2.9.0.


I suggest to repost the patch now, and then maybe include it in 2.9.1
stable.

Thanks
Laszlo

^ permalink raw reply	[flat|nested] 53+ messages in thread

end of thread, other threads:[~2017-04-24 12:28 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-16 23:15 [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID ben
2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 1/8] linker-loader: Add new 'write pointer' command ben
2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 2/8] docs: VM Generation ID device description ben
2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 3/8] ACPI: Add vmgenid blob storage to the build tables ben
2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 4/8] ACPI: Add Virtual Machine Generation ID support ben
2017-02-17 10:43   ` Igor Mammedov
2017-02-17 12:50     ` Laszlo Ersek
2017-02-17 13:05       ` Igor Mammedov
2017-02-17 13:41         ` Laszlo Ersek
2017-02-20 10:23       ` Dr. David Alan Gilbert
2017-02-20 10:40         ` Laszlo Ersek
2017-02-20 11:00           ` Dr. David Alan Gilbert
2017-02-20 11:38             ` Laszlo Ersek
2017-02-20 12:32               ` Dr. David Alan Gilbert
2017-02-20 15:35                 ` Laszlo Ersek
2017-02-20 13:13               ` Igor Mammedov
2017-02-20 13:28                 ` Laszlo Ersek
2017-02-20 14:40                   ` Igor Mammedov
2017-02-20 20:00         ` Eric Blake
2017-02-20 20:19           ` Dr. David Alan Gilbert
2017-02-20 20:45             ` Eric Blake
2017-02-20 20:55               ` Laszlo Ersek
2017-02-21  1:43                 ` Michael S. Tsirkin
2017-02-21  9:58                   ` Laszlo Ersek
2017-02-21 14:14                     ` Michael S. Tsirkin
2017-02-21 16:08                       ` Laszlo Ersek
2017-02-21 16:17                         ` Michael S. Tsirkin
2017-02-21 16:50                           ` Laszlo Ersek
2017-02-20 20:49             ` Laszlo Ersek
2017-02-17 15:33     ` Ben Warren
2017-02-17 16:03       ` Laszlo Ersek
2017-02-17 18:34         ` Ben Warren
2017-02-17 19:00           ` Michael S. Tsirkin
2017-02-17 20:42           ` Laszlo Ersek
2017-02-17 20:07         ` Laszlo Ersek
2017-02-18  0:15           ` Ben Warren
2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 5/8] qmp/hmp: add query-vm-generation-id and 'info vm-generation-id' commands ben
2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 6/8] tests: Move reusable ACPI code into a utility file ben
2017-02-20 14:49   ` Igor Mammedov
2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 7/8] tests: Add unit tests for the VM Generation ID feature ben
2017-02-20 14:49   ` Igor Mammedov
2017-04-21 10:14     ` Marc-André Lureau
2017-04-21 17:59       ` Ben Warren
2017-04-24 12:28         ` Laszlo Ersek
2017-02-16 23:15 ` [Qemu-devel] [PATCH v8 8/8] MAINTAINERS: Add VM Generation ID entries ben
2017-02-20 14:50   ` Igor Mammedov
2017-02-20 14:57 ` [Qemu-devel] [PATCH v8 0/8] Add support for VM Generation ID Igor Mammedov
2017-02-20 15:41   ` Laszlo Ersek
2017-02-20 15:45     ` Kevin O'Connor
2017-02-20 16:00       ` Laszlo Ersek
2017-02-21  7:10       ` Gerd Hoffmann
2017-02-20 18:10     ` Ben Warren
2017-02-21 12:20   ` Laszlo Ersek

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.