All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together
@ 2016-10-03 18:24 Jianjun Duan
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 1/6] migration: alternative way to set instance_id in SaveStateEntry Jianjun Duan
                   ` (8 more replies)
  0 siblings, 9 replies; 66+ messages in thread
From: Jianjun Duan @ 2016-10-03 18:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-ppc, duanj, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth,
	dgilbert

Hi all,
   The previous patches seem to get buried deep somewhere. I am sending the lated rebased version. Comments are welcome.

v5: - Rebased to David's ppc-for-2.8. Previous versions are:

v4: - Introduce a way to set customized instance_id in SaveStateEntry. Use it
      to set instance_id for DRC using its unique index to address David 
      Gibson's concern.
    - Rename VMS_CSTM to VMS_LINKED based on Paolo Bonzini's suggestions.
    - Clean up qjson stuff in put_qtailq. 
    - Add trace for put_qtailq and get_qtailq based on David Gilbert's 
      suggestion.

    - Based on David's ppc-for-2.7. 

v3: - Simplify overall design followng discussion with Paolo. No longer need
      metadata to migrate QTAILQ.
    - Extend VMStateInfo instead of adding similar fields to VMStateField.
    - Clean up macros in qemu/queue.h.
(link: https://lists.nongnu.org/archive/html/qemu-devel/2016-05/msg05695.html)

v2: - Introduce a general approach to migrate QTAILQ in qemu/queue.h.
    - Migrate signalled field in the DRC state.
    - Put the newly added migrating fields in subsections so that backward 
      migration is not broken.  
    - Set detach_cb field right after migration so that a migrated hot-unplug
      event could finish its course.
(link: https://lists.nongnu.org/archive/html/qemu-devel/2016-05/msg04188.html)

v1: - Inital version.
(link: https://lists.nongnu.org/archive/html/qemu-devel/2016-04/msg02601.html)

To make guest device (PCI, CPU and memory) hotplug work together 
with guest migration, spapr drc state needs be transmitted in
migration. This patch defines the VMStateDescription struct for
spapr drc state to enable it.

To fix the potential racing between hotplug events on guest and 
guest migration, ccs_list and pending_events of spapr state need be 
transmitted in migration. This patch also takes care of it.

Jianjun Duan (6):
  migration: alternative way to set instance_id in SaveStateEntry
  migration: spapr_drc: defined VMStateDescription struct
  migration: extend VMStateInfo
  migration: migrate QTAILQ
  migration: spapr: migrate ccs_list in spapr state
  migration: spapr: migrate pending_events of spapr state

 hw/net/vmxnet3.c            |  18 +++--
 hw/nvram/eeprom93xx.c       |   6 +-
 hw/nvram/fw_cfg.c           |   6 +-
 hw/pci/msix.c               |   6 +-
 hw/pci/pci.c                |  12 ++--
 hw/pci/shpc.c               |   5 +-
 hw/ppc/spapr.c              |  67 ++++++++++++++++++
 hw/ppc/spapr_drc.c          |  69 +++++++++++++++++++
 hw/ppc/spapr_events.c       |  22 +++---
 hw/ppc/spapr_pci.c          |  22 ++++++
 hw/scsi/scsi-bus.c          |   6 +-
 hw/timer/twl92230.c         |   6 +-
 hw/usb/redirect.c           |  18 +++--
 hw/virtio/virtio-pci.c      |   6 +-
 hw/virtio/virtio.c          |   6 +-
 include/hw/ppc/spapr.h      |   3 +-
 include/hw/ppc/spapr_drc.h  |   9 +++
 include/hw/qdev-core.h      |   6 ++
 include/migration/vmstate.h |  36 ++++++++--
 include/qemu/queue.h        |  32 +++++++++
 migration/savevm.c          |  25 +++++--
 migration/trace-events      |   4 ++
 migration/vmstate.c         | 161 ++++++++++++++++++++++++++++++++++----------
 target-alpha/machine.c      |   5 +-
 target-arm/machine.c        |  12 ++--
 target-i386/machine.c       |  21 ++++--
 target-mips/machine.c       |  10 +--
 target-ppc/machine.c        |  10 +--
 target-sparc/machine.c      |   5 +-
 29 files changed, 505 insertions(+), 109 deletions(-)

-- 
1.9.1

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

* [Qemu-devel] [QEMU PATCH v5 1/6] migration: alternative way to set instance_id in SaveStateEntry
  2016-10-03 18:24 [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together Jianjun Duan
@ 2016-10-03 18:24 ` Jianjun Duan
  2016-10-05 10:12   ` Dr. David Alan Gilbert
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 2/6] migration: spapr_drc: defined VMStateDescription struct Jianjun Duan
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 66+ messages in thread
From: Jianjun Duan @ 2016-10-03 18:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-ppc, duanj, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth,
	dgilbert

In QOM(QEMU Object Model) migrated objects are identified with instance_id
which is calculated automatically using their path in the QOM composition
tree. For some objects, this path could change from source to target in
migration. To migrate such objects, we need to make sure the instance_id does
not change from source to target. We add a hook in DeviceClass to do customized
instance_id calculation in such cases.

As a result, in these cases compat will not be set in the concerned
SaveStateEntry. This will prevent the inconsistent idstr to be sent over in
migration. We could have set alias_id in a similar way. But that will be
overloading the purpose of alias_id.

The first application will be setting instance_id for DRC using its unique
index. Doing this makes the instance_id of DRC to be consistent across migration
and supports flexible management of DRC objects in migration.

Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
---
 include/hw/qdev-core.h |  6 ++++++
 migration/savevm.c     | 20 ++++++++++++++++++--
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 2c97347..a012e8e 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -139,6 +139,12 @@ typedef struct DeviceClass {
     qdev_initfn init; /* TODO remove, once users are converted to realize */
     qdev_event exit; /* TODO remove, once users are converted to unrealize */
     const char *bus_type;
+
+    /* When this field is set, qemu will use it to get an unique instance_id
+     * instead of calculating an auto idstr and instanc_id for the relevant
+     * SaveStateEntry
+     */
+    int (*dev_get_instance_id)(DeviceState *dev);
 } DeviceClass;
 
 typedef struct NamedGPIOList NamedGPIOList;
diff --git a/migration/savevm.c b/migration/savevm.c
index 33a2911..ef5c3d1 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -495,6 +495,11 @@ int register_savevm_live(DeviceState *dev,
                          void *opaque)
 {
     SaveStateEntry *se;
+    /* when it is a device and it provides a way to get instance_id,
+     * we will use it and skip setting idstr and compat.
+     */
+    bool flag = (dev != NULL) &&
+                (DEVICE_GET_CLASS(dev)->dev_get_instance_id != NULL);
 
     se = g_new0(SaveStateEntry, 1);
     se->version_id = version_id;
@@ -507,7 +512,7 @@ int register_savevm_live(DeviceState *dev,
         se->is_ram = 1;
     }
 
-    if (dev) {
+    if (dev && !flag) {
         char *id = qdev_get_dev_path(dev);
         if (id) {
             pstrcpy(se->idstr, sizeof(se->idstr), id);
@@ -523,6 +528,9 @@ int register_savevm_live(DeviceState *dev,
     }
     pstrcat(se->idstr, sizeof(se->idstr), idstr);
 
+    if (flag) {
+        instance_id = DEVICE_GET_CLASS(dev)->dev_get_instance_id(dev);
+    }
     if (instance_id == -1) {
         se->instance_id = calculate_new_instance_id(se->idstr);
     } else {
@@ -580,6 +588,11 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
                                    int required_for_version)
 {
     SaveStateEntry *se;
+    /* when it is a device and it provides a way to get instance_id,
+     * we will use it and skip setting idstr and compat.
+     */
+    bool flag = (dev != NULL) &&
+                (DEVICE_GET_CLASS(dev)->dev_get_instance_id != NULL);
 
     /* If this triggers, alias support can be dropped for the vmsd. */
     assert(alias_id == -1 || required_for_version >= vmsd->minimum_version_id);
@@ -591,7 +604,7 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
     se->vmsd = vmsd;
     se->alias_id = alias_id;
 
-    if (dev) {
+    if (dev && !flag) {
         char *id = qdev_get_dev_path(dev);
         if (id) {
             pstrcpy(se->idstr, sizeof(se->idstr), id);
@@ -607,6 +620,9 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
     }
     pstrcat(se->idstr, sizeof(se->idstr), vmsd->name);
 
+    if (flag) {
+        instance_id = DEVICE_GET_CLASS(dev)->dev_get_instance_id(dev);
+    }
     if (instance_id == -1) {
         se->instance_id = calculate_new_instance_id(se->idstr);
     } else {
-- 
1.9.1

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

* [Qemu-devel] [QEMU PATCH v5 2/6] migration: spapr_drc: defined VMStateDescription struct
  2016-10-03 18:24 [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together Jianjun Duan
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 1/6] migration: alternative way to set instance_id in SaveStateEntry Jianjun Duan
@ 2016-10-03 18:24 ` Jianjun Duan
  2016-10-05 11:38   ` Dr. David Alan Gilbert
  2016-10-07  3:12   ` David Gibson
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 3/6] migration: extend VMStateInfo Jianjun Duan
                   ` (6 subsequent siblings)
  8 siblings, 2 replies; 66+ messages in thread
From: Jianjun Duan @ 2016-10-03 18:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-ppc, duanj, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth,
	dgilbert

To manage hotplug/unplug of dynamic resources such as PCI cards,
memory, and CPU on sPAPR guests, a firmware abstraction known as
a Dynamic Resource Connector (DRC) is used to assign a particular
dynamic resource to the guest, and provide an interface for the
guest to manage configuration/removal of the resource associated
with it.

To migrate the hotplugged resources in migration, the
associated DRC state need be migrated. To migrate the DRC state,
we defined the VMStateDescription struct for spapr_drc to enable
the transmission of spapr_drc state in migration.

Not all the elements in the DRC state are migrated. Only those
ones modifiable or needed by guest actions or device add/remove
operation are migrated. From the perspective of device
hotplugging, if we hotplug a device on the source, we need to
"coldplug" it on the target. The states across two hosts for the
same device are not the same. Ideally we want the states be same
after migration so that the device would function as hotplugged
on the target. For example we can unplug it. The minimum DRC
state we need to transfer should cover all the pieces changed by
hotplugging. Out of the elements of the DRC state, isolation_state,
allocation_sate, and configured are involved in the DR state
transition diagram from PAPR+ 2.7, 13.4. configured and signalled
are needed in attaching and detaching devices. indicator_state
provides users with hardware state information. These 6 elements
are migrated.

detach_cb in the DRC state is a function pointer that cannot be
migrated. We set it right after DRC state is migrated so that
a migrated hot-unplug event could finish its work.

The instance_id is used to identify objects in migration. We set
instance_id of DRC using the unique index so that it is the same
across migration.

Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
---
 hw/ppc/spapr_drc.c         | 69 ++++++++++++++++++++++++++++++++++++++++++++++
 hw/ppc/spapr_pci.c         | 22 +++++++++++++++
 include/hw/ppc/spapr_drc.h |  9 ++++++
 3 files changed, 100 insertions(+)

diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index 6e54fd4..369ec02 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -615,6 +615,71 @@ static void spapr_dr_connector_instance_init(Object *obj)
                         NULL, NULL, NULL, NULL);
 }
 
+static bool spapr_drc_needed(void *opaque)
+{
+    sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;
+    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+    bool rc = false;
+    sPAPRDREntitySense value;
+
+    drck->entity_sense(drc, &value);
+    /* If no dev is plugged in there is no need to migrate the DRC state */
+    if (value != SPAPR_DR_ENTITY_SENSE_PRESENT) {
+        return false;
+    }
+    /*
+     * If there is dev plugged in, we need to migrate the DRC state when
+     * it is different from cold-plugged state
+     */
+    switch(drc->type) {
+    /* for PCI type */
+    case SPAPR_DR_CONNECTOR_TYPE_PCI:
+        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) &&
+               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) &&
+               drc->configured && drc->signalled && !drc->awaiting_release);
+        break;
+    /* for LMB type */
+    case SPAPR_DR_CONNECTOR_TYPE_LMB:
+        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) &&
+               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) &&
+               drc->configured && drc->signalled && !drc->awaiting_release);
+        break;
+    default:
+        ;
+    }
+
+    return rc;
+}
+
+/* detach_cb needs be set since it is not migrated */
+static void postmigrate_set_detach_cb(sPAPRDRConnector *drc,
+                                      spapr_drc_detach_cb *detach_cb)
+{
+    drc->detach_cb = detach_cb;
+}
+
+/* return the unique drc index as instance_id for qom interfaces*/
+static int get_instance_id(DeviceState *dev)
+{
+    return (int)get_index(SPAPR_DR_CONNECTOR(OBJECT(dev)));
+}
+
+static const VMStateDescription vmstate_spapr_drc = {
+    .name = "spapr_drc",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = spapr_drc_needed,
+    .fields  = (VMStateField []) {
+        VMSTATE_UINT32(isolation_state, sPAPRDRConnector),
+        VMSTATE_UINT32(allocation_state, sPAPRDRConnector),
+        VMSTATE_UINT32(indicator_state, sPAPRDRConnector),
+        VMSTATE_BOOL(configured, sPAPRDRConnector),
+        VMSTATE_BOOL(awaiting_release, sPAPRDRConnector),
+        VMSTATE_BOOL(signalled, sPAPRDRConnector),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
 {
     DeviceClass *dk = DEVICE_CLASS(k);
@@ -623,6 +688,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
     dk->reset = reset;
     dk->realize = realize;
     dk->unrealize = unrealize;
+    dk->vmsd = &vmstate_spapr_drc;
+    dk->dev_get_instance_id = get_instance_id;
     drck->set_isolation_state = set_isolation_state;
     drck->set_indicator_state = set_indicator_state;
     drck->set_allocation_state = set_allocation_state;
@@ -636,6 +703,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
     drck->detach = detach;
     drck->release_pending = release_pending;
     drck->set_signalled = set_signalled;
+    drck->postmigrate_set_detach_cb = postmigrate_set_detach_cb;
+
     /*
      * Reason: it crashes FIXME find and document the real reason
      */
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 4f00865..080471c 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -1594,11 +1594,33 @@ static void spapr_pci_pre_save(void *opaque)
     }
 }
 
+/*
+ * detach_cb in the DRC state is a function pointer that cannot be
+ * migrated. We set it right after migration so that a migrated
+ * hot-unplug event could finish its work.
+ */
+static void spapr_pci_set_detach_cb(PCIBus *bus, PCIDevice *pdev,
+                                 void *opaque)
+{
+    sPAPRPHBState *sphb = opaque;
+    sPAPRDRConnector *drc = spapr_phb_get_pci_drc(sphb, pdev);
+    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+    drck->postmigrate_set_detach_cb(drc, spapr_phb_remove_pci_device_cb);
+}
+
 static int spapr_pci_post_load(void *opaque, int version_id)
 {
     sPAPRPHBState *sphb = opaque;
     gpointer key, value;
     int i;
+    PCIBus *bus = PCI_HOST_BRIDGE(sphb)->bus;
+    unsigned int bus_no = 0;
+
+    /* Set detach_cb for the drc unconditionally after migration */
+    if (bus) {
+        pci_for_each_device(bus, pci_bus_num(bus), spapr_pci_set_detach_cb,
+                            &bus_no);
+    }
 
     for (i = 0; i < sphb->msi_devs_num; ++i) {
         key = g_memdup(&sphb->msi_devs[i].key,
diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h
index fa531d5..17589c8 100644
--- a/include/hw/ppc/spapr_drc.h
+++ b/include/hw/ppc/spapr_drc.h
@@ -192,6 +192,15 @@ typedef struct sPAPRDRConnectorClass {
                    void *detach_cb_opaque, Error **errp);
     bool (*release_pending)(sPAPRDRConnector *drc);
     void (*set_signalled)(sPAPRDRConnector *drc);
+
+    /*
+     * QEMU interface for setting detach_cb after migration.
+     * detach_cb in the DRC state is a function pointer that cannot be
+     * migrated. We set it right after migration so that a migrated
+     * hot-unplug event could finish its work.
+     */
+    void (*postmigrate_set_detach_cb)(sPAPRDRConnector *drc,
+                                      spapr_drc_detach_cb *detach_cb);
 } sPAPRDRConnectorClass;
 
 sPAPRDRConnector *spapr_dr_connector_new(Object *owner,
-- 
1.9.1

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

* [Qemu-devel] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-03 18:24 [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together Jianjun Duan
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 1/6] migration: alternative way to set instance_id in SaveStateEntry Jianjun Duan
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 2/6] migration: spapr_drc: defined VMStateDescription struct Jianjun Duan
@ 2016-10-03 18:24 ` Jianjun Duan
  2016-10-07 12:08   ` Dr. David Alan Gilbert
  2016-10-12 11:59   ` [Qemu-devel] " Halil Pasic
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ Jianjun Duan
                   ` (5 subsequent siblings)
  8 siblings, 2 replies; 66+ messages in thread
From: Jianjun Duan @ 2016-10-03 18:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-ppc, duanj, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth,
	dgilbert

Current migration code cannot handle some data structures such as
QTAILQ in qemu/queue.h. Here we extend the signatures of put/get
in VMStateInfo so that customized handling is supported.

Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
---
 hw/net/vmxnet3.c            | 18 ++++++---
 hw/nvram/eeprom93xx.c       |  6 ++-
 hw/nvram/fw_cfg.c           |  6 ++-
 hw/pci/msix.c               |  6 ++-
 hw/pci/pci.c                | 12 ++++--
 hw/pci/shpc.c               |  5 ++-
 hw/scsi/scsi-bus.c          |  6 ++-
 hw/timer/twl92230.c         |  6 ++-
 hw/usb/redirect.c           | 18 ++++++---
 hw/virtio/virtio-pci.c      |  6 ++-
 hw/virtio/virtio.c          |  6 ++-
 include/migration/vmstate.h | 10 +++--
 migration/savevm.c          |  5 ++-
 migration/vmstate.c         | 95 ++++++++++++++++++++++++++++-----------------
 target-alpha/machine.c      |  5 ++-
 target-arm/machine.c        | 12 ++++--
 target-i386/machine.c       | 21 ++++++----
 target-mips/machine.c       | 10 +++--
 target-ppc/machine.c        | 10 +++--
 target-sparc/machine.c      |  5 ++-
 20 files changed, 171 insertions(+), 97 deletions(-)

diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 90f6943..943a960 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -2450,7 +2450,8 @@ static void vmxnet3_put_tx_stats_to_file(QEMUFile *f,
     qemu_put_be64(f, tx_stat->pktsTxDiscard);
 }
 
-static int vmxnet3_get_txq_descr(QEMUFile *f, void *pv, size_t size)
+static int vmxnet3_get_txq_descr(QEMUFile *f, void *pv, size_t size,
+    VMStateField *field)
 {
     Vmxnet3TxqDescr *r = pv;
 
@@ -2464,7 +2465,8 @@ static int vmxnet3_get_txq_descr(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void vmxnet3_put_txq_descr(QEMUFile *f, void *pv, size_t size)
+static void vmxnet3_put_txq_descr(QEMUFile *f, void *pv, size_t size,
+    VMStateField *field, QJSON *vmdesc)
 {
     Vmxnet3TxqDescr *r = pv;
 
@@ -2511,7 +2513,8 @@ static void vmxnet3_put_rx_stats_to_file(QEMUFile *f,
     qemu_put_be64(f, rx_stat->pktsRxError);
 }
 
-static int vmxnet3_get_rxq_descr(QEMUFile *f, void *pv, size_t size)
+static int vmxnet3_get_rxq_descr(QEMUFile *f, void *pv, size_t size,
+    VMStateField *field)
 {
     Vmxnet3RxqDescr *r = pv;
     int i;
@@ -2529,7 +2532,8 @@ static int vmxnet3_get_rxq_descr(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void vmxnet3_put_rxq_descr(QEMUFile *f, void *pv, size_t size)
+static void vmxnet3_put_rxq_descr(QEMUFile *f, void *pv, size_t size,
+    VMStateField *field, QJSON *vmdesc)
 {
     Vmxnet3RxqDescr *r = pv;
     int i;
@@ -2574,7 +2578,8 @@ static const VMStateInfo rxq_descr_info = {
     .put = vmxnet3_put_rxq_descr
 };
 
-static int vmxnet3_get_int_state(QEMUFile *f, void *pv, size_t size)
+static int vmxnet3_get_int_state(QEMUFile *f, void *pv, size_t size,
+    VMStateField *field)
 {
     Vmxnet3IntState *r = pv;
 
@@ -2585,7 +2590,8 @@ static int vmxnet3_get_int_state(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void vmxnet3_put_int_state(QEMUFile *f, void *pv, size_t size)
+static void vmxnet3_put_int_state(QEMUFile *f, void *pv, size_t size,
+    VMStateField *field, QJSON *vmdesc)
 {
     Vmxnet3IntState *r = pv;
 
diff --git a/hw/nvram/eeprom93xx.c b/hw/nvram/eeprom93xx.c
index 2c16fc2..76d5f41 100644
--- a/hw/nvram/eeprom93xx.c
+++ b/hw/nvram/eeprom93xx.c
@@ -94,14 +94,16 @@ struct _eeprom_t {
    This is a Big hack, but it is how the old state did it.
  */
 
-static int get_uint16_from_uint8(QEMUFile *f, void *pv, size_t size)
+static int get_uint16_from_uint8(QEMUFile *f, void *pv, size_t size,
+                                 VMStateField *field)
 {
     uint16_t *v = pv;
     *v = qemu_get_ubyte(f);
     return 0;
 }
 
-static void put_unused(QEMUFile *f, void *pv, size_t size)
+static void put_unused(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                       QJSON *vmdesc)
 {
     fprintf(stderr, "uint16_from_uint8 is used only for backwards compatibility.\n");
     fprintf(stderr, "Never should be used to write a new state.\n");
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 92aa563..a8a4a7a 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -524,14 +524,16 @@ static void fw_cfg_reset(DeviceState *d)
    Or we broke compatibility in the state, or we can't use struct tm
  */
 
-static int get_uint32_as_uint16(QEMUFile *f, void *pv, size_t size)
+static int get_uint32_as_uint16(QEMUFile *f, void *pv, size_t size,
+                                VMStateField *field)
 {
     uint32_t *v = pv;
     *v = qemu_get_be16(f);
     return 0;
 }
 
-static void put_unused(QEMUFile *f, void *pv, size_t size)
+static void put_unused(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                       QJSON *vmdesc)
 {
     fprintf(stderr, "uint32_as_uint16 is only used for backward compatibility.\n");
     fprintf(stderr, "This functions shouldn't be called.\n");
diff --git a/hw/pci/msix.c b/hw/pci/msix.c
index 0ec1cb1..69e7a50 100644
--- a/hw/pci/msix.c
+++ b/hw/pci/msix.c
@@ -587,12 +587,14 @@ void msix_unset_vector_notifiers(PCIDevice *dev)
     dev->msix_vector_poll_notifier = NULL;
 }
 
-static void put_msix_state(QEMUFile *f, void *pv, size_t size)
+static void put_msix_state(QEMUFile *f, void *pv, size_t size,
+                           VMStateField *field, QJSON *vmdesc)
 {
     msix_save(pv, f);
 }
 
-static int get_msix_state(QEMUFile *f, void *pv, size_t size)
+static int get_msix_state(QEMUFile *f, void *pv, size_t size,
+                          VMStateField *field)
 {
     msix_load(pv, f);
     return 0;
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 24fae16..08c4547 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -445,7 +445,8 @@ int pci_bus_numa_node(PCIBus *bus)
     return PCI_BUS_GET_CLASS(bus)->numa_node(bus);
 }
 
-static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
+static int get_pci_config_device(QEMUFile *f, void *pv, size_t size,
+                                 VMStateField *field)
 {
     PCIDevice *s = container_of(pv, PCIDevice, config);
     PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(s);
@@ -484,7 +485,8 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 }
 
 /* just put buffer */
-static void put_pci_config_device(QEMUFile *f, void *pv, size_t size)
+static void put_pci_config_device(QEMUFile *f, void *pv, size_t size,
+                                  VMStateField *field, QJSON *vmdesc)
 {
     const uint8_t **v = pv;
     assert(size == pci_config_size(container_of(pv, PCIDevice, config)));
@@ -497,7 +499,8 @@ static VMStateInfo vmstate_info_pci_config = {
     .put  = put_pci_config_device,
 };
 
-static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size)
+static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size,
+                             VMStateField *field)
 {
     PCIDevice *s = container_of(pv, PCIDevice, irq_state);
     uint32_t irq_state[PCI_NUM_PINS];
@@ -518,7 +521,8 @@ static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size)
+static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size,
+                              VMStateField *field, QJSON *vmdesc)
 {
     int i;
     PCIDevice *s = container_of(pv, PCIDevice, irq_state);
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
index 3dcd472..9f82aa6 100644
--- a/hw/pci/shpc.c
+++ b/hw/pci/shpc.c
@@ -695,13 +695,14 @@ void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
     shpc_cap_update_dword(d);
 }
 
-static void shpc_save(QEMUFile *f, void *pv, size_t size)
+static void shpc_save(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                QJSON *vmdesc)
 {
     PCIDevice *d = container_of(pv, PCIDevice, shpc);
     qemu_put_buffer(f, d->shpc->config, SHPC_SIZEOF(d));
 }
 
-static int shpc_load(QEMUFile *f, void *pv, size_t size)
+static int shpc_load(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     PCIDevice *d = container_of(pv, PCIDevice, shpc);
     int ret = qemu_get_buffer(f, d->shpc->config, SHPC_SIZEOF(d));
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 297216d..f40c10b 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -1945,7 +1945,8 @@ SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int id, int lun)
 
 /* SCSI request list.  For simplicity, pv points to the whole device */
 
-static void put_scsi_requests(QEMUFile *f, void *pv, size_t size)
+static void put_scsi_requests(QEMUFile *f, void *pv, size_t size,
+                              VMStateField *field, QJSON *vmdesc)
 {
     SCSIDevice *s = pv;
     SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
@@ -1970,7 +1971,8 @@ static void put_scsi_requests(QEMUFile *f, void *pv, size_t size)
     qemu_put_sbyte(f, 0);
 }
 
-static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
+static int get_scsi_requests(QEMUFile *f, void *pv, size_t size,
+                             VMStateField *field)
 {
     SCSIDevice *s = pv;
     SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
diff --git a/hw/timer/twl92230.c b/hw/timer/twl92230.c
index 7ba4e9a..95eb7f3 100644
--- a/hw/timer/twl92230.c
+++ b/hw/timer/twl92230.c
@@ -747,14 +747,16 @@ static int menelaus_rx(I2CSlave *i2c)
    Or we broke compatibility in the state, or we can't use struct tm
  */
 
-static int get_int32_as_uint16(QEMUFile *f, void *pv, size_t size)
+static int get_int32_as_uint16(QEMUFile *f, void *pv, size_t size,
+                               VMStateField *field)
 {
     int *v = pv;
     *v = qemu_get_be16(f);
     return 0;
 }
 
-static void put_int32_as_uint16(QEMUFile *f, void *pv, size_t size)
+static void put_int32_as_uint16(QEMUFile *f, void *pv, size_t size,
+                                VMStateField *field, QJSON *vmdesc)
 {
     int *v = pv;
     qemu_put_be16(f, *v);
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 444672a..2ca4b46 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -2154,7 +2154,8 @@ static int usbredir_post_load(void *priv, int version_id)
 }
 
 /* For usbredirparser migration */
-static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
+static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused,
+                                void *opaque, QJSON *vmdesc)
 {
     USBRedirDevice *dev = priv;
     uint8_t *data;
@@ -2174,7 +2175,8 @@ static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
     free(data);
 }
 
-static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused)
+static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused,
+                               void *opaque)
 {
     USBRedirDevice *dev = priv;
     uint8_t *data;
@@ -2217,7 +2219,8 @@ static const VMStateInfo usbredir_parser_vmstate_info = {
 
 
 /* For buffered packets (iso/irq) queue migration */
-static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
+static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused,
+                               VMStateField *field, QJSON *vmdesc)
 {
     struct endp_data *endp = priv;
     USBRedirDevice *dev = endp->dev;
@@ -2237,7 +2240,8 @@ static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
     assert(i == endp->bufpq_size);
 }
 
-static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused)
+static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused,
+                              VMStateField *field)
 {
     struct endp_data *endp = priv;
     USBRedirDevice *dev = endp->dev;
@@ -2340,7 +2344,8 @@ static const VMStateDescription usbredir_ep_vmstate = {
 
 
 /* For PacketIdQueue migration */
-static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused)
+static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused,
+                                     VMStateField *field, QJSON *vmdesc)
 {
     struct PacketIdQueue *q = priv;
     USBRedirDevice *dev = q->dev;
@@ -2356,7 +2361,8 @@ static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused)
     assert(remain == 0);
 }
 
-static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused)
+static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused,
+                                    VMStateField *field)
 {
     struct PacketIdQueue *q = priv;
     USBRedirDevice *dev = q->dev;
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 2d60a00..38a7abd 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -108,7 +108,8 @@ static bool virtio_pci_has_extra_state(DeviceState *d)
     return proxy->flags & VIRTIO_PCI_FLAG_MIGRATE_EXTRA;
 }
 
-static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size)
+static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size,
+                                       VMStateField *field)
 {
     VirtIOPCIProxy *proxy = pv;
     int i;
@@ -137,7 +138,8 @@ static void virtio_pci_save_modern_queue_state(VirtIOPCIQueue *vq,
     qemu_put_be32(f, vq->used[1]);
 }
 
-static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size)
+static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size,
+                                        VMStateField *field, QJSON *vmdesc)
 {
     VirtIOPCIProxy *proxy = pv;
     int i;
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 18ce333..ade2683 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1467,7 +1467,8 @@ static const VMStateDescription vmstate_virtio_ringsize = {
     }
 };
 
-static int get_extra_state(QEMUFile *f, void *pv, size_t size)
+static int get_extra_state(QEMUFile *f, void *pv, size_t size,
+                           VMStateField *field)
 {
     VirtIODevice *vdev = pv;
     BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
@@ -1480,7 +1481,8 @@ static int get_extra_state(QEMUFile *f, void *pv, size_t size)
     }
 }
 
-static void put_extra_state(QEMUFile *f, void *pv, size_t size)
+static void put_extra_state(QEMUFile *f, void *pv, size_t size,
+                            VMStateField *field, QJSON *vmdesc)
 {
     VirtIODevice *vdev = pv;
     BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 1638ee5..459dd4a 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -81,11 +81,13 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque);
 
 typedef struct VMStateInfo VMStateInfo;
 typedef struct VMStateDescription VMStateDescription;
+typedef struct VMStateField VMStateField;
 
 struct VMStateInfo {
     const char *name;
-    int (*get)(QEMUFile *f, void *pv, size_t size);
-    void (*put)(QEMUFile *f, void *pv, size_t size);
+    int (*get)(QEMUFile *f, void *pv, size_t size, VMStateField *field);
+    void (*put)(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                QJSON *vmdesc);
 };
 
 enum VMStateFlags {
@@ -186,7 +188,7 @@ enum VMStateFlags {
     VMS_MULTIPLY_ELEMENTS = 0x4000,
 };
 
-typedef struct {
+struct VMStateField {
     const char *name;
     size_t offset;
     size_t size;
@@ -199,7 +201,7 @@ typedef struct {
     const VMStateDescription *vmsd;
     int version_id;
     bool (*field_exists)(void *opaque, int version_id);
-} VMStateField;
+};
 
 struct VMStateDescription {
     const char *name;
diff --git a/migration/savevm.c b/migration/savevm.c
index ef5c3d1..13b53ad 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -220,14 +220,15 @@ void timer_get(QEMUFile *f, QEMUTimer *ts)
  * Not in vmstate.c to not add qemu-timer.c as dependency to vmstate.c
  */
 
-static int get_timer(QEMUFile *f, void *pv, size_t size)
+static int get_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     QEMUTimer *v = pv;
     timer_get(f, v);
     return 0;
 }
 
-static void put_timer(QEMUFile *f, void *pv, size_t size)
+static void put_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                QJSON *vmdesc)
 {
     QEMUTimer *v = pv;
     timer_put(f, v);
diff --git a/migration/vmstate.c b/migration/vmstate.c
index fc29acf..66802cb 100644
--- a/migration/vmstate.c
+++ b/migration/vmstate.c
@@ -122,7 +122,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
                     ret = vmstate_load_state(f, field->vmsd, addr,
                                              field->vmsd->version_id);
                 } else {
-                    ret = field->info->get(f, addr, size);
+                    ret = field->info->get(f, addr, size, NULL);
 
                 }
                 if (ret >= 0) {
@@ -328,7 +328,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
                 if (field->flags & VMS_STRUCT) {
                     vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
                 } else {
-                    field->info->put(f, addr, size);
+                    field->info->put(f, addr, size, NULL, NULL);
                 }
 
                 written_bytes = qemu_ftell_fast(f) - old_offset;
@@ -461,14 +461,15 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
 
 /* bool */
 
-static int get_bool(QEMUFile *f, void *pv, size_t size)
+static int get_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     bool *v = pv;
     *v = qemu_get_byte(f);
     return 0;
 }
 
-static void put_bool(QEMUFile *f, void *pv, size_t size)
+static void put_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                     QJSON *vmdesc)
 {
     bool *v = pv;
     qemu_put_byte(f, *v);
@@ -482,14 +483,15 @@ const VMStateInfo vmstate_info_bool = {
 
 /* 8 bit int */
 
-static int get_int8(QEMUFile *f, void *pv, size_t size)
+static int get_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     int8_t *v = pv;
     qemu_get_s8s(f, v);
     return 0;
 }
 
-static void put_int8(QEMUFile *f, void *pv, size_t size)
+static void put_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                     QJSON *vmdesc)
 {
     int8_t *v = pv;
     qemu_put_s8s(f, v);
@@ -503,14 +505,15 @@ const VMStateInfo vmstate_info_int8 = {
 
 /* 16 bit int */
 
-static int get_int16(QEMUFile *f, void *pv, size_t size)
+static int get_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     int16_t *v = pv;
     qemu_get_sbe16s(f, v);
     return 0;
 }
 
-static void put_int16(QEMUFile *f, void *pv, size_t size)
+static void put_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                      QJSON *vmdesc)
 {
     int16_t *v = pv;
     qemu_put_sbe16s(f, v);
@@ -524,14 +527,15 @@ const VMStateInfo vmstate_info_int16 = {
 
 /* 32 bit int */
 
-static int get_int32(QEMUFile *f, void *pv, size_t size)
+static int get_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     int32_t *v = pv;
     qemu_get_sbe32s(f, v);
     return 0;
 }
 
-static void put_int32(QEMUFile *f, void *pv, size_t size)
+static void put_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                      QJSON *vmdesc)
 {
     int32_t *v = pv;
     qemu_put_sbe32s(f, v);
@@ -546,7 +550,8 @@ const VMStateInfo vmstate_info_int32 = {
 /* 32 bit int. See that the received value is the same than the one
    in the field */
 
-static int get_int32_equal(QEMUFile *f, void *pv, size_t size)
+static int get_int32_equal(QEMUFile *f, void *pv, size_t size,
+                           VMStateField *field)
 {
     int32_t *v = pv;
     int32_t v2;
@@ -568,7 +573,7 @@ const VMStateInfo vmstate_info_int32_equal = {
  * and less than or equal to the one in the field.
  */
 
-static int get_int32_le(QEMUFile *f, void *pv, size_t size)
+static int get_int32_le(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     int32_t *cur = pv;
     int32_t loaded;
@@ -589,14 +594,15 @@ const VMStateInfo vmstate_info_int32_le = {
 
 /* 64 bit int */
 
-static int get_int64(QEMUFile *f, void *pv, size_t size)
+static int get_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     int64_t *v = pv;
     qemu_get_sbe64s(f, v);
     return 0;
 }
 
-static void put_int64(QEMUFile *f, void *pv, size_t size)
+static void put_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                      QJSON *vmdesc)
 {
     int64_t *v = pv;
     qemu_put_sbe64s(f, v);
@@ -610,14 +616,15 @@ const VMStateInfo vmstate_info_int64 = {
 
 /* 8 bit unsigned int */
 
-static int get_uint8(QEMUFile *f, void *pv, size_t size)
+static int get_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     uint8_t *v = pv;
     qemu_get_8s(f, v);
     return 0;
 }
 
-static void put_uint8(QEMUFile *f, void *pv, size_t size)
+static void put_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                      QJSON *vmdesc)
 {
     uint8_t *v = pv;
     qemu_put_8s(f, v);
@@ -631,14 +638,15 @@ const VMStateInfo vmstate_info_uint8 = {
 
 /* 16 bit unsigned int */
 
-static int get_uint16(QEMUFile *f, void *pv, size_t size)
+static int get_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     uint16_t *v = pv;
     qemu_get_be16s(f, v);
     return 0;
 }
 
-static void put_uint16(QEMUFile *f, void *pv, size_t size)
+static void put_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                       QJSON *vmdesc)
 {
     uint16_t *v = pv;
     qemu_put_be16s(f, v);
@@ -652,14 +660,15 @@ const VMStateInfo vmstate_info_uint16 = {
 
 /* 32 bit unsigned int */
 
-static int get_uint32(QEMUFile *f, void *pv, size_t size)
+static int get_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     uint32_t *v = pv;
     qemu_get_be32s(f, v);
     return 0;
 }
 
-static void put_uint32(QEMUFile *f, void *pv, size_t size)
+static void put_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                       QJSON *vmdesc)
 {
     uint32_t *v = pv;
     qemu_put_be32s(f, v);
@@ -674,7 +683,8 @@ const VMStateInfo vmstate_info_uint32 = {
 /* 32 bit uint. See that the received value is the same than the one
    in the field */
 
-static int get_uint32_equal(QEMUFile *f, void *pv, size_t size)
+static int get_uint32_equal(QEMUFile *f, void *pv, size_t size,
+                            VMStateField *field)
 {
     uint32_t *v = pv;
     uint32_t v2;
@@ -694,14 +704,15 @@ const VMStateInfo vmstate_info_uint32_equal = {
 
 /* 64 bit unsigned int */
 
-static int get_uint64(QEMUFile *f, void *pv, size_t size)
+static int get_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     uint64_t *v = pv;
     qemu_get_be64s(f, v);
     return 0;
 }
 
-static void put_uint64(QEMUFile *f, void *pv, size_t size)
+static void put_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                       QJSON *vmdesc)
 {
     uint64_t *v = pv;
     qemu_put_be64s(f, v);
@@ -716,7 +727,8 @@ const VMStateInfo vmstate_info_uint64 = {
 /* 64 bit unsigned int. See that the received value is the same than the one
    in the field */
 
-static int get_uint64_equal(QEMUFile *f, void *pv, size_t size)
+static int get_uint64_equal(QEMUFile *f, void *pv, size_t size,
+                            VMStateField *field)
 {
     uint64_t *v = pv;
     uint64_t v2;
@@ -737,7 +749,8 @@ const VMStateInfo vmstate_info_uint64_equal = {
 /* 8 bit int. See that the received value is the same than the one
    in the field */
 
-static int get_uint8_equal(QEMUFile *f, void *pv, size_t size)
+static int get_uint8_equal(QEMUFile *f, void *pv, size_t size,
+                           VMStateField *field)
 {
     uint8_t *v = pv;
     uint8_t v2;
@@ -758,7 +771,8 @@ const VMStateInfo vmstate_info_uint8_equal = {
 /* 16 bit unsigned int int. See that the received value is the same than the one
    in the field */
 
-static int get_uint16_equal(QEMUFile *f, void *pv, size_t size)
+static int get_uint16_equal(QEMUFile *f, void *pv, size_t size,
+                            VMStateField *field)
 {
     uint16_t *v = pv;
     uint16_t v2;
@@ -778,7 +792,8 @@ const VMStateInfo vmstate_info_uint16_equal = {
 
 /* floating point */
 
-static int get_float64(QEMUFile *f, void *pv, size_t size)
+static int get_float64(QEMUFile *f, void *pv, size_t size,
+                       VMStateField *field)
 {
     float64 *v = pv;
 
@@ -786,7 +801,8 @@ static int get_float64(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_float64(QEMUFile *f, void *pv, size_t size)
+static void put_float64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                        QJSON *vmdesc)
 {
     uint64_t *v = pv;
 
@@ -801,7 +817,8 @@ const VMStateInfo vmstate_info_float64 = {
 
 /* CPU_DoubleU type */
 
-static int get_cpudouble(QEMUFile *f, void *pv, size_t size)
+static int get_cpudouble(QEMUFile *f, void *pv, size_t size,
+                         VMStateField *field)
 {
     CPU_DoubleU *v = pv;
     qemu_get_be32s(f, &v->l.upper);
@@ -809,7 +826,8 @@ static int get_cpudouble(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_cpudouble(QEMUFile *f, void *pv, size_t size)
+static void put_cpudouble(QEMUFile *f, void *pv, size_t size,
+                          VMStateField *field, QJSON *vmdesc)
 {
     CPU_DoubleU *v = pv;
     qemu_put_be32s(f, &v->l.upper);
@@ -824,14 +842,16 @@ const VMStateInfo vmstate_info_cpudouble = {
 
 /* uint8_t buffers */
 
-static int get_buffer(QEMUFile *f, void *pv, size_t size)
+static int get_buffer(QEMUFile *f, void *pv, size_t size,
+                      VMStateField *field)
 {
     uint8_t *v = pv;
     qemu_get_buffer(f, v, size);
     return 0;
 }
 
-static void put_buffer(QEMUFile *f, void *pv, size_t size)
+static void put_buffer(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                       QJSON *vmdesc)
 {
     uint8_t *v = pv;
     qemu_put_buffer(f, v, size);
@@ -846,7 +866,8 @@ const VMStateInfo vmstate_info_buffer = {
 /* unused buffers: space that was used for some fields that are
    not useful anymore */
 
-static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
+static int get_unused_buffer(QEMUFile *f, void *pv, size_t size,
+                             VMStateField *field)
 {
     uint8_t buf[1024];
     int block_len;
@@ -859,7 +880,8 @@ static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
    return 0;
 }
 
-static void put_unused_buffer(QEMUFile *f, void *pv, size_t size)
+static void put_unused_buffer(QEMUFile *f, void *pv, size_t size,
+                              VMStateField *field, QJSON *vmdesc)
 {
     static const uint8_t buf[1024];
     int block_len;
@@ -884,7 +906,7 @@ const VMStateInfo vmstate_info_unused_buffer = {
  */
 /* This is the number of 64 bit words sent over the wire */
 #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
-static int get_bitmap(QEMUFile *f, void *pv, size_t size)
+static int get_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     unsigned long *bmp = pv;
     int i, idx = 0;
@@ -898,7 +920,8 @@ static int get_bitmap(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_bitmap(QEMUFile *f, void *pv, size_t size)
+static void put_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                QJSON *vmdesc)
 {
     unsigned long *bmp = pv;
     int i, idx = 0;
diff --git a/target-alpha/machine.c b/target-alpha/machine.c
index 710b783..48e3278 100644
--- a/target-alpha/machine.c
+++ b/target-alpha/machine.c
@@ -5,14 +5,15 @@
 #include "hw/boards.h"
 #include "migration/cpu.h"
 
-static int get_fpcr(QEMUFile *f, void *opaque, size_t size)
+static int get_fpcr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
 {
     CPUAlphaState *env = opaque;
     cpu_alpha_store_fpcr(env, qemu_get_be64(f));
     return 0;
 }
 
-static void put_fpcr(QEMUFile *f, void *opaque, size_t size)
+static void put_fpcr(QEMUFile *f, void *opaque, size_t size,
+                     VMStateField *field, QJSON *vmdesc)
 {
     CPUAlphaState *env = opaque;
     qemu_put_be64(f, cpu_alpha_load_fpcr(env));
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 7a6ca31..41a0de9 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -17,7 +17,8 @@ static bool vfp_needed(void *opaque)
     return arm_feature(env, ARM_FEATURE_VFP);
 }
 
-static int get_fpscr(QEMUFile *f, void *opaque, size_t size)
+static int get_fpscr(QEMUFile *f, void *opaque, size_t size,
+                     VMStateField *field)
 {
     ARMCPU *cpu = opaque;
     CPUARMState *env = &cpu->env;
@@ -27,7 +28,8 @@ static int get_fpscr(QEMUFile *f, void *opaque, size_t size)
     return 0;
 }
 
-static void put_fpscr(QEMUFile *f, void *opaque, size_t size)
+static void put_fpscr(QEMUFile *f, void *opaque, size_t size,
+                      VMStateField *field, QJSON *vmdesc)
 {
     ARMCPU *cpu = opaque;
     CPUARMState *env = &cpu->env;
@@ -163,7 +165,8 @@ static const VMStateDescription vmstate_pmsav7 = {
     }
 };
 
-static int get_cpsr(QEMUFile *f, void *opaque, size_t size)
+static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
+                    VMStateField *field)
 {
     ARMCPU *cpu = opaque;
     CPUARMState *env = &cpu->env;
@@ -180,7 +183,8 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size)
     return 0;
 }
 
-static void put_cpsr(QEMUFile *f, void *opaque, size_t size)
+static void put_cpsr(QEMUFile *f, void *opaque, size_t size,
+                     VMStateField *field, QJSON *vmdesc)
 {
     ARMCPU *cpu = opaque;
     CPUARMState *env = &cpu->env;
diff --git a/target-i386/machine.c b/target-i386/machine.c
index 71c0e4d..1df19e2 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -139,7 +139,8 @@ static const VMStateDescription vmstate_mtrr_var = {
 #define VMSTATE_MTRR_VARS(_field, _state, _n, _v)                    \
     VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar)
 
-static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size)
+static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size,
+                            VMStateField *field, QJSON *vmdesc)
 {
     fprintf(stderr, "call put_fpreg() with invalid arguments\n");
     exit(0);
@@ -167,7 +168,8 @@ static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
     p->exp = e;
 }
 
-static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
+static int get_fpreg(QEMUFile *f, void *opaque, size_t size,
+                     VMStateField *field)
 {
     FPReg *fp_reg = opaque;
     uint64_t mant;
@@ -179,7 +181,8 @@ static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
     return 0;
 }
 
-static void put_fpreg(QEMUFile *f, void *opaque, size_t size)
+static void put_fpreg(QEMUFile *f, void *opaque, size_t size,
+                      VMStateField *field, QJSON *vmdesc)
 {
     FPReg *fp_reg = opaque;
     uint64_t mant;
@@ -197,7 +200,8 @@ static const VMStateInfo vmstate_fpreg = {
     .put  = put_fpreg,
 };
 
-static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size)
+static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size,
+                           VMStateField *field)
 {
     union x86_longdouble *p = opaque;
     uint64_t mant;
@@ -214,7 +218,8 @@ static const VMStateInfo vmstate_fpreg_1_mmx = {
     .put  = put_fpreg_error,
 };
 
-static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size)
+static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size,
+                              VMStateField *field)
 {
     union x86_longdouble *p = opaque;
     uint64_t mant;
@@ -276,14 +281,16 @@ static bool less_than_7(void *opaque, int version_id)
     return version_id < 7;
 }
 
-static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
+static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size,
+                                VMStateField *field)
 {
     uint64_t *v = pv;
     *v = qemu_get_be32(f);
     return 0;
 }
 
-static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
+static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size,
+                                 VMStateField *field, QJSON *vmdesc)
 {
     uint64_t *v = pv;
     qemu_put_be32(f, *v);
diff --git a/target-mips/machine.c b/target-mips/machine.c
index a27f2f1..179084c 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -20,7 +20,7 @@ static int cpu_post_load(void *opaque, int version_id)
 
 /* FPU state */
 
-static int get_fpr(QEMUFile *f, void *pv, size_t size)
+static int get_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     int i;
     fpr_t *v = pv;
@@ -31,7 +31,8 @@ static int get_fpr(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_fpr(QEMUFile *f, void *pv, size_t size)
+static void put_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                    QJSON *vmdesc)
 {
     int i;
     fpr_t *v = pv;
@@ -125,7 +126,7 @@ const VMStateDescription vmstate_mvp = {
 
 /* TLB state */
 
-static int get_tlb(QEMUFile *f, void *pv, size_t size)
+static int get_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     r4k_tlb_t *v = pv;
     uint16_t flags;
@@ -152,7 +153,8 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_tlb(QEMUFile *f, void *pv, size_t size)
+static void put_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                    QJSON *vmdesc)
 {
     r4k_tlb_t *v = pv;
 
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index 4820f22..0e1822c 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -106,7 +106,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static int get_avr(QEMUFile *f, void *pv, size_t size)
+static int get_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     ppc_avr_t *v = pv;
 
@@ -116,7 +116,8 @@ static int get_avr(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_avr(QEMUFile *f, void *pv, size_t size)
+static void put_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                    QJSON *vmdesc)
 {
     ppc_avr_t *v = pv;
 
@@ -324,7 +325,7 @@ static const VMStateDescription vmstate_sr = {
 };
 
 #ifdef TARGET_PPC64
-static int get_slbe(QEMUFile *f, void *pv, size_t size)
+static int get_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field)
 {
     ppc_slb_t *v = pv;
 
@@ -334,7 +335,8 @@ static int get_slbe(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_slbe(QEMUFile *f, void *pv, size_t size)
+static void put_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field,
+                     QJSON *vmdesc)
 {
     ppc_slb_t *v = pv;
 
diff --git a/target-sparc/machine.c b/target-sparc/machine.c
index 59c92f7..3194e03 100644
--- a/target-sparc/machine.c
+++ b/target-sparc/machine.c
@@ -59,7 +59,7 @@ static const VMStateDescription vmstate_tlb_entry = {
 };
 #endif
 
-static int get_psr(QEMUFile *f, void *opaque, size_t size)
+static int get_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
 {
     SPARCCPU *cpu = opaque;
     CPUSPARCState *env = &cpu->env;
@@ -72,7 +72,8 @@ static int get_psr(QEMUFile *f, void *opaque, size_t size)
     return 0;
 }
 
-static void put_psr(QEMUFile *f, void *opaque, size_t size)
+static void put_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field,
+                QJSON *vmdesc)
 {
     SPARCCPU *cpu = opaque;
     CPUSPARCState *env = &cpu->env;
-- 
1.9.1

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

* [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-03 18:24 [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together Jianjun Duan
                   ` (2 preceding siblings ...)
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 3/6] migration: extend VMStateInfo Jianjun Duan
@ 2016-10-03 18:24 ` Jianjun Duan
  2016-10-05 16:56   ` Dr. David Alan Gilbert
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 5/6] migration: spapr: migrate ccs_list in spapr state Jianjun Duan
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 66+ messages in thread
From: Jianjun Duan @ 2016-10-03 18:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-ppc, duanj, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth,
	dgilbert

Currently we cannot directly transfer a QTAILQ instance because of the
limitation in the migration code. Here we introduce an approach to
transfer such structures. In our approach such a structure is tagged
with VMS_LINKED. We then modified vmstate_save_state and vmstate_load_state
so that when VMS_LINKED is encountered, put and get from VMStateInfo are
called respectively. We created VMStateInfo vmstate_info_qtailq for QTAILQ.
Similar VMStateInfo can be created for other data structures such as list.
This approach will be used to transfer pending_events and ccs_list in spapr
state.

We also create some macros in qemu/queue.h to access a QTAILQ using pointer
arithmetic. This ensures that we do not depend on the implementation
details about QTAILQ in the migration code.

Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
---
 include/migration/vmstate.h | 26 ++++++++++++++++++
 include/qemu/queue.h        | 32 ++++++++++++++++++++++
 migration/trace-events      |  4 +++
 migration/vmstate.c         | 66 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 128 insertions(+)

diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 459dd4a..e60c994 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -186,6 +186,12 @@ enum VMStateFlags {
      * to determine the number of entries in the array. Only valid in
      * combination with one of VMS_VARRAY*. */
     VMS_MULTIPLY_ELEMENTS = 0x4000,
+    /* For fields which need customized handling, such as QTAILQ in queue.h.
+     * When this flag is set in VMStateField, info->get/put will
+     * be used in vmstate_load/save_state instead of recursive call.
+     * User should implement set info to handle the concerned data structure.
+     */
+    VMS_LINKED            = 0x8000,
 };
 
 struct VMStateField {
@@ -246,6 +252,7 @@ extern const VMStateInfo vmstate_info_timer;
 extern const VMStateInfo vmstate_info_buffer;
 extern const VMStateInfo vmstate_info_unused_buffer;
 extern const VMStateInfo vmstate_info_bitmap;
+extern const VMStateInfo vmstate_info_qtailq;
 
 #define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0)
 #define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0)
@@ -657,6 +664,25 @@ extern const VMStateInfo vmstate_info_bitmap;
     .offset       = offsetof(_state, _field),                        \
 }
 
+/* For QTAILQ that need customized handling
+ * _type: type of QTAILQ element
+ * _next: name of QTAILQ entry field in QTAILQ element
+ * _vmsd: VMSD for QTAILQ element
+ * size: size of QTAILQ element
+ * start: offset of QTAILQ entry in QTAILQ element
+ */
+#define VMSTATE_QTAILQ_V(_field, _state, _version, _vmsd, _type, _next)  \
+{                                                                        \
+    .name         = (stringify(_field)),                                 \
+    .version_id   = (_version),                                          \
+    .vmsd         = &(_vmsd),                                            \
+    .size         = sizeof(_type),                                       \
+    .info         = &vmstate_info_qtailq,                                \
+    .flags        = VMS_LINKED,                                          \
+    .offset       = offsetof(_state, _field),                            \
+    .start        = offsetof(_type, _next),                              \
+}
+
 /* _f : field name
    _f_n : num of elements field_name
    _n : num of elements
diff --git a/include/qemu/queue.h b/include/qemu/queue.h
index 342073f..12c3f80 100644
--- a/include/qemu/queue.h
+++ b/include/qemu/queue.h
@@ -438,4 +438,36 @@ struct {                                                                \
 #define QTAILQ_PREV(elm, headname, field) \
         (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
 
+/*
+ * Offsets of layout of a tail queue head.
+ */
+#define QTAILQ_FIRST_OFFSET 0
+#define QTAILQ_LAST_OFFSET (sizeof(void *))
+
+/*
+ * Offsets of layout of a tail queue element.
+ */
+#define QTAILQ_NEXT_OFFSET 0
+#define QTAILQ_PREV_OFFSET (sizeof(void *))
+
+/*
+ * Tail queue tranversal using pointer arithmetic.
+ */
+#define QTAILQ_RAW_FOREACH(elm, head, entry)                                   \
+        for ((elm) = *((void **) ((char *) (head) + QTAILQ_FIRST_OFFSET));     \
+             (elm);                                                            \
+             (elm) =                                                           \
+                 *((void **) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET)))
+/*
+ * Tail queue insertion using pointer arithmetic.
+ */
+#define QTAILQ_RAW_INSERT_TAIL(head, elm, entry) do {                          \
+        *((void **) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET)) = NULL;   \
+        *((void **) ((char *) (elm) + (entry) + QTAILQ_PREV_OFFSET)) =         \
+            *((void **) ((char *) (head) +QTAILQ_LAST_OFFSET));                \
+        **((void ***)((char *) (head) +QTAILQ_LAST_OFFSET)) = (elm);           \
+        *((void **) ((char *) (head) + QTAILQ_LAST_OFFSET)) =                  \
+            (void *) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET);          \
+} while (/*CONSTCOND*/0)
+
 #endif /* QEMU_SYS_QUEUE_H */
diff --git a/migration/trace-events b/migration/trace-events
index dfee75a..9a6ec59 100644
--- a/migration/trace-events
+++ b/migration/trace-events
@@ -52,6 +52,10 @@ vmstate_n_elems(const char *name, int n_elems) "%s: %d"
 vmstate_subsection_load(const char *parent) "%s"
 vmstate_subsection_load_bad(const char *parent,  const char *sub, const char *sub2) "%s: %s/%s"
 vmstate_subsection_load_good(const char *parent) "%s"
+get_qtailq(const char *name, int version_id) "%s v%d"
+get_qtailq_end(const char *name, const char *reason, int val) "%s %s/%d"
+put_qtailq(const char *name, int version_id) "%s v%d"
+put_qtailq_end(const char *name, const char *reason) "%s %s"
 
 # migration/qemu-file.c
 qemu_file_fclose(void) ""
diff --git a/migration/vmstate.c b/migration/vmstate.c
index 66802cb..192db8a 100644
--- a/migration/vmstate.c
+++ b/migration/vmstate.c
@@ -5,7 +5,9 @@
 #include "migration/vmstate.h"
 #include "qemu/bitops.h"
 #include "qemu/error-report.h"
+#include "qemu/queue.h"
 #include "trace.h"
+#include "migration/qjson.h"
 
 static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
                                     void *opaque, QJSON *vmdesc);
@@ -121,6 +123,8 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
                 if (field->flags & VMS_STRUCT) {
                     ret = vmstate_load_state(f, field->vmsd, addr,
                                              field->vmsd->version_id);
+                } else if (field->flags & VMS_LINKED) {
+                    ret = field->info->get(f, addr, size, field);
                 } else {
                     ret = field->info->get(f, addr, size, NULL);
 
@@ -193,6 +197,8 @@ static const char *vmfield_get_type_name(VMStateField *field)
 
     if (field->flags & VMS_STRUCT) {
         type = "struct";
+    } else if (field->flags & VMS_LINKED) {
+        type = "linked";
     } else if (field->info->name) {
         type = field->info->name;
     }
@@ -327,6 +333,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
                 }
                 if (field->flags & VMS_STRUCT) {
                     vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
+                } else if  (field->flags & VMS_LINKED) {
+                    field->info->put(f, addr, size, field, vmdesc_loop);
                 } else {
                     field->info->put(f, addr, size, NULL, NULL);
                 }
@@ -939,3 +947,61 @@ const VMStateInfo vmstate_info_bitmap = {
     .get = get_bitmap,
     .put = put_bitmap,
 };
+
+/*get for QTAILQ */
+static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
+                      VMStateField *field)
+{
+    int ret = 0;
+    const VMStateDescription *vmsd = field->vmsd;
+    size_t size = field->size;
+    size_t entry = field->start;
+    int version_id = field->version_id;
+    void *elm;
+
+    trace_get_qtailq(vmsd->name, version_id);
+    if (version_id > vmsd->version_id) {
+        trace_get_qtailq_end(vmsd->name, "too new", -EINVAL);
+        return -EINVAL;
+    }
+    if (version_id < vmsd->minimum_version_id) {
+        trace_get_qtailq_end(vmsd->name, "too old", -EINVAL);
+        return -EINVAL;
+    }
+
+    while (qemu_get_byte(f)) {
+        elm =  g_malloc(size);
+        ret = vmstate_load_state(f, vmsd, elm, version_id);
+        if (ret) {
+            return ret;
+        }
+        QTAILQ_RAW_INSERT_TAIL(pv, elm, entry);
+    }
+
+    trace_get_qtailq_end(vmsd->name, "end", ret);
+    return ret;
+}
+
+/* put for QTAILQ */
+static void put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
+                       VMStateField *field, QJSON *vmdesc)
+{
+    const VMStateDescription *vmsd = field->vmsd;
+    size_t entry = field->start;
+    void *elm;
+
+    trace_put_qtailq(vmsd->name, vmsd->version_id);
+
+    QTAILQ_RAW_FOREACH(elm, pv, entry) {
+        qemu_put_byte(f, true);
+        vmstate_save_state(f, vmsd, elm, vmdesc);
+    }
+    qemu_put_byte(f, false);
+
+    trace_put_qtailq_end(vmsd->name, "end");
+}
+const VMStateInfo vmstate_info_qtailq = {
+    .name = "qtailq",
+    .get  = get_qtailq,
+    .put  = put_qtailq,
+};
-- 
1.9.1

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

* [Qemu-devel] [QEMU PATCH v5 5/6] migration: spapr: migrate ccs_list in spapr state
  2016-10-03 18:24 [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together Jianjun Duan
                   ` (3 preceding siblings ...)
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ Jianjun Duan
@ 2016-10-03 18:24 ` Jianjun Duan
  2016-10-07  3:36   ` David Gibson
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 6/6] migration: spapr: migrate pending_events of " Jianjun Duan
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 66+ messages in thread
From: Jianjun Duan @ 2016-10-03 18:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-ppc, duanj, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth,
	dgilbert

ccs_list in spapr state maintains the device tree related
information on the rtas side for hotplugged devices. In racing
situations between hotplug events and migration operation, a rtas
hotplug event could be migrated from the source guest to target
guest, or the source guest could have not yet finished fetching
the device tree when migration is started, the target will try
to finish fetching the device tree. By migrating ccs_list, the
target can fetch the device tree properly.

ccs_list is put in a subsection in the spapr state VMSD to make
sure migration across different versions is not broken.

Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
---
 hw/ppc/spapr.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 63b6a0d..1847d35 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1255,6 +1255,36 @@ static bool version_before_3(void *opaque, int version_id)
     return version_id < 3;
 }
 
+static bool spapr_ccs_list_needed(void *opaque)
+{
+    sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
+    return !QTAILQ_EMPTY(&spapr->ccs_list);
+}
+
+static const VMStateDescription vmstate_spapr_ccs = {
+    .name = "spaprconfigureconnectorstate",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(drc_index, sPAPRConfigureConnectorState),
+        VMSTATE_INT32(fdt_offset, sPAPRConfigureConnectorState),
+        VMSTATE_INT32(fdt_depth, sPAPRConfigureConnectorState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
+static const VMStateDescription vmstate_spapr_ccs_list = {
+    .name = "spaprccslist",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = spapr_ccs_list_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_QTAILQ_V(ccs_list, sPAPRMachineState, 1,
+                         vmstate_spapr_ccs, sPAPRConfigureConnectorState, next),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
 static const VMStateDescription vmstate_spapr = {
     .name = "spapr",
     .version_id = 3,
@@ -1270,6 +1300,10 @@ static const VMStateDescription vmstate_spapr = {
         VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2),
         VMSTATE_END_OF_LIST()
     },
+    .subsections = (const VMStateDescription*[]) {
+        &vmstate_spapr_ccs_list,
+        NULL
+    }
 };
 
 static int htab_save_setup(QEMUFile *f, void *opaque)
-- 
1.9.1

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

* [Qemu-devel] [QEMU PATCH v5 6/6] migration: spapr: migrate pending_events of spapr state
  2016-10-03 18:24 [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together Jianjun Duan
                   ` (4 preceding siblings ...)
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 5/6] migration: spapr: migrate ccs_list in spapr state Jianjun Duan
@ 2016-10-03 18:24 ` Jianjun Duan
  2016-10-03 18:35 ` [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together no-reply
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 66+ messages in thread
From: Jianjun Duan @ 2016-10-03 18:24 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-ppc, duanj, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth,
	dgilbert

In racing situations between hotplug events and migration operation,
a rtas hotplug event could have not yet be delivered to the source
guest when migration is started. In this case the pending_events of
spapr state need be transmitted to the target so that the hotplug
event can be finished on the target.

All the different fields of the events are encoded as defined by
PAPR. We can migrate them as uint8_t binary stream without any
concerns about data padding or endianess.

pending_events is put in a subsection in the spapr state VMSD to make
sure migration across different versions is not broken.

Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
---
 hw/ppc/spapr.c         | 33 +++++++++++++++++++++++++++++++++
 hw/ppc/spapr_events.c  | 22 +++++++++++++---------
 include/hw/ppc/spapr.h |  3 ++-
 3 files changed, 48 insertions(+), 10 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 1847d35..5b57e5a 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1255,12 +1255,32 @@ static bool version_before_3(void *opaque, int version_id)
     return version_id < 3;
 }
 
+static bool spapr_pending_events_needed(void *opaque)
+{
+    sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
+    return !QTAILQ_EMPTY(&spapr->pending_events);
+}
+
 static bool spapr_ccs_list_needed(void *opaque)
 {
     sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
     return !QTAILQ_EMPTY(&spapr->ccs_list);
 }
 
+static const VMStateDescription vmstate_spapr_event_entry = {
+    .name = "spapreventlogentry",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_INT32(log_type, sPAPREventLogEntry),
+        VMSTATE_BOOL(exception, sPAPREventLogEntry),
+        VMSTATE_UINT32(data_size, sPAPREventLogEntry),
+        VMSTATE_VARRAY_UINT32_ALLOC(data, sPAPREventLogEntry, data_size,
+                                    0, vmstate_info_uint8, uint8_t),
+        VMSTATE_END_OF_LIST()
+  },
+};
+
 static const VMStateDescription vmstate_spapr_ccs = {
     .name = "spaprconfigureconnectorstate",
     .version_id = 1,
@@ -1273,6 +1293,18 @@ static const VMStateDescription vmstate_spapr_ccs = {
     },
 };
 
+static const VMStateDescription vmstate_spapr_pending_events = {
+    .name = "spaprpendingevents",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = spapr_pending_events_needed,
+    .fields = (VMStateField[]) {
+        VMSTATE_QTAILQ_V(pending_events, sPAPRMachineState, 1,
+                         vmstate_spapr_event_entry, sPAPREventLogEntry, next),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
 static const VMStateDescription vmstate_spapr_ccs_list = {
     .name = "spaprccslist",
     .version_id = 1,
@@ -1301,6 +1333,7 @@ static const VMStateDescription vmstate_spapr = {
         VMSTATE_END_OF_LIST()
     },
     .subsections = (const VMStateDescription*[]) {
+        &vmstate_spapr_pending_events,
         &vmstate_spapr_ccs_list,
         NULL
     }
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index 4c7b6ae..3f45744 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -230,7 +230,8 @@ void spapr_events_fdt_skel(void *fdt, uint32_t check_exception_irq)
     _FDT((fdt_end_node(fdt)));
 }
 
-static void rtas_event_log_queue(int log_type, void *data, bool exception)
+static void rtas_event_log_queue(int log_type, void *data, bool exception,
+				 int data_size)
 {
     sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
     sPAPREventLogEntry *entry = g_new(sPAPREventLogEntry, 1);
@@ -239,6 +240,7 @@ static void rtas_event_log_queue(int log_type, void *data, bool exception)
     entry->log_type = log_type;
     entry->exception = exception;
     entry->data = data;
+    entry->data_size = data_size;
     QTAILQ_INSERT_TAIL(&spapr->pending_events, entry, next);
 }
 
@@ -341,6 +343,7 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
     struct rtas_event_log_v6_mainb *mainb;
     struct rtas_event_log_v6_epow *epow;
     struct epow_log_full *new_epow;
+    uint32_t data_size;
 
     new_epow = g_malloc0(sizeof(*new_epow));
     hdr = &new_epow->hdr;
@@ -349,13 +352,13 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
     mainb = &new_epow->mainb;
     epow = &new_epow->epow;
 
+    data_size = sizeof(*new_epow);
     hdr->summary = cpu_to_be32(RTAS_LOG_VERSION_6
                                | RTAS_LOG_SEVERITY_EVENT
                                | RTAS_LOG_DISPOSITION_NOT_RECOVERED
                                | RTAS_LOG_OPTIONAL_PART_PRESENT
                                | RTAS_LOG_TYPE_EPOW);
-    hdr->extended_length = cpu_to_be32(sizeof(*new_epow)
-                                       - sizeof(new_epow->hdr));
+    hdr->extended_length = cpu_to_be32(data_size - sizeof(new_epow->hdr));
 
     spapr_init_v6hdr(v6hdr);
     spapr_init_maina(maina, 3 /* Main-A, Main-B and EPOW */);
@@ -375,7 +378,7 @@ static void spapr_powerdown_req(Notifier *n, void *opaque)
     epow->event_modifier = RTAS_LOG_V6_EPOW_MODIFIER_NORMAL;
     epow->extended_modifier = RTAS_LOG_V6_EPOW_XMODIFIER_PARTITION_SPECIFIC;
 
-    rtas_event_log_queue(RTAS_LOG_TYPE_EPOW, new_epow, true);
+    rtas_event_log_queue(RTAS_LOG_TYPE_EPOW, new_epow, true, data_size);
 
     qemu_irq_pulse(xics_get_qirq(spapr->xics, spapr->check_exception_irq));
 }
@@ -398,6 +401,7 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
     struct rtas_event_log_v6_maina *maina;
     struct rtas_event_log_v6_mainb *mainb;
     struct rtas_event_log_v6_hp *hp;
+    uint32_t data_size;
 
     new_hp = g_malloc0(sizeof(struct hp_log_full));
     hdr = &new_hp->hdr;
@@ -406,14 +410,14 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
     mainb = &new_hp->mainb;
     hp = &new_hp->hp;
 
+    data_size = sizeof(*new_hp);
     hdr->summary = cpu_to_be32(RTAS_LOG_VERSION_6
                                | RTAS_LOG_SEVERITY_EVENT
                                | RTAS_LOG_DISPOSITION_NOT_RECOVERED
                                | RTAS_LOG_OPTIONAL_PART_PRESENT
                                | RTAS_LOG_INITIATOR_HOTPLUG
                                | RTAS_LOG_TYPE_HOTPLUG);
-    hdr->extended_length = cpu_to_be32(sizeof(*new_hp)
-                                       - sizeof(new_hp->hdr));
+    hdr->extended_length = cpu_to_be32(data_size - sizeof(new_hp->hdr));
 
     spapr_init_v6hdr(v6hdr);
     spapr_init_maina(maina, 3 /* Main-A, Main-B, HP */);
@@ -457,7 +461,7 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
         hp->drc.index = cpu_to_be32(drc);
     }
 
-    rtas_event_log_queue(RTAS_LOG_TYPE_HOTPLUG, new_hp, true);
+    rtas_event_log_queue(RTAS_LOG_TYPE_HOTPLUG, new_hp, true, data_size);
 
     qemu_irq_pulse(xics_get_qirq(spapr->xics, spapr->check_exception_irq));
 }
@@ -524,7 +528,7 @@ static void check_exception(PowerPCCPU *cpu, sPAPRMachineState *spapr,
         goto out_no_events;
     }
 
-    hdr = event->data;
+    hdr = (struct rtas_error_log *)event->data;
     event_len = be32_to_cpu(hdr->extended_length) + sizeof(*hdr);
 
     if (event_len < len) {
@@ -574,7 +578,7 @@ static void event_scan(PowerPCCPU *cpu, sPAPRMachineState *spapr,
         goto out_no_events;
     }
 
-    hdr = event->data;
+    hdr = (struct rtas_error_log *)event->data;
     event_len = be32_to_cpu(hdr->extended_length) + sizeof(*hdr);
 
     if (event_len < len) {
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 6289d50..8772f9d 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -568,7 +568,8 @@ sPAPRTCETable *spapr_tce_find_by_liobn(target_ulong liobn);
 struct sPAPREventLogEntry {
     int log_type;
     bool exception;
-    void *data;
+    uint32_t data_size;
+    uint8_t *data;
     QTAILQ_ENTRY(sPAPREventLogEntry) next;
 };
 
-- 
1.9.1

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

* Re: [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together
  2016-10-03 18:24 [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together Jianjun Duan
                   ` (5 preceding siblings ...)
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 6/6] migration: spapr: migrate pending_events of " Jianjun Duan
@ 2016-10-03 18:35 ` no-reply
  2016-10-03 19:00 ` no-reply
  2016-10-03 19:11 ` Jianjun Duan
  8 siblings, 0 replies; 66+ messages in thread
From: no-reply @ 2016-10-03 18:35 UTC (permalink / raw)
  To: duanj
  Cc: famz, qemu-devel, veroniabahaa, peter.maydell, dgilbert, mst,
	quintela, mark.cave-ayland, mdroth, mreitz, blauwirbel,
	amit.shah, qemu-ppc, kraxel, kwolf, dmitry, pbonzini, rth,
	leon.alrae, aurelien, david

Hi,

Your series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 1475519097-27611-1-git-send-email-duanj@linux.vnet.ibm.com
Subject: [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

# Useful git options
git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
    echo "Checking PATCH $n/$total: $(git show --no-patch --format=%s $c)..."
    if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
        failed=1
        echo
    fi
    n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]         patchew/1475519097-27611-1-git-send-email-duanj@linux.vnet.ibm.com -> patchew/1475519097-27611-1-git-send-email-duanj@linux.vnet.ibm.com
Switched to a new branch 'test'
d935e1f migration: spapr: migrate pending_events of spapr state
64aa229 migration: spapr: migrate ccs_list in spapr state
ecf2d6c migration: migrate QTAILQ
6f641b8 migration: extend VMStateInfo
803e704 migration: spapr_drc: defined VMStateDescription struct
08b0c64 migration: alternative way to set instance_id in SaveStateEntry

=== OUTPUT BEGIN ===
Checking PATCH 1/6: migration: alternative way to set instance_id in SaveStateEntry...
Checking PATCH 2/6: migration: spapr_drc: defined VMStateDescription struct...
ERROR: space required before the open parenthesis '('
#69: FILE: hw/ppc/spapr_drc.c:634:
+    switch(drc->type) {

total: 1 errors, 0 warnings, 135 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 3/6: migration: extend VMStateInfo...
Checking PATCH 4/6: migration: migrate QTAILQ...
ERROR: spaces required around that '+' (ctx:WxV)
#108: FILE: include/qemu/queue.h:467:
+            *((void **) ((char *) (head) +QTAILQ_LAST_OFFSET));                \
                                          ^

ERROR: spaces required around that '+' (ctx:WxV)
#109: FILE: include/qemu/queue.h:468:
+        **((void ***)((char *) (head) +QTAILQ_LAST_OFFSET)) = (elm);           \
                                       ^

total: 2 errors, 0 warnings, 184 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 5/6: migration: spapr: migrate ccs_list in spapr state...
ERROR: spaces required around that '*' (ctx:VxV)
#66: FILE: hw/ppc/spapr.c:1287:
+    .subsections = (const VMStateDescription*[]) {
                                             ^

total: 1 errors, 0 warnings, 46 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 6/6: migration: spapr: migrate pending_events of spapr state...
ERROR: code indent should never use tabs
#96: FILE: hw/ppc/spapr_events.c:234:
+^I^I^I^I int data_size)$

total: 1 errors, 0 warnings, 159 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

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

* Re: [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together
  2016-10-03 18:24 [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together Jianjun Duan
                   ` (6 preceding siblings ...)
  2016-10-03 18:35 ` [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together no-reply
@ 2016-10-03 19:00 ` no-reply
  2016-10-03 19:11 ` Jianjun Duan
  8 siblings, 0 replies; 66+ messages in thread
From: no-reply @ 2016-10-03 19:00 UTC (permalink / raw)
  To: duanj
  Cc: famz, qemu-devel, veroniabahaa, peter.maydell, dgilbert, mst,
	quintela, mark.cave-ayland, mdroth, mreitz, blauwirbel,
	amit.shah, qemu-ppc, kraxel, kwolf, dmitry, pbonzini, rth,
	leon.alrae, aurelien, david

Hi,

Your series failed automatic build test. Please find the testing commands and
their output below. If you have docker installed, you can probably reproduce it
locally.

Type: series
Message-id: 1475519097-27611-1-git-send-email-duanj@linux.vnet.ibm.com
Subject: [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together

=== TEST SCRIPT BEGIN ===
#!/bin/bash
set -e
git submodule update --init dtc
# Let docker tests dump environment info
export SHOW_ENV=1
make J=8 docker-test-quick@centos6
make J=8 docker-test-mingw@fedora
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
d935e1f migration: spapr: migrate pending_events of spapr state
64aa229 migration: spapr: migrate ccs_list in spapr state
ecf2d6c migration: migrate QTAILQ
6f641b8 migration: extend VMStateInfo
803e704 migration: spapr_drc: defined VMStateDescription struct
08b0c64 migration: alternative way to set instance_id in SaveStateEntry

=== OUTPUT BEGIN ===
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into 'dtc'...
Submodule path 'dtc': checked out '65cc4d2748a2c2e6f27f1cf39e07a5dbabd80ebf'
  BUILD centos6
  ARCHIVE qemu.tgz
  ARCHIVE dtc.tgz
  COPY RUNNER
  RUN test-quick in centos6
Packages installed:
SDL-devel-1.2.14-7.el6_7.1.x86_64
ccache-3.1.6-2.el6.x86_64
epel-release-6-8.noarch
gcc-4.4.7-17.el6.x86_64
git-1.7.1-4.el6_7.1.x86_64
glib2-devel-2.28.8-5.el6.x86_64
libfdt-devel-1.4.0-1.el6.x86_64
make-3.81-23.el6.x86_64
package g++ is not installed
pixman-devel-0.32.8-1.el6.x86_64
tar-1.23-15.el6_8.x86_64
zlib-devel-1.2.3-29.el6.x86_64

Environment variables:
PACKAGES=libfdt-devel ccache     tar git make gcc g++     zlib-devel glib2-devel SDL-devel pixman-devel     epel-release
HOSTNAME=cb3993c582fb
TERM=xterm
MAKEFLAGS= -j8
HISTSIZE=1000
J=8
USER=root
CCACHE_DIR=/var/tmp/ccache
EXTRA_CONFIGURE_OPTS=
V=
SHOW_ENV=1
MAIL=/var/spool/mail/root
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
LANG=en_US.UTF-8
TARGET_LIST=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
TEST_DIR=/tmp/qemu-test
LOGNAME=root
LESSOPEN=||/usr/bin/lesspipe.sh %s
FEATURES= dtc
DEBUG=
G_BROKEN_FILENAMES=1
CCACHE_HASHDIR=
_=/usr/bin/env

Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/tmp/qemu-test/src/tests/docker/install
No C++ compiler available; disabling C++ specific optional code
Install prefix    /tmp/qemu-test/src/tests/docker/install
BIOS directory    /tmp/qemu-test/src/tests/docker/install/share/qemu
binary directory  /tmp/qemu-test/src/tests/docker/install/bin
library directory /tmp/qemu-test/src/tests/docker/install/lib
module directory  /tmp/qemu-test/src/tests/docker/install/lib/qemu
libexec directory /tmp/qemu-test/src/tests/docker/install/libexec
include directory /tmp/qemu-test/src/tests/docker/install/include
config directory  /tmp/qemu-test/src/tests/docker/install/etc
local state directory   /tmp/qemu-test/src/tests/docker/install/var
Manual directory  /tmp/qemu-test/src/tests/docker/install/share/man
ELF interp prefix /usr/gnemul/qemu-%M
Source path       /tmp/qemu-test/src
C compiler        cc
Host C compiler   cc
C++ compiler      
Objective-C compiler cc
ARFLAGS           rv
CFLAGS            -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g 
QEMU_CFLAGS       -I/usr/include/pixman-1    -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include   -fPIE -DPIE -m64 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv  -Wendif-labels -Wmissing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-all
LDFLAGS           -Wl,--warn-common -Wl,-z,relro -Wl,-z,now -pie -m64 -g 
make              make
install           install
python            python -B
smbd              /usr/sbin/smbd
module support    no
host CPU          x86_64
host big endian   no
target list       x86_64-softmmu aarch64-softmmu
tcg debug enabled no
gprof enabled     no
sparse enabled    no
strip binaries    yes
profiler          no
static build      no
pixman            system
SDL support       yes (1.2.14)
GTK support       no 
GTK GL support    no
VTE support       no 
TLS priority      NORMAL
GNUTLS support    no
GNUTLS rnd        no
libgcrypt         no
libgcrypt kdf     no
nettle            no 
nettle kdf        no
libtasn1          no
curses support    no
virgl support     no
curl support      no
mingw32 support   no
Audio drivers     oss
Block whitelist (rw) 
Block whitelist (ro) 
VirtFS support    no
VNC support       yes
VNC SASL support  no
VNC JPEG support  no
VNC PNG support   no
xen support       no
brlapi support    no
bluez  support    no
Documentation     no
PIE               yes
vde support       no
netmap support    no
Linux AIO support no
ATTR/XATTR support yes
Install blobs     yes
KVM support       yes
RDMA support      no
TCG interpreter   no
fdt support       yes
preadv support    yes
fdatasync         yes
madvise           yes
posix_madvise     yes
libcap-ng support no
vhost-net support yes
vhost-scsi support yes
vhost-vsock support yes
Trace backends    log
spice support     no 
rbd support       no
xfsctl support    no
smartcard support no
libusb            no
usb net redir     no
OpenGL support    no
OpenGL dmabufs    no
libiscsi support  no
libnfs support    no
build guest agent yes
QGA VSS support   no
QGA w32 disk info no
QGA MSI support   no
seccomp support   no
coroutine backend ucontext
coroutine pool    yes
GlusterFS support no
Archipelago support no
gcov              gcov
gcov enabled      no
TPM support       yes
libssh2 support   no
TPM passthrough   yes
QOM debugging     yes
lzo support       no
snappy support    no
bzip2 support     no
NUMA host support no
tcmalloc support  no
jemalloc support  no
avx2 optimization no
replication support yes
  GEN   x86_64-softmmu/config-devices.mak.tmp
  GEN   aarch64-softmmu/config-devices.mak.tmp
  GEN   config-host.h
  GEN   qemu-options.def
  GEN   qmp-commands.h
  GEN   qapi-types.h
  GEN   qapi-visit.h
  GEN   qapi-event.h
  GEN   x86_64-softmmu/config-devices.mak
  GEN   aarch64-softmmu/config-devices.mak
  GEN   qmp-introspect.h
  GEN   module_block.h
  GEN   tests/test-qapi-types.h
  GEN   tests/test-qapi-visit.h
  GEN   tests/test-qmp-commands.h
  GEN   tests/test-qapi-event.h
  GEN   tests/test-qmp-introspect.h
  GEN   config-all-devices.mak
  GEN   trace/generated-events.h
  GEN   trace/generated-tracers.h
  GEN   trace/generated-tcg-tracers.h
  GEN   trace/generated-helpers-wrappers.h
  GEN   trace/generated-helpers.h
  CC    tests/qemu-iotests/socket_scm_helper.o
  GEN   qga/qapi-generated/qga-qapi-visit.h
  GEN   qga/qapi-generated/qga-qapi-types.h
  GEN   qga/qapi-generated/qga-qmp-commands.h
  GEN   qga/qapi-generated/qga-qapi-types.c
  GEN   qga/qapi-generated/qga-qapi-visit.c
  GEN   qga/qapi-generated/qga-qmp-marshal.c
  GEN   qmp-introspect.c
  GEN   qapi-types.c
  GEN   qapi-visit.c
  GEN   qapi-event.c
  CC    qapi/qapi-visit-core.o
  CC    qapi/qapi-dealloc-visitor.o
  CC    qapi/qmp-input-visitor.o
  CC    qapi/qmp-output-visitor.o
  CC    qapi/qmp-registry.o
  CC    qapi/qmp-dispatch.o
  CC    qapi/string-input-visitor.o
  CC    qapi/string-output-visitor.o
  CC    qapi/opts-visitor.o
  CC    qapi/qapi-clone-visitor.o
  CC    qapi/qmp-event.o
  CC    qapi/qapi-util.o
  CC    qobject/qnull.o
  CC    qobject/qint.o
  CC    qobject/qstring.o
  CC    qobject/qdict.o
  CC    qobject/qlist.o
  CC    qobject/qfloat.o
  CC    qobject/qbool.o
  CC    qobject/qjson.o
  CC    qobject/qobject.o
  CC    qobject/json-lexer.o
  CC    qobject/json-streamer.o
  CC    qobject/json-parser.o
  GEN   trace/generated-events.c
  CC    trace/control.o
  CC    trace/qmp.o
  CC    util/osdep.o
  CC    util/cutils.o
  CC    util/unicode.o
  CC    util/qemu-timer-common.o
  CC    util/bufferiszero.o
  CC    util/compatfd.o
  CC    util/event_notifier-posix.o
  CC    util/mmap-alloc.o
  CC    util/oslib-posix.o
  CC    util/qemu-openpty.o
  CC    util/qemu-thread-posix.o
  CC    util/memfd.o
  CC    util/envlist.o
  CC    util/path.o
  CC    util/module.o
  CC    util/bitmap.o
  CC    util/bitops.o
  CC    util/hbitmap.o
  CC    util/fifo8.o
  CC    util/acl.o
  CC    util/error.o
  CC    util/qemu-error.o
  CC    util/id.o
  CC    util/iov.o
  CC    util/qemu-config.o
  CC    util/qemu-sockets.o
  CC    util/uri.o
  CC    util/notify.o
  CC    util/qemu-option.o
  CC    util/qemu-progress.o
  CC    util/hexdump.o
  CC    util/crc32c.o
  CC    util/uuid.o
  CC    util/throttle.o
  CC    util/getauxval.o
  CC    util/readline.o
  CC    util/rfifolock.o
  CC    util/rcu.o
  CC    util/qemu-coroutine.o
  CC    util/qemu-coroutine-lock.o
  CC    util/qemu-coroutine-io.o
  CC    util/qemu-coroutine-sleep.o
  CC    util/coroutine-ucontext.o
  CC    util/buffer.o
  CC    util/timed-average.o
  CC    util/base64.o
  CC    util/log.o
  CC    util/qdist.o
  CC    util/qht.o
  CC    util/range.o
  CC    crypto/pbkdf-stub.o
  CC    stubs/arch-query-cpu-def.o
  CC    stubs/arch-query-cpu-model-expansion.o
  CC    stubs/arch-query-cpu-model-comparison.o
/tmp/qemu-test/src/util/qht.c: In function ‘qht_reset_size’:
/tmp/qemu-test/src/util/qht.c:413: warning: ‘new’ may be used uninitialized in this function
  CC    stubs/arch-query-cpu-model-baseline.o
  CC    stubs/bdrv-next-monitor-owned.o
  CC    stubs/blk-commit-all.o
  CC    stubs/blockdev-close-all-bdrv-states.o
  CC    stubs/clock-warp.o
  CC    stubs/cpu-get-clock.o
  CC    stubs/cpu-get-icount.o
  CC    stubs/dump.o
  CC    stubs/fdset-add-fd.o
  CC    stubs/fdset-find-fd.o
  CC    stubs/fdset-get-fd.o
  CC    stubs/fdset-remove-fd.o
  CC    stubs/gdbstub.o
  CC    stubs/get-fd.o
  CC    stubs/get-next-serial.o
  CC    stubs/get-vm-name.o
  CC    stubs/iothread-lock.o
  CC    stubs/is-daemonized.o
  CC    stubs/machine-init-done.o
  CC    stubs/migr-blocker.o
  CC    stubs/mon-is-qmp.o
  CC    stubs/mon-printf.o
  CC    stubs/monitor-init.o
  CC    stubs/notify-event.o
  CC    stubs/qtest.o
  CC    stubs/replay.o
  CC    stubs/replay-user.o
  CC    stubs/reset.o
  CC    stubs/runstate-check.o
  CC    stubs/set-fd-handler.o
  CC    stubs/slirp.o
  CC    stubs/sysbus.o
  CC    stubs/trace-control.o
  CC    stubs/uuid.o
  CC    stubs/vm-stop.o
  CC    stubs/vmstate.o
  CC    stubs/cpus.o
  CC    stubs/kvm.o
  CC    stubs/qmp_pc_dimm_device_list.o
  CC    stubs/target-monitor-defs.o
  CC    stubs/target-get-monitor-def.o
  CC    stubs/vhost.o
  CC    stubs/iohandler.o
  CC    stubs/smbios_type_38.o
  CC    stubs/ipmi.o
  CC    stubs/pc_madt_cpu_entry.o
  CC    contrib/ivshmem-client/ivshmem-client.o
  CC    contrib/ivshmem-client/main.o
  CC    contrib/ivshmem-server/ivshmem-server.o
  CC    contrib/ivshmem-server/main.o
  CC    qemu-nbd.o
  CC    async.o
  CC    thread-pool.o
  CC    block.o
  CC    blockjob.o
  CC    main-loop.o
  CC    iohandler.o
  CC    qemu-timer.o
  CC    aio-posix.o
  CC    qemu-io-cmds.o
  CC    replication.o
  CC    block/raw_bsd.o
  CC    block/qcow.o
  CC    block/vdi.o
  CC    block/vmdk.o
  CC    block/cloop.o
  CC    block/bochs.o
  CC    block/vpc.o
  CC    block/vvfat.o
  CC    block/dmg.o
  CC    block/qcow2.o
  CC    block/qcow2-refcount.o
  CC    block/qcow2-cluster.o
  CC    block/qcow2-snapshot.o
  CC    block/qcow2-cache.o
  CC    block/qed.o
  CC    block/qed-gencb.o
  CC    block/qed-l2-cache.o
  CC    block/qed-table.o
  CC    block/qed-cluster.o
  CC    block/qed-check.o
  CC    block/vhdx.o
  CC    block/vhdx-endian.o
  CC    block/vhdx-log.o
  CC    block/quorum.o
  CC    block/parallels.o
  CC    block/blkdebug.o
  CC    block/blkverify.o
  CC    block/blkreplay.o
  CC    block/block-backend.o
  CC    block/snapshot.o
  CC    block/qapi.o
  CC    block/raw-posix.o
  CC    block/null.o
  CC    block/mirror.o
  CC    block/commit.o
  CC    block/io.o
  CC    block/throttle-groups.o
  CC    block/nbd.o
  CC    block/nbd-client.o
  CC    block/sheepdog.o
  CC    block/accounting.o
  CC    block/dirty-bitmap.o
  CC    block/write-threshold.o
  CC    block/backup.o
  CC    block/replication.o
  CC    block/crypto.o
  CC    nbd/server.o
  CC    nbd/client.o
  CC    nbd/common.o
  CC    crypto/init.o
  CC    crypto/hash.o
  CC    crypto/hash-glib.o
  CC    crypto/aes.o
  CC    crypto/desrfb.o
  CC    crypto/cipher.o
  CC    crypto/tlscreds.o
  CC    crypto/tlscredsanon.o
  CC    crypto/tlscredsx509.o
  CC    crypto/tlssession.o
  CC    crypto/secret.o
  CC    crypto/random-platform.o
  CC    crypto/pbkdf.o
  CC    crypto/ivgen.o
  CC    crypto/ivgen-essiv.o
  CC    crypto/ivgen-plain.o
  CC    crypto/ivgen-plain64.o
  CC    crypto/afsplit.o
  CC    crypto/xts.o
  CC    crypto/block.o
  CC    crypto/block-qcow.o
  CC    crypto/block-luks.o
  CC    io/channel.o
  CC    io/channel-buffer.o
  CC    io/channel-command.o
  CC    io/channel-file.o
  CC    io/channel-socket.o
  CC    io/channel-tls.o
  CC    io/channel-watch.o
  CC    io/channel-websock.o
  CC    io/channel-util.o
  CC    io/task.o
  CC    qom/object.o
  CC    qom/container.o
  CC    qom/qom-qobject.o
  CC    qom/object_interfaces.o
  GEN   qemu-img-cmds.h
  CC    qemu-io.o
  CC    qemu-bridge-helper.o
  CC    blockdev.o
  CC    blockdev-nbd.o
  CC    iothread.o
  CC    qdev-monitor.o
  CC    device-hotplug.o
  CC    os-posix.o
  CC    qemu-char.o
  CC    page_cache.o
  CC    accel.o
  CC    bt-host.o
  CC    bt-vhci.o
  CC    dma-helpers.o
  CC    vl.o
  CC    tpm.o
  CC    device_tree.o
  GEN   qmp-marshal.c
  CC    qmp.o
  CC    hmp.o
  CC    tcg-runtime.o
  CC    cpus-common.o
  CC    audio/audio.o
  CC    audio/noaudio.o
  CC    audio/wavaudio.o
  CC    audio/mixeng.o
  CC    audio/sdlaudio.o
  CC    audio/ossaudio.o
  CC    audio/wavcapture.o
  CC    backends/rng.o
  CC    backends/rng-egd.o
  CC    backends/rng-random.o
  CC    backends/msmouse.o
  CC    backends/testdev.o
  CC    backends/tpm.o
  CC    backends/hostmem.o
  CC    backends/hostmem-ram.o
  CC    backends/hostmem-file.o
  CC    block/stream.o
  CC    disas/arm.o
  CC    disas/i386.o
  CC    fsdev/qemu-fsdev-dummy.o
  CC    fsdev/qemu-fsdev-opts.o
  CC    hw/acpi/core.o
  CC    hw/acpi/piix4.o
  CC    hw/acpi/pcihp.o
  CC    hw/acpi/ich9.o
  CC    hw/acpi/tco.o
  CC    hw/acpi/cpu_hotplug.o
  CC    hw/acpi/memory_hotplug.o
  CC    hw/acpi/memory_hotplug_acpi_table.o
  CC    hw/acpi/cpu.o
  CC    hw/acpi/acpi_interface.o
  CC    hw/acpi/bios-linker-loader.o
  CC    hw/acpi/aml-build.o
  CC    hw/acpi/ipmi.o
  CC    hw/audio/sb16.o
  CC    hw/audio/es1370.o
  CC    hw/audio/ac97.o
  CC    hw/audio/fmopl.o
  CC    hw/audio/adlib.o
  CC    hw/audio/gus.o
  CC    hw/audio/gusemu_hal.o
  CC    hw/audio/gusemu_mixer.o
  CC    hw/audio/cs4231a.o
  CC    hw/audio/intel-hda.o
  CC    hw/audio/hda-codec.o
  CC    hw/audio/pcspk.o
  CC    hw/audio/wm8750.o
  CC    hw/audio/pl041.o
  CC    hw/audio/lm4549.o
  CC    hw/audio/marvell_88w8618.o
  CC    hw/block/block.o
  CC    hw/block/cdrom.o
  CC    hw/block/hd-geometry.o
  CC    hw/block/fdc.o
  CC    hw/block/m25p80.o
  CC    hw/block/nand.o
  CC    hw/block/pflash_cfi01.o
  CC    hw/block/pflash_cfi02.o
  CC    hw/block/ecc.o
  CC    hw/block/onenand.o
  CC    hw/block/nvme.o
  CC    hw/bt/core.o
  CC    hw/bt/l2cap.o
  CC    hw/bt/sdp.o
  CC    hw/bt/hci.o
  CC    hw/bt/hid.o
  CC    hw/bt/hci-csr.o
  CC    hw/char/ipoctal232.o
  CC    hw/char/parallel.o
  CC    hw/char/pl011.o
  CC    hw/char/serial.o
  CC    hw/char/serial-isa.o
  CC    hw/char/serial-pci.o
  CC    hw/char/virtio-console.o
  CC    hw/char/cadence_uart.o
  CC    hw/char/debugcon.o
  CC    hw/char/imx_serial.o
  CC    hw/core/qdev.o
  CC    hw/core/qdev-properties.o
  CC    hw/core/bus.o
  CC    hw/core/fw-path-provider.o
  CC    hw/core/irq.o
  CC    hw/core/hotplug.o
  CC    hw/core/ptimer.o
  CC    hw/core/sysbus.o
  CC    hw/core/machine.o
  CC    hw/core/null-machine.o
  CC    hw/core/loader.o
  CC    hw/core/qdev-properties-system.o
  CC    hw/core/register.o
  CC    hw/core/platform-bus.o
  CC    hw/display/ads7846.o
  CC    hw/display/cirrus_vga.o
  CC    hw/display/pl110.o
  CC    hw/display/ssd0303.o
  CC    hw/display/ssd0323.o
  CC    hw/display/vga-pci.o
  CC    hw/display/vga-isa.o
  CC    hw/display/vmware_vga.o
  CC    hw/display/blizzard.o
  CC    hw/display/exynos4210_fimd.o
  CC    hw/display/framebuffer.o
  CC    hw/display/tc6393xb.o
  CC    hw/dma/pl080.o
  CC    hw/dma/pl330.o
  CC    hw/dma/i8257.o
  CC    hw/dma/xlnx-zynq-devcfg.o
  CC    hw/gpio/max7310.o
  CC    hw/gpio/pl061.o
  CC    hw/gpio/zaurus.o
  CC    hw/gpio/gpio_key.o
  CC    hw/i2c/core.o
  CC    hw/i2c/smbus.o
  CC    hw/i2c/smbus_eeprom.o
  CC    hw/i2c/i2c-ddc.o
  CC    hw/i2c/versatile_i2c.o
  CC    hw/i2c/smbus_ich9.o
  CC    hw/i2c/pm_smbus.o
  CC    hw/i2c/bitbang_i2c.o
  CC    hw/i2c/exynos4210_i2c.o
  CC    hw/i2c/imx_i2c.o
  CC    hw/i2c/aspeed_i2c.o
  CC    hw/ide/core.o
  CC    hw/ide/atapi.o
  CC    hw/ide/qdev.o
  CC    hw/ide/pci.o
  CC    hw/ide/isa.o
  CC    hw/ide/piix.o
  CC    hw/ide/microdrive.o
  CC    hw/ide/ahci.o
  CC    hw/ide/ich.o
  CC    hw/input/hid.o
  CC    hw/input/lm832x.o
  CC    hw/input/pckbd.o
  CC    hw/input/pl050.o
  CC    hw/input/ps2.o
  CC    hw/input/stellaris_input.o
  CC    hw/input/tsc2005.o
  CC    hw/input/vmmouse.o
  CC    hw/input/virtio-input.o
  CC    hw/input/virtio-input-hid.o
  CC    hw/input/virtio-input-host.o
  CC    hw/intc/i8259_common.o
  CC    hw/intc/i8259.o
  CC    hw/intc/pl190.o
  CC    hw/intc/realview_gic.o
  CC    hw/intc/imx_avic.o
  CC    hw/intc/ioapic_common.o
  CC    hw/intc/arm_gic_common.o
  CC    hw/intc/arm_gic.o
  CC    hw/intc/arm_gicv2m.o
/tmp/qemu-test/src/hw/input/virtio-input.c:299: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/input/virtio-input.c:299: warning: initialization from incompatible pointer type
  CC    hw/intc/arm_gicv3_common.o
  CC    hw/intc/arm_gicv3.o
  CC    hw/intc/arm_gicv3_dist.o
  CC    hw/intc/arm_gicv3_redist.o
  CC    hw/ipack/ipack.o
  CC    hw/ipack/tpci200.o
  CC    hw/ipmi/ipmi.o
  CC    hw/ipmi/ipmi_bmc_sim.o
  CC    hw/ipmi/ipmi_bmc_extern.o
  CC    hw/ipmi/isa_ipmi_kcs.o
  CC    hw/ipmi/isa_ipmi_bt.o
  CC    hw/isa/isa-bus.o
  CC    hw/isa/apm.o
  CC    hw/mem/pc-dimm.o
  CC    hw/mem/nvdimm.o
  CC    hw/misc/applesmc.o
  CC    hw/misc/max111x.o
  CC    hw/misc/tmp105.o
  CC    hw/misc/debugexit.o
  CC    hw/misc/sga.o
  CC    hw/misc/pc-testdev.o
  CC    hw/misc/pci-testdev.o
  CC    hw/misc/arm_l2x0.o
  CC    hw/misc/arm_integrator_debug.o
  CC    hw/misc/a9scu.o
  CC    hw/misc/arm11scu.o
  CC    hw/net/ne2000.o
  CC    hw/net/eepro100.o
  CC    hw/net/pcnet-pci.o
  CC    hw/net/pcnet.o
  CC    hw/net/e1000.o
  CC    hw/net/e1000x_common.o
  CC    hw/net/net_tx_pkt.o
  CC    hw/net/net_rx_pkt.o
  CC    hw/net/e1000e.o
  CC    hw/net/e1000e_core.o
  CC    hw/net/rtl8139.o
  CC    hw/net/vmxnet3.o
  CC    hw/net/smc91c111.o
  CC    hw/net/lan9118.o
  CC    hw/net/ne2000-isa.o
  CC    hw/net/xgmac.o
  CC    hw/net/allwinner_emac.o
  CC    hw/net/imx_fec.o
  CC    hw/net/cadence_gem.o
  CC    hw/net/stellaris_enet.o
  CC    hw/net/rocker/rocker.o
  CC    hw/net/rocker/rocker_fp.o
  CC    hw/net/rocker/rocker_desc.o
  CC    hw/net/rocker/rocker_world.o
  CC    hw/net/rocker/rocker_of_dpa.o
  CC    hw/nvram/eeprom93xx.o
  CC    hw/nvram/fw_cfg.o
  CC    hw/pci-bridge/pci_bridge_dev.o
  CC    hw/pci-bridge/pci_expander_bridge.o
  CC    hw/pci-bridge/xio3130_upstream.o
  CC    hw/pci-bridge/xio3130_downstream.o
  CC    hw/pci-bridge/ioh3420.o
  CC    hw/pci-bridge/i82801b11.o
  CC    hw/pci-host/pam.o
  CC    hw/pci-host/versatile.o
  CC    hw/pci-host/piix.o
  CC    hw/pci-host/q35.o
  CC    hw/pci-host/gpex.o
  CC    hw/pci/pci.o
  CC    hw/pci/pci_bridge.o
  CC    hw/pci/msix.o
/tmp/qemu-test/src/hw/nvram/fw_cfg.c: In function ‘fw_cfg_dma_transfer’:
/tmp/qemu-test/src/hw/nvram/fw_cfg.c:330: warning: ‘read’ may be used uninitialized in this function
  CC    hw/pci/msi.o
  CC    hw/pci/shpc.o
  CC    hw/pci/slotid_cap.o
  CC    hw/pci/pci_host.o
  CC    hw/pci/pcie_host.o
  CC    hw/pci/pcie.o
  CC    hw/pci/pcie_aer.o
  CC    hw/pci/pcie_port.o
  CC    hw/pci/pci-stub.o
  CC    hw/pcmcia/pcmcia.o
  CC    hw/scsi/scsi-disk.o
  CC    hw/scsi/scsi-generic.o
  CC    hw/scsi/scsi-bus.o
  CC    hw/scsi/lsi53c895a.o
  CC    hw/scsi/mptsas.o
  CC    hw/scsi/mptconfig.o
  CC    hw/scsi/mptendian.o
  CC    hw/scsi/megasas.o
  CC    hw/scsi/vmw_pvscsi.o
  CC    hw/scsi/esp.o
  CC    hw/scsi/esp-pci.o
  CC    hw/sd/pl181.o
  CC    hw/sd/ssi-sd.o
  CC    hw/sd/sd.o
  CC    hw/sd/core.o
  CC    hw/sd/sdhci.o
  CC    hw/smbios/smbios.o
  CC    hw/smbios/smbios_type_38.o
  CC    hw/ssi/pl022.o
  CC    hw/ssi/ssi.o
  CC    hw/ssi/xilinx_spips.o
  CC    hw/ssi/aspeed_smc.o
  CC    hw/timer/arm_timer.o
  CC    hw/timer/arm_mptimer.o
  CC    hw/timer/a9gtimer.o
  CC    hw/timer/cadence_ttc.o
  CC    hw/timer/ds1338.o
  CC    hw/timer/hpet.o
  CC    hw/timer/i8254_common.o
  CC    hw/timer/i8254.o
  CC    hw/timer/pl031.o
  CC    hw/timer/twl92230.o
  CC    hw/timer/imx_epit.o
  CC    hw/timer/imx_gpt.o
  CC    hw/timer/stm32f2xx_timer.o
  CC    hw/timer/aspeed_timer.o
  CC    hw/tpm/tpm_tis.o
  CC    hw/tpm/tpm_passthrough.o
  CC    hw/tpm/tpm_util.o
  CC    hw/usb/core.o
  CC    hw/usb/combined-packet.o
  CC    hw/usb/bus.o
  CC    hw/usb/libhw.o
  CC    hw/usb/desc.o
  CC    hw/usb/desc-msos.o
  CC    hw/usb/hcd-uhci.o
  CC    hw/usb/hcd-ohci.o
  CC    hw/usb/hcd-ehci.o
  CC    hw/usb/hcd-ehci-pci.o
  CC    hw/usb/hcd-ehci-sysbus.o
  CC    hw/usb/hcd-xhci.o
  CC    hw/usb/hcd-musb.o
  CC    hw/usb/dev-hub.o
  CC    hw/usb/dev-hid.o
  CC    hw/usb/dev-wacom.o
  CC    hw/usb/dev-storage.o
  CC    hw/usb/dev-uas.o
  CC    hw/usb/dev-audio.o
  CC    hw/usb/dev-serial.o
  CC    hw/usb/dev-network.o
  CC    hw/usb/dev-bluetooth.o
  CC    hw/usb/dev-smartcard-reader.o
  CC    hw/usb/dev-mtp.o
  CC    hw/usb/host-stub.o
  CC    hw/virtio/virtio-rng.o
  CC    hw/virtio/virtio-pci.o
  CC    hw/virtio/virtio-bus.o
  CC    hw/virtio/virtio-mmio.o
  CC    hw/watchdog/watchdog.o
  CC    hw/watchdog/wdt_i6300esb.o
  CC    hw/watchdog/wdt_ib700.o
  CC    migration/migration.o
  CC    migration/socket.o
  CC    migration/fd.o
  CC    migration/exec.o
  CC    migration/tls.o
  CC    migration/vmstate.o
  CC    migration/qemu-file.o
/tmp/qemu-test/src/hw/virtio/virtio-rng.c:219: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/virtio/virtio-rng.c:219: warning: initialization from incompatible pointer type
  CC    migration/qemu-file-channel.o
  CC    migration/xbzrle.o
  CC    migration/postcopy-ram.o
  CC    migration/qjson.o
  CC    migration/block.o
  CC    net/net.o
  CC    net/queue.o
  CC    net/checksum.o
  CC    net/util.o
  CC    net/hub.o
  CC    net/socket.o
  CC    net/dump.o
  CC    net/eth.o
  CC    net/l2tpv3.o
  CC    net/tap.o
  CC    net/vhost-user.o
  CC    net/tap-linux.o
  CC    net/slirp.o
  CC    net/filter.o
  CC    net/filter-buffer.o
  CC    net/filter-mirror.o
  CC    net/colo-compare.o
  CC    net/colo.o
  CC    net/filter-rewriter.o
  CC    qom/cpu.o
  CC    replay/replay.o
  CC    replay/replay-internal.o
  CC    replay/replay-events.o
  CC    replay/replay-time.o
  CC    replay/replay-input.o
  CC    replay/replay-char.o
/tmp/qemu-test/src/replay/replay-internal.c: In function ‘replay_put_array’:
/tmp/qemu-test/src/replay/replay-internal.c:65: warning: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result
  CC    replay/replay-snapshot.o
  CC    slirp/cksum.o
  CC    slirp/if.o
  CC    slirp/ip_icmp.o
  CC    slirp/ip6_icmp.o
  CC    slirp/ip6_input.o
  CC    slirp/ip6_output.o
  CC    slirp/ip_input.o
  CC    slirp/ip_output.o
  CC    slirp/dnssearch.o
  CC    slirp/dhcpv6.o
  CC    slirp/slirp.o
  CC    slirp/mbuf.o
  CC    slirp/misc.o
  CC    slirp/sbuf.o
  CC    slirp/socket.o
  CC    slirp/tcp_input.o
  CC    slirp/tcp_output.o
  CC    slirp/tcp_subr.o
  CC    slirp/tcp_timer.o
  CC    slirp/udp.o
  CC    slirp/udp6.o
  CC    slirp/bootp.o
/tmp/qemu-test/src/slirp/tcp_input.c: In function ‘tcp_input’:
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_p’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_len’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_tos’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_id’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_off’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_ttl’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_sum’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_src.s_addr’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_dst.s_addr’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:220: warning: ‘save_ip6.ip_nh’ may be used uninitialized in this function
  CC    slirp/tftp.o
  CC    slirp/arp_table.o
  CC    slirp/ndp_table.o
  CC    ui/keymaps.o
  CC    ui/console.o
  CC    ui/cursor.o
  CC    ui/qemu-pixman.o
  CC    ui/input.o
  CC    ui/input-keymap.o
  CC    ui/input-legacy.o
  CC    ui/input-linux.o
  CC    ui/sdl.o
  CC    ui/sdl_zoom.o
  CC    ui/x_keymap.o
  CC    ui/vnc.o
  CC    ui/vnc-enc-zlib.o
  CC    ui/vnc-enc-hextile.o
  CC    ui/vnc-enc-tight.o
  CC    ui/vnc-palette.o
  CC    ui/vnc-enc-zrle.o
  CC    ui/vnc-auth-vencrypt.o
  CC    ui/vnc-ws.o
  CC    ui/vnc-jobs.o
  LINK  tests/qemu-iotests/socket_scm_helper
  CC    qga/commands.o
  CC    qga/guest-agent-command-state.o
  AS    optionrom/multiboot.o
  AS    optionrom/linuxboot.o
  CC    optionrom/linuxboot_dma.o
  AS    optionrom/kvmvapic.o
cc: unrecognized option '-no-integrated-as'
cc: unrecognized option '-no-integrated-as'
  CC    qga/main.o
  Building optionrom/multiboot.img
  Building optionrom/linuxboot.img
  CC    qga/commands-posix.o
  Building optionrom/linuxboot_dma.img
  Building optionrom/kvmvapic.img
  Building optionrom/multiboot.raw
  Building optionrom/linuxboot.raw
  Building optionrom/linuxboot_dma.raw
  Building optionrom/kvmvapic.raw
  Signing optionrom/multiboot.bin
  Signing optionrom/linuxboot.bin
  Signing optionrom/linuxboot_dma.bin
  CC    qga/channel-posix.o
  Signing optionrom/kvmvapic.bin
  CC    qga/qapi-generated/qga-qapi-types.o
  CC    qga/qapi-generated/qga-qapi-visit.o
  CC    qga/qapi-generated/qga-qmp-marshal.o
  CC    qmp-introspect.o
  CC    qapi-types.o
  CC    qapi-visit.o
  CC    qapi-event.o
  AR    libqemustub.a
  CC    qemu-img.o
  CC    qmp-marshal.o
  CC    trace/generated-events.o
  AR    libqemuutil.a
  LINK  qemu-ga
  LINK  ivshmem-client
  LINK  ivshmem-server
  LINK  qemu-nbd
  LINK  qemu-io
  LINK  qemu-bridge-helper
  LINK  qemu-img
  GEN   x86_64-softmmu/hmp-commands.h
  GEN   x86_64-softmmu/hmp-commands-info.h
  GEN   x86_64-softmmu/config-target.h
  CC    x86_64-softmmu/exec.o
  CC    x86_64-softmmu/translate-all.o
  CC    x86_64-softmmu/cpu-exec.o
  CC    x86_64-softmmu/translate-common.o
  CC    x86_64-softmmu/cpu-exec-common.o
  CC    x86_64-softmmu/tcg/tcg.o
  CC    x86_64-softmmu/tcg/tcg-op.o
  GEN   aarch64-softmmu/hmp-commands.h
  GEN   aarch64-softmmu/hmp-commands-info.h
  GEN   aarch64-softmmu/config-target.h
  CC    aarch64-softmmu/exec.o
  CC    x86_64-softmmu/tcg/optimize.o
  CC    x86_64-softmmu/tcg/tcg-common.o
  CC    x86_64-softmmu/fpu/softfloat.o
  CC    x86_64-softmmu/disas.o
  CC    x86_64-softmmu/arch_init.o
  CC    aarch64-softmmu/translate-all.o
  CC    x86_64-softmmu/cpus.o
  CC    x86_64-softmmu/monitor.o
  CC    x86_64-softmmu/gdbstub.o
  CC    x86_64-softmmu/balloon.o
  CC    aarch64-softmmu/cpu-exec.o
  CC    aarch64-softmmu/translate-common.o
  CC    aarch64-softmmu/cpu-exec-common.o
  CC    aarch64-softmmu/tcg/tcg.o
  CC    x86_64-softmmu/ioport.o
  CC    x86_64-softmmu/numa.o
  CC    aarch64-softmmu/tcg/tcg-op.o
  CC    x86_64-softmmu/qtest.o
  CC    aarch64-softmmu/tcg/optimize.o
  CC    aarch64-softmmu/tcg/tcg-common.o
  CC    x86_64-softmmu/bootdevice.o
  CC    x86_64-softmmu/kvm-all.o
  CC    aarch64-softmmu/fpu/softfloat.o
  CC    aarch64-softmmu/disas.o
  GEN   aarch64-softmmu/gdbstub-xml.c
  CC    x86_64-softmmu/memory.o
  CC    aarch64-softmmu/kvm-stub.o
  CC    aarch64-softmmu/arch_init.o
  CC    x86_64-softmmu/cputlb.o
  CC    aarch64-softmmu/cpus.o
  CC    x86_64-softmmu/memory_mapping.o
  CC    aarch64-softmmu/monitor.o
  CC    aarch64-softmmu/gdbstub.o
  CC    aarch64-softmmu/balloon.o
  CC    x86_64-softmmu/dump.o
  CC    aarch64-softmmu/ioport.o
  CC    aarch64-softmmu/numa.o
  CC    aarch64-softmmu/qtest.o
  CC    aarch64-softmmu/bootdevice.o
  CC    x86_64-softmmu/migration/ram.o
  CC    x86_64-softmmu/migration/savevm.o
  CC    aarch64-softmmu/memory.o
  CC    aarch64-softmmu/cputlb.o
  CC    x86_64-softmmu/xen-common-stub.o
  CC    aarch64-softmmu/memory_mapping.o
  CC    x86_64-softmmu/xen-hvm-stub.o
  CC    aarch64-softmmu/dump.o
  CC    x86_64-softmmu/hw/acpi/nvdimm.o
  CC    aarch64-softmmu/migration/ram.o
  CC    x86_64-softmmu/hw/block/virtio-blk.o
  CC    x86_64-softmmu/hw/block/dataplane/virtio-blk.o
  CC    aarch64-softmmu/migration/savevm.o
  CC    x86_64-softmmu/hw/char/virtio-serial-bus.o
  CC    x86_64-softmmu/hw/core/nmi.o
  CC    aarch64-softmmu/xen-common-stub.o
  CC    x86_64-softmmu/hw/cpu/core.o
  CC    aarch64-softmmu/xen-hvm-stub.o
  CC    aarch64-softmmu/hw/block/virtio-blk.o
/tmp/qemu-test/src/hw/block/virtio-blk.c:959: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/block/virtio-blk.c:959: warning: initialization from incompatible pointer type
  CC    x86_64-softmmu/hw/display/vga.o
  CC    aarch64-softmmu/hw/block/dataplane/virtio-blk.o
  CC    x86_64-softmmu/hw/display/virtio-gpu.o
  CC    x86_64-softmmu/hw/display/virtio-gpu-3d.o
  CC    aarch64-softmmu/hw/char/exynos4210_uart.o
/tmp/qemu-test/src/hw/char/virtio-serial-bus.c:1078: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/char/virtio-serial-bus.c:1078: warning: initialization from incompatible pointer type
  CC    aarch64-softmmu/hw/char/omap_uart.o
  CC    aarch64-softmmu/hw/char/digic-uart.o
  CC    x86_64-softmmu/hw/display/virtio-gpu-pci.o
  CC    x86_64-softmmu/hw/display/virtio-vga.o
  CC    x86_64-softmmu/hw/intc/apic.o
  CC    x86_64-softmmu/hw/intc/apic_common.o
  CC    x86_64-softmmu/hw/intc/ioapic.o
/tmp/qemu-test/src/hw/block/virtio-blk.c:959: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/block/virtio-blk.c:959: warning: initialization from incompatible pointer type
  CC    aarch64-softmmu/hw/char/stm32f2xx_usart.o
  CC    aarch64-softmmu/hw/char/bcm2835_aux.o
  CC    aarch64-softmmu/hw/char/virtio-serial-bus.o
/tmp/qemu-test/src/hw/display/virtio-gpu.c:1222: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/display/virtio-gpu.c:1222: warning: initialization from incompatible pointer type
  CC    aarch64-softmmu/hw/core/nmi.o
  CC    x86_64-softmmu/hw/isa/lpc_ich9.o
  CC    x86_64-softmmu/hw/misc/vmport.o
  CC    x86_64-softmmu/hw/misc/ivshmem.o
  CC    aarch64-softmmu/hw/cpu/arm11mpcore.o
  CC    aarch64-softmmu/hw/cpu/realview_mpcore.o
  CC    x86_64-softmmu/hw/misc/pvpanic.o
  CC    x86_64-softmmu/hw/misc/edu.o
  CC    x86_64-softmmu/hw/misc/hyperv_testdev.o
  CC    aarch64-softmmu/hw/cpu/a9mpcore.o
  CC    aarch64-softmmu/hw/cpu/a15mpcore.o
  CC    aarch64-softmmu/hw/cpu/core.o
  CC    x86_64-softmmu/hw/net/virtio-net.o
  CC    x86_64-softmmu/hw/net/vhost_net.o
  CC    aarch64-softmmu/hw/display/omap_dss.o
/tmp/qemu-test/src/hw/char/virtio-serial-bus.c:1078: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/char/virtio-serial-bus.c:1078: warning: initialization from incompatible pointer type
  CC    x86_64-softmmu/hw/scsi/virtio-scsi.o
  CC    x86_64-softmmu/hw/scsi/virtio-scsi-dataplane.o
  CC    x86_64-softmmu/hw/scsi/vhost-scsi.o
  CC    aarch64-softmmu/hw/display/omap_lcdc.o
  CC    x86_64-softmmu/hw/timer/mc146818rtc.o
  CC    aarch64-softmmu/hw/display/pxa2xx_lcd.o
  CC    x86_64-softmmu/hw/vfio/common.o
  CC    aarch64-softmmu/hw/display/bcm2835_fb.o
  CC    aarch64-softmmu/hw/display/vga.o
/tmp/qemu-test/src/hw/scsi/virtio-scsi.c:924: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/scsi/virtio-scsi.c:924: warning: initialization from incompatible pointer type
  CC    x86_64-softmmu/hw/vfio/pci.o
  CC    aarch64-softmmu/hw/display/virtio-gpu.o
  CC    x86_64-softmmu/hw/vfio/pci-quirks.o
/tmp/qemu-test/src/hw/net/virtio-net.c:1857: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/net/virtio-net.c:1857: warning: initialization from incompatible pointer type
  CC    aarch64-softmmu/hw/display/virtio-gpu-3d.o
  CC    aarch64-softmmu/hw/display/virtio-gpu-pci.o
  CC    aarch64-softmmu/hw/display/dpcd.o
  CC    aarch64-softmmu/hw/display/xlnx_dp.o
  CC    x86_64-softmmu/hw/vfio/platform.o
  CC    x86_64-softmmu/hw/vfio/calxeda-xgmac.o
/tmp/qemu-test/src/hw/display/virtio-gpu.c:1222: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/display/virtio-gpu.c:1222: warning: initialization from incompatible pointer type
  CC    x86_64-softmmu/hw/vfio/amd-xgbe.o
  CC    x86_64-softmmu/hw/vfio/spapr.o
  CC    aarch64-softmmu/hw/dma/xlnx_dpdma.o
  CC    aarch64-softmmu/hw/dma/omap_dma.o
  CC    aarch64-softmmu/hw/dma/soc_dma.o
  CC    aarch64-softmmu/hw/dma/pxa2xx_dma.o
  CC    aarch64-softmmu/hw/dma/bcm2835_dma.o
  CC    x86_64-softmmu/hw/virtio/virtio.o
  CC    aarch64-softmmu/hw/gpio/omap_gpio.o
  CC    x86_64-softmmu/hw/virtio/virtio-balloon.o
  CC    x86_64-softmmu/hw/virtio/vhost.o
  CC    aarch64-softmmu/hw/gpio/imx_gpio.o
  CC    aarch64-softmmu/hw/i2c/omap_i2c.o
  CC    aarch64-softmmu/hw/input/pxa2xx_keypad.o
  CC    x86_64-softmmu/hw/virtio/vhost-backend.o
  CC    aarch64-softmmu/hw/input/tsc210x.o
  CC    aarch64-softmmu/hw/intc/armv7m_nvic.o
  CC    x86_64-softmmu/hw/virtio/vhost-user.o
  CC    x86_64-softmmu/hw/virtio/vhost-vsock.o
  CC    aarch64-softmmu/hw/intc/exynos4210_gic.o
  CC    x86_64-softmmu/hw/i386/multiboot.o
/tmp/qemu-test/src/hw/virtio/virtio-balloon.c:497: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/virtio/virtio-balloon.c:497: warning: initialization from incompatible pointer type
  CC    x86_64-softmmu/hw/i386/pc.o
  CC    x86_64-softmmu/hw/i386/pc_piix.o
/tmp/qemu-test/src/hw/virtio/vhost-vsock.c:295: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/virtio/vhost-vsock.c:295: warning: initialization from incompatible pointer type
  CC    x86_64-softmmu/hw/i386/pc_q35.o
  CC    x86_64-softmmu/hw/i386/pc_sysfw.o
  CC    x86_64-softmmu/hw/i386/x86-iommu.o
  CC    aarch64-softmmu/hw/intc/exynos4210_combiner.o
  CC    aarch64-softmmu/hw/intc/omap_intc.o
  CC    aarch64-softmmu/hw/intc/bcm2835_ic.o
  CC    x86_64-softmmu/hw/i386/intel_iommu.o
  CC    aarch64-softmmu/hw/intc/bcm2836_control.o
  CC    aarch64-softmmu/hw/intc/allwinner-a10-pic.o
  CC    x86_64-softmmu/hw/i386/amd_iommu.o
/tmp/qemu-test/src/hw/i386/pc_piix.c: In function ‘igd_passthrough_isa_bridge_create’:
/tmp/qemu-test/src/hw/i386/pc_piix.c:1046: warning: ‘pch_rev_id’ may be used uninitialized in this function
  CC    x86_64-softmmu/hw/i386/kvmvapic.o
  CC    aarch64-softmmu/hw/intc/aspeed_vic.o
  CC    x86_64-softmmu/hw/i386/acpi-build.o
  CC    x86_64-softmmu/hw/i386/pci-assign-load-rom.o
  CC    aarch64-softmmu/hw/intc/arm_gicv3_cpuif.o
  CC    aarch64-softmmu/hw/misc/ivshmem.o
  CC    x86_64-softmmu/hw/i386/kvm/clock.o
  CC    aarch64-softmmu/hw/misc/arm_sysctl.o
  CC    x86_64-softmmu/hw/i386/kvm/apic.o
  CC    aarch64-softmmu/hw/misc/cbus.o
  CC    aarch64-softmmu/hw/misc/exynos4210_pmu.o
  CC    aarch64-softmmu/hw/misc/imx_ccm.o
  CC    x86_64-softmmu/hw/i386/kvm/i8259.o
  CC    aarch64-softmmu/hw/misc/imx31_ccm.o
  CC    aarch64-softmmu/hw/misc/imx25_ccm.o
/tmp/qemu-test/src/hw/i386/acpi-build.c: In function ‘build_append_pci_bus_devices’:
/tmp/qemu-test/src/hw/i386/acpi-build.c:472: warning: ‘notify_method’ may be used uninitialized in this function
  CC    aarch64-softmmu/hw/misc/imx6_ccm.o
  CC    x86_64-softmmu/hw/i386/kvm/ioapic.o
  CC    aarch64-softmmu/hw/misc/imx6_src.o
  CC    x86_64-softmmu/hw/i386/kvm/i8254.o
  CC    x86_64-softmmu/hw/i386/kvm/pci-assign.o
  CC    x86_64-softmmu/target-i386/translate.o
  CC    aarch64-softmmu/hw/misc/mst_fpga.o
  CC    x86_64-softmmu/target-i386/helper.o
  CC    x86_64-softmmu/target-i386/cpu.o
  CC    x86_64-softmmu/target-i386/bpt_helper.o
  CC    aarch64-softmmu/hw/misc/omap_clk.o
  CC    aarch64-softmmu/hw/misc/omap_gpmc.o
  CC    x86_64-softmmu/target-i386/excp_helper.o
  CC    aarch64-softmmu/hw/misc/omap_l4.o
  CC    aarch64-softmmu/hw/misc/omap_sdrc.o
  CC    aarch64-softmmu/hw/misc/omap_tap.o
  CC    aarch64-softmmu/hw/misc/bcm2835_mbox.o
  CC    x86_64-softmmu/target-i386/fpu_helper.o
  CC    aarch64-softmmu/hw/misc/bcm2835_property.o
  CC    aarch64-softmmu/hw/misc/zynq_slcr.o
  CC    x86_64-softmmu/target-i386/cc_helper.o
  CC    x86_64-softmmu/target-i386/int_helper.o
  CC    x86_64-softmmu/target-i386/svm_helper.o
  CC    x86_64-softmmu/target-i386/smm_helper.o
  CC    aarch64-softmmu/hw/misc/zynq-xadc.o
  CC    aarch64-softmmu/hw/misc/stm32f2xx_syscfg.o
  CC    aarch64-softmmu/hw/misc/edu.o
  CC    x86_64-softmmu/target-i386/misc_helper.o
  CC    x86_64-softmmu/target-i386/mem_helper.o
  CC    x86_64-softmmu/target-i386/seg_helper.o
  CC    x86_64-softmmu/target-i386/mpx_helper.o
  CC    aarch64-softmmu/hw/misc/auxbus.o
  CC    aarch64-softmmu/hw/misc/aspeed_scu.o
  CC    aarch64-softmmu/hw/misc/aspeed_sdmc.o
  CC    aarch64-softmmu/hw/net/virtio-net.o
  CC    x86_64-softmmu/target-i386/gdbstub.o
  CC    aarch64-softmmu/hw/net/vhost_net.o
  CC    aarch64-softmmu/hw/pcmcia/pxa2xx.o
/tmp/qemu-test/src/hw/net/virtio-net.c:1857: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/net/virtio-net.c:1857: warning: initialization from incompatible pointer type
  CC    x86_64-softmmu/target-i386/machine.o
  CC    aarch64-softmmu/hw/scsi/virtio-scsi.o
  CC    x86_64-softmmu/target-i386/arch_memory_mapping.o
  CC    aarch64-softmmu/hw/scsi/virtio-scsi-dataplane.o
  CC    aarch64-softmmu/hw/scsi/vhost-scsi.o
  CC    x86_64-softmmu/target-i386/arch_dump.o
  CC    x86_64-softmmu/target-i386/monitor.o
  CC    aarch64-softmmu/hw/sd/omap_mmc.o
  CC    x86_64-softmmu/target-i386/kvm.o
/tmp/qemu-test/src/hw/scsi/virtio-scsi.c:924: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/scsi/virtio-scsi.c:924: warning: initialization from incompatible pointer type
  CC    aarch64-softmmu/hw/sd/pxa2xx_mmci.o
  CC    aarch64-softmmu/hw/ssi/omap_spi.o
  CC    aarch64-softmmu/hw/ssi/imx_spi.o
  CC    aarch64-softmmu/hw/timer/exynos4210_mct.o
  CC    x86_64-softmmu/target-i386/hyperv.o
  CC    aarch64-softmmu/hw/timer/exynos4210_pwm.o
  CC    aarch64-softmmu/hw/timer/exynos4210_rtc.o
  GEN   trace/generated-helpers.c
  CC    x86_64-softmmu/trace/control-target.o
  CC    aarch64-softmmu/hw/timer/omap_gptimer.o
  CC    aarch64-softmmu/hw/timer/omap_synctimer.o
  CC    aarch64-softmmu/hw/timer/pxa2xx_timer.o
  CC    aarch64-softmmu/hw/timer/digic-timer.o
  CC    x86_64-softmmu/trace/generated-helpers.o
  CC    aarch64-softmmu/hw/timer/allwinner-a10-pit.o
  CC    aarch64-softmmu/hw/usb/tusb6010.o
  CC    aarch64-softmmu/hw/vfio/common.o
  CC    aarch64-softmmu/hw/vfio/pci.o
  CC    aarch64-softmmu/hw/vfio/pci-quirks.o
  CC    aarch64-softmmu/hw/vfio/platform.o
  CC    aarch64-softmmu/hw/vfio/calxeda-xgmac.o
  CC    aarch64-softmmu/hw/vfio/amd-xgbe.o
  LINK  x86_64-softmmu/qemu-system-x86_64
  CC    aarch64-softmmu/hw/vfio/spapr.o
  CC    aarch64-softmmu/hw/virtio/virtio.o
  CC    aarch64-softmmu/hw/virtio/virtio-balloon.o
  CC    aarch64-softmmu/hw/virtio/vhost.o
  CC    aarch64-softmmu/hw/virtio/vhost-backend.o
  CC    aarch64-softmmu/hw/virtio/vhost-user.o
  CC    aarch64-softmmu/hw/virtio/vhost-vsock.o
  CC    aarch64-softmmu/hw/arm/boot.o
  CC    aarch64-softmmu/hw/arm/collie.o
  CC    aarch64-softmmu/hw/arm/exynos4_boards.o
/tmp/qemu-test/src/hw/virtio/virtio-balloon.c:497: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/virtio/virtio-balloon.c:497: warning: initialization from incompatible pointer type
  CC    aarch64-softmmu/hw/arm/gumstix.o
/tmp/qemu-test/src/hw/virtio/vhost-vsock.c:295: warning: initialization from incompatible pointer type
/tmp/qemu-test/src/hw/virtio/vhost-vsock.c:295: warning: initialization from incompatible pointer type
  CC    aarch64-softmmu/hw/arm/highbank.o
  CC    aarch64-softmmu/hw/arm/digic_boards.o
  CC    aarch64-softmmu/hw/arm/integratorcp.o
  CC    aarch64-softmmu/hw/arm/mainstone.o
  CC    aarch64-softmmu/hw/arm/musicpal.o
  CC    aarch64-softmmu/hw/arm/nseries.o
  CC    aarch64-softmmu/hw/arm/omap_sx1.o
  CC    aarch64-softmmu/hw/arm/palm.o
  CC    aarch64-softmmu/hw/arm/realview.o
  CC    aarch64-softmmu/hw/arm/spitz.o
  CC    aarch64-softmmu/hw/arm/stellaris.o
  CC    aarch64-softmmu/hw/arm/tosa.o
  CC    aarch64-softmmu/hw/arm/versatilepb.o
  CC    aarch64-softmmu/hw/arm/vexpress.o
  CC    aarch64-softmmu/hw/arm/virt.o
  CC    aarch64-softmmu/hw/arm/xilinx_zynq.o
  CC    aarch64-softmmu/hw/arm/z2.o
  CC    aarch64-softmmu/hw/arm/virt-acpi-build.o
  CC    aarch64-softmmu/hw/arm/netduino2.o
  CC    aarch64-softmmu/hw/arm/sysbus-fdt.o
  CC    aarch64-softmmu/hw/arm/armv7m.o
  CC    aarch64-softmmu/hw/arm/exynos4210.o
  CC    aarch64-softmmu/hw/arm/pxa2xx.o
  CC    aarch64-softmmu/hw/arm/pxa2xx_gpio.o
  CC    aarch64-softmmu/hw/arm/pxa2xx_pic.o
  CC    aarch64-softmmu/hw/arm/digic.o
  CC    aarch64-softmmu/hw/arm/omap1.o
  CC    aarch64-softmmu/hw/arm/omap2.o
  CC    aarch64-softmmu/hw/arm/strongarm.o
  CC    aarch64-softmmu/hw/arm/allwinner-a10.o
  CC    aarch64-softmmu/hw/arm/cubieboard.o
  CC    aarch64-softmmu/hw/arm/bcm2835_peripherals.o
  CC    aarch64-softmmu/hw/arm/bcm2836.o
  CC    aarch64-softmmu/hw/arm/raspi.o
  CC    aarch64-softmmu/hw/arm/stm32f205_soc.o
  CC    aarch64-softmmu/hw/arm/xlnx-zynqmp.o
  CC    aarch64-softmmu/hw/arm/xlnx-ep108.o
  CC    aarch64-softmmu/hw/arm/fsl-imx25.o
  CC    aarch64-softmmu/hw/arm/imx25_pdk.o
  CC    aarch64-softmmu/hw/arm/fsl-imx31.o
  CC    aarch64-softmmu/hw/arm/kzm.o
  CC    aarch64-softmmu/hw/arm/fsl-imx6.o
  CC    aarch64-softmmu/hw/arm/sabrelite.o
  CC    aarch64-softmmu/hw/arm/aspeed_soc.o
  CC    aarch64-softmmu/hw/arm/aspeed.o
  CC    aarch64-softmmu/target-arm/arm-semi.o
  CC    aarch64-softmmu/target-arm/machine.o
  CC    aarch64-softmmu/target-arm/psci.o
  CC    aarch64-softmmu/target-arm/arch_dump.o
  CC    aarch64-softmmu/target-arm/monitor.o
  CC    aarch64-softmmu/target-arm/kvm-stub.o
  CC    aarch64-softmmu/target-arm/translate.o
  CC    aarch64-softmmu/target-arm/op_helper.o
  CC    aarch64-softmmu/target-arm/helper.o
  CC    aarch64-softmmu/target-arm/cpu.o
  CC    aarch64-softmmu/target-arm/neon_helper.o
  CC    aarch64-softmmu/target-arm/iwmmxt_helper.o
  CC    aarch64-softmmu/target-arm/gdbstub.o
  CC    aarch64-softmmu/target-arm/cpu64.o
  CC    aarch64-softmmu/target-arm/translate-a64.o
  CC    aarch64-softmmu/target-arm/helper-a64.o
  CC    aarch64-softmmu/target-arm/gdbstub64.o
  CC    aarch64-softmmu/target-arm/crypto_helper.o
  CC    aarch64-softmmu/target-arm/arm-powerctl.o
  GEN   trace/generated-helpers.c
  CC    aarch64-softmmu/trace/control-target.o
  CC    aarch64-softmmu/gdbstub-xml.o
  CC    aarch64-softmmu/trace/generated-helpers.o
/tmp/qemu-test/src/target-arm/translate-a64.c: In function ‘handle_shri_with_rndacc’:
/tmp/qemu-test/src/target-arm/translate-a64.c:6333: warning: ‘tcg_src_hi’ may be used uninitialized in this function
/tmp/qemu-test/src/target-arm/translate-a64.c: In function ‘disas_simd_scalar_two_reg_misc’:
/tmp/qemu-test/src/target-arm/translate-a64.c:8060: warning: ‘rmode’ may be used uninitialized in this function
  LINK  aarch64-softmmu/qemu-system-aarch64
  TEST  tests/qapi-schema/alternate-any.out
  TEST  tests/qapi-schema/alternate-array.out
  TEST  tests/qapi-schema/alternate-base.out
  TEST  tests/qapi-schema/alternate-clash.out
  TEST  tests/qapi-schema/alternate-conflict-dict.out
  TEST  tests/qapi-schema/alternate-conflict-string.out
  TEST  tests/qapi-schema/alternate-empty.out
  TEST  tests/qapi-schema/alternate-nested.out
  TEST  tests/qapi-schema/alternate-unknown.out
  TEST  tests/qapi-schema/args-alternate.out
  TEST  tests/qapi-schema/args-any.out
  TEST  tests/qapi-schema/args-array-empty.out
  TEST  tests/qapi-schema/args-array-unknown.out
  TEST  tests/qapi-schema/args-bad-boxed.out
  TEST  tests/qapi-schema/args-boxed-anon.out
  TEST  tests/qapi-schema/args-boxed-empty.out
  TEST  tests/qapi-schema/args-boxed-string.out
  TEST  tests/qapi-schema/args-int.out
  TEST  tests/qapi-schema/args-invalid.out
  TEST  tests/qapi-schema/args-member-array-bad.out
  TEST  tests/qapi-schema/args-member-case.out
  TEST  tests/qapi-schema/args-member-unknown.out
  TEST  tests/qapi-schema/args-name-clash.out
  TEST  tests/qapi-schema/args-union.out
  TEST  tests/qapi-schema/args-unknown.out
  TEST  tests/qapi-schema/bad-base.out
  TEST  tests/qapi-schema/bad-data.out
  TEST  tests/qapi-schema/bad-ident.out
  TEST  tests/qapi-schema/bad-type-bool.out
  TEST  tests/qapi-schema/bad-type-dict.out
  TEST  tests/qapi-schema/bad-type-int.out
  TEST  tests/qapi-schema/base-cycle-direct.out
  TEST  tests/qapi-schema/base-cycle-indirect.out
  TEST  tests/qapi-schema/command-int.out
  TEST  tests/qapi-schema/comments.out
  TEST  tests/qapi-schema/double-data.out
  TEST  tests/qapi-schema/double-type.out
  TEST  tests/qapi-schema/duplicate-key.out
  TEST  tests/qapi-schema/empty.out
  TEST  tests/qapi-schema/enum-bad-name.out
  TEST  tests/qapi-schema/enum-bad-prefix.out
  TEST  tests/qapi-schema/enum-clash-member.out
  TEST  tests/qapi-schema/enum-dict-member.out
  TEST  tests/qapi-schema/enum-int-member.out
  TEST  tests/qapi-schema/enum-member-case.out
  TEST  tests/qapi-schema/enum-missing-data.out
  TEST  tests/qapi-schema/enum-wrong-data.out
  TEST  tests/qapi-schema/escape-outside-string.out
  TEST  tests/qapi-schema/escape-too-big.out
  TEST  tests/qapi-schema/escape-too-short.out
  TEST  tests/qapi-schema/event-boxed-empty.out
  TEST  tests/qapi-schema/event-case.out
  TEST  tests/qapi-schema/event-nest-struct.out
  TEST  tests/qapi-schema/flat-union-array-branch.out
  TEST  tests/qapi-schema/flat-union-bad-base.out
  TEST  tests/qapi-schema/flat-union-bad-discriminator.out
  TEST  tests/qapi-schema/flat-union-base-any.out
  TEST  tests/qapi-schema/flat-union-base-union.out
  TEST  tests/qapi-schema/flat-union-clash-member.out
  TEST  tests/qapi-schema/flat-union-empty.out
  TEST  tests/qapi-schema/flat-union-incomplete-branch.out
  TEST  tests/qapi-schema/flat-union-inline.out
  TEST  tests/qapi-schema/flat-union-int-branch.out
  TEST  tests/qapi-schema/flat-union-invalid-branch-key.out
  TEST  tests/qapi-schema/flat-union-invalid-discriminator.out
  TEST  tests/qapi-schema/flat-union-no-base.out
  TEST  tests/qapi-schema/flat-union-optional-discriminator.out
  TEST  tests/qapi-schema/flat-union-string-discriminator.out
  TEST  tests/qapi-schema/funny-char.out
  TEST  tests/qapi-schema/ident-with-escape.out
  TEST  tests/qapi-schema/include-before-err.out
  TEST  tests/qapi-schema/include-cycle.out
  TEST  tests/qapi-schema/include-format-err.out
  TEST  tests/qapi-schema/include-nested-err.out
  TEST  tests/qapi-schema/include-no-file.out
  TEST  tests/qapi-schema/include-non-file.out
  TEST  tests/qapi-schema/include-relpath.out
  TEST  tests/qapi-schema/include-repetition.out
  TEST  tests/qapi-schema/include-self-cycle.out
  TEST  tests/qapi-schema/include-simple.out
  TEST  tests/qapi-schema/indented-expr.out
  TEST  tests/qapi-schema/leading-comma-list.out
  TEST  tests/qapi-schema/leading-comma-object.out
  TEST  tests/qapi-schema/missing-colon.out
  TEST  tests/qapi-schema/missing-comma-list.out
  TEST  tests/qapi-schema/missing-comma-object.out
  TEST  tests/qapi-schema/missing-type.out
  TEST  tests/qapi-schema/nested-struct-data.out
  TEST  tests/qapi-schema/non-objects.out
  TEST  tests/qapi-schema/qapi-schema-test.out
  TEST  tests/qapi-schema/quoted-structural-chars.out
  TEST  tests/qapi-schema/redefined-builtin.out
  TEST  tests/qapi-schema/redefined-command.out
  TEST  tests/qapi-schema/redefined-event.out
  TEST  tests/qapi-schema/redefined-type.out
  TEST  tests/qapi-schema/reserved-command-q.out
  TEST  tests/qapi-schema/reserved-enum-q.out
  TEST  tests/qapi-schema/reserved-member-has.out
  TEST  tests/qapi-schema/reserved-member-q.out
  TEST  tests/qapi-schema/reserved-member-u.out
  TEST  tests/qapi-schema/reserved-member-underscore.out
  TEST  tests/qapi-schema/reserved-type-kind.out
  TEST  tests/qapi-schema/reserved-type-list.out
  TEST  tests/qapi-schema/returns-alternate.out
  TEST  tests/qapi-schema/returns-array-bad.out
  TEST  tests/qapi-schema/returns-dict.out
  TEST  tests/qapi-schema/returns-unknown.out
  TEST  tests/qapi-schema/returns-whitelist.out
  TEST  tests/qapi-schema/struct-base-clash-deep.out
  TEST  tests/qapi-schema/struct-base-clash.out
  TEST  tests/qapi-schema/struct-data-invalid.out
  TEST  tests/qapi-schema/struct-member-invalid.out
  TEST  tests/qapi-schema/trailing-comma-list.out
  TEST  tests/qapi-schema/trailing-comma-object.out
  TEST  tests/qapi-schema/type-bypass-bad-gen.out
  TEST  tests/qapi-schema/unclosed-list.out
  TEST  tests/qapi-schema/unclosed-object.out
  TEST  tests/qapi-schema/unclosed-string.out
  TEST  tests/qapi-schema/unicode-str.out
  TEST  tests/qapi-schema/union-base-no-discriminator.out
  TEST  tests/qapi-schema/union-branch-case.out
  TEST  tests/qapi-schema/union-clash-branches.out
  TEST  tests/qapi-schema/union-empty.out
  TEST  tests/qapi-schema/union-invalid-base.out
  TEST  tests/qapi-schema/union-optional-branch.out
  TEST  tests/qapi-schema/union-unknown.out
  TEST  tests/qapi-schema/unknown-escape.out
  TEST  tests/qapi-schema/unknown-expr-key.out
  CC    tests/check-qdict.o
  CC    tests/check-qfloat.o
  CC    tests/check-qint.o
  CC    tests/check-qstring.o
  CC    tests/check-qlist.o
  CC    tests/check-qnull.o
  CC    tests/check-qjson.o
  CC    tests/test-qmp-output-visitor.o
  GEN   tests/test-qapi-visit.c
  GEN   tests/test-qapi-types.c
  GEN   tests/test-qapi-event.c
  GEN   tests/test-qmp-introspect.c
  CC    tests/test-clone-visitor.o
  CC    tests/test-qmp-input-visitor.o
  CC    tests/test-qmp-input-strict.o
  CC    tests/test-qmp-commands.o
  GEN   tests/test-qmp-marshal.c
  CC    tests/test-string-input-visitor.o
  CC    tests/test-string-output-visitor.o
  CC    tests/test-qmp-event.o
  CC    tests/test-opts-visitor.o
  CC    tests/test-coroutine.o
  CC    tests/test-visitor-serialization.o
  CC    tests/test-iov.o
  CC    tests/test-aio.o
  CC    tests/test-rfifolock.o
  CC    tests/test-throttle.o
  CC    tests/test-thread-pool.o
  CC    tests/test-hbitmap.o
  CC    tests/test-blockjob.o
  CC    tests/test-blockjob-txn.o
  CC    tests/test-x86-cpuid.o
  CC    tests/test-xbzrle.o
  CC    tests/test-vmstate.o
  CC    tests/test-cutils.o
  CC    tests/test-mul64.o
  CC    tests/test-int128.o
  CC    tests/rcutorture.o
  CC    tests/test-rcu-list.o
  CC    tests/test-qdist.o
  CC    tests/test-qht.o
  CC    tests/test-qht-par.o
/tmp/qemu-test/src/tests/test-int128.c:180: warning: ‘__noclone__’ attribute directive ignored
  CC    tests/qht-bench.o
  CC    tests/test-bitops.o
  CC    tests/check-qom-interface.o
  CC    tests/check-qom-proplist.o
  CC    tests/test-qemu-opts.o
  CC    tests/test-write-threshold.o
  CC    tests/test-crypto-hash.o
  CC    tests/test-crypto-cipher.o
  CC    tests/test-crypto-secret.o
  CC    tests/test-qga.o
  CC    tests/test-timed-average.o
  CC    tests/libqtest.o
  CC    tests/test-io-task.o
  CC    tests/test-io-channel-socket.o
  CC    tests/io-channel-helpers.o
  CC    tests/test-io-channel-file.o
  CC    tests/test-io-channel-command.o
  CC    tests/test-io-channel-buffer.o
  CC    tests/test-base64.o
  CC    tests/test-crypto-ivgen.o
  CC    tests/test-crypto-afsplit.o
  CC    tests/test-crypto-xts.o
  CC    tests/test-crypto-block.o
  CC    tests/test-logging.o
  CC    tests/test-replication.o
  CC    tests/test-bufferiszero.o
  CC    tests/test-uuid.o
  CC    tests/vhost-user-test.o
  CC    tests/libqos/pci.o
  CC    tests/libqos/fw_cfg.o
  CC    tests/libqos/malloc.o
  CC    tests/libqos/i2c.o
  CC    tests/libqos/libqos.o
  CC    tests/libqos/pci-pc.o
  CC    tests/libqos/malloc-pc.o
  CC    tests/libqos/libqos-pc.o
  CC    tests/libqos/ahci.o
  CC    tests/libqos/virtio.o
  CC    tests/libqos/virtio-pci.o
  CC    tests/libqos/virtio-mmio.o
  CC    tests/libqos/malloc-generic.o
  CC    tests/endianness-test.o
  CC    tests/fdc-test.o
  CC    tests/ide-test.o
  CC    tests/ahci-test.o
  CC    tests/hd-geo-test.o
  CC    tests/boot-order-test.o
  CC    tests/bios-tables-test.o
  CC    tests/boot-sector.o
/tmp/qemu-test/src/tests/ide-test.c: In function ‘cdrom_pio_impl’:
/tmp/qemu-test/src/tests/ide-test.c:739: warning: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result
/tmp/qemu-test/src/tests/ide-test.c: In function ‘test_cdrom_dma’:
/tmp/qemu-test/src/tests/ide-test.c:832: warning: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result
  CC    tests/boot-serial-test.o
  CC    tests/pxe-test.o
  CC    tests/rtc-test.o
  CC    tests/ipmi-kcs-test.o
  CC    tests/ipmi-bt-test.o
  CC    tests/i440fx-test.o
/tmp/qemu-test/src/tests/boot-sector.c: In function ‘boot_sector_init’:
/tmp/qemu-test/src/tests/boot-sector.c:80: warning: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result
  CC    tests/fw_cfg-test.o
  CC    tests/drive_del-test.o
  CC    tests/wdt_ib700-test.o
  CC    tests/tco-test.o
  CC    tests/e1000-test.o
  CC    tests/e1000e-test.o
  CC    tests/rtl8139-test.o
  CC    tests/pcnet-test.o
  CC    tests/eepro100-test.o
  CC    tests/ne2000-test.o
  CC    tests/nvme-test.o
  CC    tests/ac97-test.o
  CC    tests/es1370-test.o
  CC    tests/virtio-net-test.o
  CC    tests/virtio-balloon-test.o
  CC    tests/virtio-blk-test.o
  CC    tests/virtio-rng-test.o
  CC    tests/virtio-scsi-test.o
  CC    tests/virtio-serial-test.o
  CC    tests/virtio-console-test.o
  CC    tests/tpci200-test.o
  CC    tests/ipoctal232-test.o
  CC    tests/display-vga-test.o
  CC    tests/intel-hda-test.o
  CC    tests/ivshmem-test.o
  CC    tests/vmxnet3-test.o
  CC    tests/pvpanic-test.o
  CC    tests/i82801b11-test.o
  CC    tests/ioh3420-test.o
  CC    tests/usb-hcd-ohci-test.o
  CC    tests/libqos/usb.o
  CC    tests/usb-hcd-uhci-test.o
  CC    tests/usb-hcd-ehci-test.o
  CC    tests/usb-hcd-xhci-test.o
  CC    tests/pc-cpu-test.o
  CC    tests/q35-test.o
  CC    tests/test-netfilter.o
  CC    tests/test-filter-mirror.o
  CC    tests/test-filter-redirector.o
  CC    tests/postcopy-test.o
  CC    tests/test-x86-cpuid-compat.o
  CC    tests/device-introspect-test.o
  CC    tests/qom-test.o
  CC    tests/ptimer-test.o
  CC    tests/ptimer-test-stubs.o
  LINK  tests/check-qdict
  LINK  tests/check-qfloat
  LINK  tests/check-qint
  LINK  tests/check-qstring
  LINK  tests/check-qlist
  LINK  tests/check-qnull
  LINK  tests/check-qjson
  CC    tests/test-qapi-visit.o
  CC    tests/test-qapi-types.o
  CC    tests/test-qapi-event.o
  CC    tests/test-qmp-introspect.o
  CC    tests/test-qmp-marshal.o
  LINK  tests/test-coroutine
  LINK  tests/test-iov
  LINK  tests/test-aio
  LINK  tests/test-rfifolock
  LINK  tests/test-throttle
  LINK  tests/test-thread-pool
  LINK  tests/test-hbitmap
  LINK  tests/test-blockjob
  LINK  tests/test-blockjob-txn
  LINK  tests/test-x86-cpuid
  LINK  tests/test-xbzrle
  LINK  tests/test-vmstate
  LINK  tests/test-cutils
  LINK  tests/test-mul64
  LINK  tests/test-int128
  LINK  tests/rcutorture
  LINK  tests/test-rcu-list
  LINK  tests/test-qdist
  LINK  tests/test-qht
  LINK  tests/qht-bench
  LINK  tests/test-bitops
  LINK  tests/check-qom-interface
  LINK  tests/check-qom-proplist
  LINK  tests/test-qemu-opts
  LINK  tests/test-write-threshold
  LINK  tests/test-crypto-hash
  LINK  tests/test-crypto-cipher
  LINK  tests/test-crypto-secret
  LINK  tests/test-qga
  LINK  tests/test-timed-average
  LINK  tests/test-io-task
  LINK  tests/test-io-channel-socket
  LINK  tests/test-io-channel-file
  LINK  tests/test-io-channel-command
  LINK  tests/test-io-channel-buffer
  LINK  tests/test-base64
  LINK  tests/test-crypto-ivgen
  LINK  tests/test-crypto-afsplit
  LINK  tests/test-crypto-xts
  LINK  tests/test-crypto-block
  LINK  tests/test-logging
  LINK  tests/test-replication
  LINK  tests/test-bufferiszero
  LINK  tests/test-uuid
  LINK  tests/vhost-user-test
  LINK  tests/endianness-test
  LINK  tests/fdc-test
  LINK  tests/ide-test
  LINK  tests/ahci-test
  LINK  tests/hd-geo-test
  LINK  tests/boot-order-test
  LINK  tests/bios-tables-test
  LINK  tests/boot-serial-test
  LINK  tests/pxe-test
  LINK  tests/rtc-test
  LINK  tests/ipmi-kcs-test
  LINK  tests/ipmi-bt-test
  LINK  tests/i440fx-test
  LINK  tests/fw_cfg-test
  LINK  tests/drive_del-test
  LINK  tests/wdt_ib700-test
  LINK  tests/tco-test
  LINK  tests/e1000-test
  LINK  tests/e1000e-test
  LINK  tests/rtl8139-test
  LINK  tests/pcnet-test
  LINK  tests/eepro100-test
  LINK  tests/ne2000-test
  LINK  tests/nvme-test
  LINK  tests/ac97-test
  LINK  tests/es1370-test
  LINK  tests/virtio-net-test
  LINK  tests/virtio-balloon-test
  LINK  tests/virtio-blk-test
  LINK  tests/virtio-rng-test
  LINK  tests/virtio-scsi-test
  LINK  tests/virtio-serial-test
  LINK  tests/virtio-console-test
  LINK  tests/tpci200-test
  LINK  tests/ipoctal232-test
  LINK  tests/display-vga-test
  LINK  tests/intel-hda-test
  LINK  tests/ivshmem-test
  LINK  tests/vmxnet3-test
  LINK  tests/pvpanic-test
  LINK  tests/i82801b11-test
  LINK  tests/ioh3420-test
  LINK  tests/usb-hcd-ohci-test
  LINK  tests/usb-hcd-uhci-test
  LINK  tests/usb-hcd-ehci-test
  LINK  tests/usb-hcd-xhci-test
  LINK  tests/pc-cpu-test
  LINK  tests/q35-test
  LINK  tests/test-netfilter
  LINK  tests/test-filter-mirror
  LINK  tests/test-filter-redirector
  LINK  tests/postcopy-test
  LINK  tests/test-x86-cpuid-compat
  LINK  tests/device-introspect-test
  LINK  tests/qom-test
  LINK  tests/ptimer-test
GTESTER tests/check-qdict
GTESTER tests/check-qfloat
GTESTER tests/check-qint
GTESTER tests/check-qstring
GTESTER tests/check-qlist
GTESTER tests/check-qnull
GTESTER tests/check-qjson
  LINK  tests/test-qmp-output-visitor
  LINK  tests/test-clone-visitor
  LINK  tests/test-qmp-input-visitor
  LINK  tests/test-qmp-input-strict
  LINK  tests/test-qmp-commands
  LINK  tests/test-string-input-visitor
  LINK  tests/test-string-output-visitor
  LINK  tests/test-qmp-event
  LINK  tests/test-opts-visitor
GTESTER tests/test-coroutine
  LINK  tests/test-visitor-serialization
GTESTER tests/test-iov
GTESTER tests/test-aio
GTESTER tests/test-rfifolock
GTESTER tests/test-throttle
GTESTER tests/test-thread-pool
GTESTER tests/test-hbitmap
GTESTER tests/test-blockjob
GTESTER tests/test-blockjob-txn
GTESTER tests/test-x86-cpuid
GTESTER tests/test-xbzrle
GTESTER tests/test-vmstate
GTESTER tests/test-cutils
GTESTER tests/test-mul64
GTESTER tests/test-int128
GTESTER tests/rcutorture
GTESTER tests/test-rcu-list
GTESTER tests/test-qdist
GTESTER tests/test-qht
  LINK  tests/test-qht-par
GTESTER tests/test-bitops
GTESTER tests/check-qom-interface
GTESTER tests/check-qom-proplist
GTESTER tests/test-qemu-opts
GTESTER tests/test-write-threshold
GTESTER tests/test-crypto-hash
GTESTER tests/test-crypto-cipher
GTESTER tests/test-crypto-secret
GTESTER tests/test-qga
GTESTER tests/test-timed-average
GTESTER tests/test-io-task
GTESTER tests/test-io-channel-socket
GTESTER tests/test-io-channel-file
GTESTER tests/test-io-channel-command
GTESTER tests/test-io-channel-buffer
GTESTER tests/test-base64
GTESTER tests/test-crypto-ivgen
GTESTER tests/test-crypto-afsplit
GTESTER tests/test-crypto-xts
GTESTER tests/test-crypto-block
GTESTER tests/test-logging
GTESTER tests/test-replication
GTESTER tests/test-bufferiszero
GTESTER tests/test-uuid
GTESTER check-qtest-x86_64
GTESTER check-qtest-aarch64
GTESTER tests/test-qmp-output-visitor
GTESTER tests/test-clone-visitor
GTESTER tests/test-qmp-input-visitor
GTESTER tests/test-qmp-input-strict
GTESTER tests/test-qmp-commands
GTESTER tests/test-string-input-visitor
GTESTER tests/test-string-output-visitor
GTESTER tests/test-qmp-event
GTESTER tests/test-opts-visitor
GTESTER tests/test-visitor-serialization
GTESTER tests/test-qht-par
qemu-system-x86_64: Failed to unlink socket .: Is a directory
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
  BUILD fedora
  ARCHIVE qemu.tgz
  ARCHIVE dtc.tgz
  COPY RUNNER
  RUN test-mingw in fedora
Packages installed:
PyYAML-3.11-12.fc24.x86_64
SDL-devel-1.2.15-21.fc24.x86_64
bc-1.06.95-16.fc24.x86_64
bison-3.0.4-4.fc24.x86_64
ccache-3.3.1-1.fc24.x86_64
clang-3.8.0-2.fc24.x86_64
findutils-4.6.0-7.fc24.x86_64
flex-2.6.0-2.fc24.x86_64
gcc-6.1.1-3.fc24.x86_64
gcc-c++-6.1.1-3.fc24.x86_64
git-2.7.4-2.fc24.x86_64
glib2-devel-2.48.2-1.fc24.x86_64
libfdt-devel-1.4.2-1.fc24.x86_64
make-4.1-5.fc24.x86_64
mingw32-SDL-1.2.15-7.fc24.noarch
mingw32-bzip2-1.0.6-7.fc24.noarch
mingw32-curl-7.47.0-1.fc24.noarch
mingw32-glib2-2.48.2-1.fc24.noarch
mingw32-gmp-6.1.0-1.fc24.noarch
mingw32-gnutls-3.4.14-1.fc24.noarch
mingw32-gtk2-2.24.30-1.fc24.noarch
mingw32-gtk3-3.20.9-1.fc24.noarch
mingw32-libjpeg-turbo-1.4.2-1.fc24.noarch
mingw32-libpng-1.6.23-1.fc24.noarch
mingw32-libssh2-1.4.3-5.fc24.noarch
mingw32-libtasn1-4.5-2.fc24.noarch
mingw32-nettle-3.2-1.fc24.noarch
mingw32-pixman-0.34.0-1.fc24.noarch
mingw32-pkg-config-0.28-6.fc24.x86_64
mingw64-SDL-1.2.15-7.fc24.noarch
mingw64-bzip2-1.0.6-7.fc24.noarch
mingw64-curl-7.47.0-1.fc24.noarch
mingw64-glib2-2.48.2-1.fc24.noarch
mingw64-gmp-6.1.0-1.fc24.noarch
mingw64-gnutls-3.4.14-1.fc24.noarch
mingw64-gtk2-2.24.30-1.fc24.noarch
mingw64-gtk3-3.20.9-1.fc24.noarch
mingw64-libjpeg-turbo-1.4.2-1.fc24.noarch
mingw64-libpng-1.6.23-1.fc24.noarch
mingw64-libssh2-1.4.3-5.fc24.noarch
mingw64-libtasn1-4.5-2.fc24.noarch
mingw64-nettle-3.2-1.fc24.noarch
mingw64-pixman-0.34.0-1.fc24.noarch
mingw64-pkg-config-0.28-6.fc24.x86_64
perl-5.22.2-362.fc24.x86_64
pixman-devel-0.34.0-2.fc24.x86_64
sparse-0.5.0-7.fc24.x86_64
tar-1.28-7.fc24.x86_64
which-2.20-13.fc24.x86_64
zlib-devel-1.2.8-10.fc24.x86_64

Environment variables:
PACKAGES=ccache git tar PyYAML sparse flex bison     glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel     gcc gcc-c++ clang make perl which bc findutils     mingw32-pixman mingw32-glib2 mingw32-gmp mingw32-SDL mingw32-pkg-config     mingw32-gtk2 mingw32-gtk3 mingw32-gnutls mingw32-nettle mingw32-libtasn1     mingw32-libjpeg-turbo mingw32-libpng mingw32-curl mingw32-libssh2     mingw32-bzip2     mingw64-pixman mingw64-glib2 mingw64-gmp mingw64-SDL mingw64-pkg-config     mingw64-gtk2 mingw64-gtk3 mingw64-gnutls mingw64-nettle mingw64-libtasn1     mingw64-libjpeg-turbo mingw64-libpng mingw64-curl mingw64-libssh2     mingw64-bzip2
HOSTNAME=
TERM=xterm
MAKEFLAGS= -j8
HISTSIZE=1000
J=8
USER=root
CCACHE_DIR=/var/tmp/ccache
EXTRA_CONFIGURE_OPTS=
V=
SHOW_ENV=1
MAIL=/var/spool/mail/root
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
TARGET_LIST=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
TEST_DIR=/tmp/qemu-test
LOGNAME=root
LESSOPEN=||/usr/bin/lesspipe.sh %s
FEATURES=mingw clang pyyaml dtc
DEBUG=
_=/usr/bin/env

Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/tmp/qemu-test/src/tests/docker/install --cross-prefix=x86_64-w64-mingw32- --enable-trace-backends=simple --enable-debug --enable-gnutls --enable-nettle --enable-curl --enable-vnc --enable-bzip2 --enable-guest-agent --with-sdlabi=1.2 --with-gtkabi=2.0
Install prefix    /tmp/qemu-test/src/tests/docker/install
BIOS directory    /tmp/qemu-test/src/tests/docker/install
binary directory  /tmp/qemu-test/src/tests/docker/install
library directory /tmp/qemu-test/src/tests/docker/install/lib
module directory  /tmp/qemu-test/src/tests/docker/install/lib
libexec directory /tmp/qemu-test/src/tests/docker/install/libexec
include directory /tmp/qemu-test/src/tests/docker/install/include
config directory  /tmp/qemu-test/src/tests/docker/install
local state directory   queried at runtime
Windows SDK       no
Source path       /tmp/qemu-test/src
C compiler        x86_64-w64-mingw32-gcc
Host C compiler   cc
C++ compiler      x86_64-w64-mingw32-g++
Objective-C compiler clang
ARFLAGS           rv
CFLAGS            -g 
QEMU_CFLAGS       -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/pixman-1  -I$(SRC_PATH)/dtc/libfdt -Werror -mms-bitfields -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/glib-2.0 -I/usr/x86_64-w64-mingw32/sys-root/mingw/lib/glib-2.0/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include  -m64 -mthreads -D__USE_MINGW_ANSI_STDIO=1 -DWIN32_LEAN_AND_MEAN -DWINVER=0x501 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv  -Wendif-labels -Wno-shift-negative-value -Wmissing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-strong -I/usr/x86_64-w64-mingw32/sys-root/mingw/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/p11-kit-1 -I/usr/x86_64-w64-mingw32/sys-root/mingw/include  -I/usr/x86_64-w64-mingw32/sys-root/mingw/include   -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/libpng16 
LDFLAGS           -Wl,--nxcompat -Wl,--no-seh -Wl,--dynamicbase -Wl,--warn-common -m64 -g 
make              make
install           install
python            python -B
smbd              /usr/sbin/smbd
module support    no
host CPU          x86_64
host big endian   no
target list       x86_64-softmmu aarch64-softmmu
tcg debug enabled yes
gprof enabled     no
sparse enabled    no
strip binaries    no
profiler          no
static build      no
pixman            system
SDL support       yes (1.2.15)
GTK support       yes (2.24.30)
GTK GL support    no
VTE support       no 
TLS priority      NORMAL
GNUTLS support    yes
GNUTLS rnd        yes
libgcrypt         no
libgcrypt kdf     no
nettle            yes (3.2)
nettle kdf        yes
libtasn1          yes
curses support    no
virgl support     no
curl support      yes
mingw32 support   yes
Audio drivers     dsound
Block whitelist (rw) 
Block whitelist (ro) 
VirtFS support    no
VNC support       yes
VNC SASL support  no
VNC JPEG support  yes
VNC PNG support   yes
xen support       no
brlapi support    no
bluez  support    no
Documentation     no
PIE               no
vde support       no
netmap support    no
Linux AIO support no
ATTR/XATTR support no
Install blobs     yes
KVM support       no
RDMA support      no
TCG interpreter   no
fdt support       yes
preadv support    no
fdatasync         no
madvise           no
posix_madvise     no
libcap-ng support no
vhost-net support no
vhost-scsi support no
vhost-vsock support no
Trace backends    simple
Trace output file trace-<pid>
spice support     no 
rbd support       no
xfsctl support    no
smartcard support no
libusb            no
usb net redir     no
OpenGL support    no
OpenGL dmabufs    no
libiscsi support  no
libnfs support    no
build guest agent yes
QGA VSS support   no
QGA w32 disk info yes
QGA MSI support   no
seccomp support   no
coroutine backend win32
coroutine pool    yes
GlusterFS support no
Archipelago support no
gcov              gcov
gcov enabled      no
TPM support       yes
libssh2 support   yes
TPM passthrough   no
QOM debugging     yes
lzo support       no
snappy support    no
bzip2 support     yes
NUMA host support no
tcmalloc support  no
jemalloc support  no
avx2 optimization yes
replication support yes
mkdir -p dtc/libfdt
  GEN   x86_64-softmmu/config-devices.mak.tmp
mkdir -p dtc/tests
  GEN   aarch64-softmmu/config-devices.mak.tmp
  GEN   config-host.h
  GEN   qemu-options.def
  GEN   qmp-commands.h
  GEN   qapi-types.h
  GEN   qapi-visit.h
  GEN   qapi-event.h
  GEN   x86_64-softmmu/config-devices.mak
  GEN   aarch64-softmmu/config-devices.mak
  GEN   qmp-introspect.h
  GEN   module_block.h
  GEN   tests/test-qapi-types.h
  GEN   tests/test-qapi-visit.h
  GEN   tests/test-qmp-commands.h
  GEN   tests/test-qapi-event.h
  GEN   tests/test-qmp-introspect.h
  GEN   config-all-devices.mak
  GEN   trace/generated-events.h
	 DEP /tmp/qemu-test/src/dtc/tests/dumptrees.c
	 DEP /tmp/qemu-test/src/dtc/tests/trees.S
	 DEP /tmp/qemu-test/src/dtc/tests/testutils.c
	 DEP /tmp/qemu-test/src/dtc/tests/value-labels.c
  GEN   trace/generated-tracers.h
	 DEP /tmp/qemu-test/src/dtc/tests/asm_tree_dump.c
	 DEP /tmp/qemu-test/src/dtc/tests/truncated_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/subnode_iterate.c
  GEN   trace/generated-tcg-tracers.h
	 DEP /tmp/qemu-test/src/dtc/tests/integer-expressions.c
	 DEP /tmp/qemu-test/src/dtc/tests/utilfdt_test.c
  GEN   trace/generated-helpers-wrappers.h
	 DEP /tmp/qemu-test/src/dtc/tests/path_offset_aliases.c
  GEN   trace/generated-helpers.h
	 DEP /tmp/qemu-test/src/dtc/tests/add_subnode_with_nops.c
	 DEP /tmp/qemu-test/src/dtc/tests/dtbs_equal_unordered.c
	 DEP /tmp/qemu-test/src/dtc/tests/dtb_reverse.c
	 DEP /tmp/qemu-test/src/dtc/tests/dtbs_equal_ordered.c
	 DEP /tmp/qemu-test/src/dtc/tests/extra-terminating-null.c
	 DEP /tmp/qemu-test/src/dtc/tests/incbin.c
	 DEP /tmp/qemu-test/src/dtc/tests/boot-cpuid.c
	 DEP /tmp/qemu-test/src/dtc/tests/phandle_format.c
	 DEP /tmp/qemu-test/src/dtc/tests/path-references.c
	 DEP /tmp/qemu-test/src/dtc/tests/references.c
	 DEP /tmp/qemu-test/src/dtc/tests/propname_escapes.c
	 DEP /tmp/qemu-test/src/dtc/tests/string_escapes.c
	 DEP /tmp/qemu-test/src/dtc/tests/appendprop2.c
	 DEP /tmp/qemu-test/src/dtc/tests/appendprop1.c
	 DEP /tmp/qemu-test/src/dtc/tests/del_node.c
	 DEP /tmp/qemu-test/src/dtc/tests/del_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/setprop.c
	 DEP /tmp/qemu-test/src/dtc/tests/set_name.c
	 DEP /tmp/qemu-test/src/dtc/tests/rw_tree1.c
	 DEP /tmp/qemu-test/src/dtc/tests/open_pack.c
	 DEP /tmp/qemu-test/src/dtc/tests/nopulate.c
	 DEP /tmp/qemu-test/src/dtc/tests/mangle-layout.c
	 DEP /tmp/qemu-test/src/dtc/tests/move_and_save.c
	 DEP /tmp/qemu-test/src/dtc/tests/sw_tree1.c
	 DEP /tmp/qemu-test/src/dtc/tests/nop_node.c
	 DEP /tmp/qemu-test/src/dtc/tests/nop_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/setprop_inplace.c
	 DEP /tmp/qemu-test/src/dtc/tests/notfound.c
	 DEP /tmp/qemu-test/src/dtc/tests/sized_cells.c
	 DEP /tmp/qemu-test/src/dtc/tests/char_literal.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_alias.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_compatible.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_check_compatible.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_phandle.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_prop_value.c
	 DEP /tmp/qemu-test/src/dtc/tests/supernode_atdepth_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/parent_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_path.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_phandle.c
	 DEP /tmp/qemu-test/src/dtc/tests/getprop.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_name.c
	 DEP /tmp/qemu-test/src/dtc/tests/path_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/find_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/subnode_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/root_node.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_mem_rsv.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_empty_tree.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_strerror.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_rw.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_sw.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_wip.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_ro.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt.c
	 DEP /tmp/qemu-test/src/dtc/util.c
	 DEP /tmp/qemu-test/src/dtc/fdtput.c
	 DEP /tmp/qemu-test/src/dtc/fdtget.c
	 DEP /tmp/qemu-test/src/dtc/fdtdump.c
	 LEX convert-dtsv0-lexer.lex.c
	 DEP /tmp/qemu-test/src/dtc/srcpos.c
	 BISON dtc-parser.tab.c
	 LEX dtc-lexer.lex.c
	 DEP /tmp/qemu-test/src/dtc/treesource.c
	 DEP /tmp/qemu-test/src/dtc/livetree.c
	 DEP /tmp/qemu-test/src/dtc/fstree.c
	 DEP /tmp/qemu-test/src/dtc/flattree.c
	 DEP /tmp/qemu-test/src/dtc/dtc.c
	 DEP /tmp/qemu-test/src/dtc/data.c
	 DEP /tmp/qemu-test/src/dtc/checks.c
	 DEP convert-dtsv0-lexer.lex.c
	 DEP dtc-parser.tab.c
	 DEP dtc-lexer.lex.c
	CHK version_gen.h
	UPD version_gen.h
	 DEP /tmp/qemu-test/src/dtc/util.c
	 CC libfdt/fdt.o
	 CC libfdt/fdt_sw.o
	 CC libfdt/fdt_wip.o
	 CC libfdt/fdt_ro.o
	 CC libfdt/fdt_rw.o
	 CC libfdt/fdt_strerror.o
	 CC libfdt/fdt_empty_tree.o
	 AR libfdt/libfdt.a
x86_64-w64-mingw32-ar: creating libfdt/libfdt.a
a - libfdt/fdt.o
a - libfdt/fdt_ro.o
a - libfdt/fdt_wip.o
a - libfdt/fdt_sw.o
a - libfdt/fdt_rw.o
a - libfdt/fdt_strerror.o
a - libfdt/fdt_empty_tree.o
  RC    version.lo
  RC    version.o
  GEN   qga/qapi-generated/qga-qapi-types.h
  GEN   qga/qapi-generated/qga-qapi-visit.h
  GEN   qga/qapi-generated/qga-qmp-commands.h
  GEN   qga/qapi-generated/qga-qapi-types.c
  GEN   qga/qapi-generated/qga-qapi-visit.c
  GEN   qga/qapi-generated/qga-qmp-marshal.c
  GEN   qmp-introspect.c
  GEN   qapi-types.c
  GEN   qapi-visit.c
  GEN   qapi-event.c
  CC    qapi/qapi-visit-core.o
  CC    qapi/qapi-dealloc-visitor.o
  CC    qapi/qmp-input-visitor.o
  CC    qapi/qmp-output-visitor.o
  CC    qapi/qmp-registry.o
  CC    qapi/qmp-dispatch.o
  CC    qapi/string-input-visitor.o
  CC    qapi/string-output-visitor.o
  CC    qapi/opts-visitor.o
  CC    qapi/qapi-clone-visitor.o
  CC    qapi/qmp-event.o
  CC    qapi/qapi-util.o
  CC    qobject/qnull.o
  CC    qobject/qint.o
  CC    qobject/qstring.o
  CC    qobject/qdict.o
  CC    qobject/qlist.o
  CC    qobject/qfloat.o
  CC    qobject/qbool.o
  CC    qobject/qobject.o
  CC    qobject/qjson.o
  CC    qobject/json-lexer.o
  CC    qobject/json-streamer.o
  CC    qobject/json-parser.o
  GEN   trace/generated-events.c
  GEN   trace/generated-tracers.c
  CC    trace/simple.o
  CC    trace/control.o
  CC    trace/qmp.o
  CC    util/osdep.o
  CC    util/cutils.o
  CC    util/unicode.o
  CC    util/qemu-timer-common.o
  CC    util/bufferiszero.o
  CC    util/event_notifier-win32.o
  CC    util/oslib-win32.o
  CC    util/qemu-thread-win32.o
  CC    util/envlist.o
  CC    util/path.o
  CC    util/module.o
  CC    util/bitmap.o
  CC    util/bitops.o
  CC    util/hbitmap.o
  CC    util/fifo8.o
  CC    util/acl.o
  CC    util/error.o
  CC    util/qemu-error.o
  CC    util/id.o
  CC    util/iov.o
  CC    util/qemu-config.o
  CC    util/qemu-sockets.o
  CC    util/uri.o
  CC    util/notify.o
  CC    util/qemu-option.o
  CC    util/qemu-progress.o
  CC    util/hexdump.o
  CC    util/crc32c.o
  CC    util/uuid.o
  CC    util/throttle.o
  CC    util/getauxval.o
  CC    util/readline.o
  CC    util/rfifolock.o
  CC    util/rcu.o
  CC    util/qemu-coroutine.o
  CC    util/qemu-coroutine-lock.o
  CC    util/qemu-coroutine-io.o
  CC    util/qemu-coroutine-sleep.o
  CC    util/coroutine-win32.o
  CC    util/buffer.o
  CC    util/timed-average.o
  CC    util/base64.o
  CC    util/log.o
  CC    util/qdist.o
  CC    util/qht.o
  CC    util/range.o
  CC    crypto/pbkdf-stub.o
  CC    stubs/arch-query-cpu-def.o
  CC    stubs/arch-query-cpu-model-expansion.o
  CC    stubs/arch-query-cpu-model-comparison.o
  CC    stubs/arch-query-cpu-model-baseline.o
  CC    stubs/bdrv-next-monitor-owned.o
  CC    stubs/blk-commit-all.o
  CC    stubs/blockdev-close-all-bdrv-states.o
  CC    stubs/clock-warp.o
  CC    stubs/cpu-get-clock.o
  CC    stubs/cpu-get-icount.o
  CC    stubs/dump.o
  CC    stubs/fdset-add-fd.o
  CC    stubs/fdset-find-fd.o
  CC    stubs/fdset-get-fd.o
  CC    stubs/fdset-remove-fd.o
  CC    stubs/gdbstub.o
  CC    stubs/get-fd.o
  CC    stubs/get-next-serial.o
  CC    stubs/get-vm-name.o
  CC    stubs/iothread-lock.o
  CC    stubs/is-daemonized.o
  CC    stubs/machine-init-done.o
  CC    stubs/migr-blocker.o
  CC    stubs/mon-is-qmp.o
  CC    stubs/mon-printf.o
  CC    stubs/monitor-init.o
  CC    stubs/notify-event.o
  CC    stubs/qtest.o
  CC    stubs/replay.o
  CC    stubs/replay-user.o
  CC    stubs/reset.o
  CC    stubs/runstate-check.o
  CC    stubs/set-fd-handler.o
  CC    stubs/slirp.o
  CC    stubs/sysbus.o
  CC    stubs/trace-control.o
  CC    stubs/uuid.o
  CC    stubs/vm-stop.o
  CC    stubs/vmstate.o
  CC    stubs/fd-register.o
  CC    stubs/cpus.o
  CC    stubs/kvm.o
  CC    stubs/qmp_pc_dimm_device_list.o
  CC    stubs/target-monitor-defs.o
  CC    stubs/target-get-monitor-def.o
  CC    stubs/vhost.o
  CC    stubs/iohandler.o
  CC    stubs/smbios_type_38.o
  CC    stubs/ipmi.o
  CC    stubs/pc_madt_cpu_entry.o
  GEN   qemu-img-cmds.h
  CC    async.o
  CC    thread-pool.o
  CC    blockjob.o
  CC    block.o
  CC    main-loop.o
  CC    iohandler.o
  CC    qemu-timer.o
  CC    aio-win32.o
  CC    qemu-io-cmds.o
  CC    replication.o
  CC    block/raw_bsd.o
  CC    block/qcow.o
  CC    block/vdi.o
  CC    block/vmdk.o
  CC    block/cloop.o
  CC    block/bochs.o
  CC    block/vpc.o
  CC    block/vvfat.o
  CC    block/dmg.o
  CC    block/qcow2.o
  CC    block/qcow2-refcount.o
  CC    block/qcow2-cluster.o
  CC    block/qcow2-snapshot.o
  CC    block/qcow2-cache.o
  CC    block/qed.o
  CC    block/qed-gencb.o
  CC    block/qed-l2-cache.o
  CC    block/qed-table.o
  CC    block/qed-cluster.o
  CC    block/qed-check.o
  CC    block/vhdx.o
  CC    block/vhdx-endian.o
  CC    block/vhdx-log.o
  CC    block/quorum.o
  CC    block/parallels.o
  CC    block/blkdebug.o
  CC    block/blkverify.o
  CC    block/blkreplay.o
  CC    block/block-backend.o
  CC    block/snapshot.o
  CC    block/qapi.o
  CC    block/raw-win32.o
  CC    block/win32-aio.o
  CC    block/null.o
  CC    block/mirror.o
  CC    block/commit.o
  CC    block/io.o
  CC    block/throttle-groups.o
  CC    block/nbd.o
  CC    block/nbd-client.o
  CC    block/sheepdog.o
  CC    block/accounting.o
  CC    block/dirty-bitmap.o
  CC    block/write-threshold.o
  CC    block/backup.o
  CC    block/replication.o
  CC    block/crypto.o
  CC    nbd/server.o
  CC    nbd/client.o
  CC    nbd/common.o
  CC    block/curl.o
  CC    block/ssh.o
  CC    crypto/init.o
  CC    crypto/hash.o
  CC    crypto/hash-nettle.o
  CC    crypto/aes.o
  CC    crypto/desrfb.o
  CC    crypto/cipher.o
  CC    crypto/tlscreds.o
  CC    crypto/tlscredsanon.o
  CC    crypto/tlscredsx509.o
  CC    crypto/tlssession.o
  CC    crypto/secret.o
  CC    crypto/random-gnutls.o
  CC    crypto/pbkdf.o
  CC    crypto/pbkdf-nettle.o
  CC    crypto/ivgen.o
  CC    crypto/ivgen-essiv.o
  CC    crypto/ivgen-plain.o
  CC    crypto/ivgen-plain64.o
  CC    crypto/afsplit.o
  CC    crypto/xts.o
  CC    crypto/block.o
  CC    crypto/block-qcow.o
  CC    crypto/block-luks.o
  CC    io/channel.o
  CC    io/channel-buffer.o
  CC    io/channel-command.o
  CC    io/channel-file.o
  CC    io/channel-socket.o
  CC    io/channel-tls.o
  CC    io/channel-watch.o
  CC    io/channel-websock.o
  CC    io/channel-util.o
  CC    io/task.o
  CC    qom/object.o
  CC    qom/container.o
  CC    qom/qom-qobject.o
  CC    qom/object_interfaces.o
  CC    qemu-io.o
  CC    blockdev.o
  CC    blockdev-nbd.o
  CC    iothread.o
  CC    qdev-monitor.o
  CC    device-hotplug.o
  CC    os-win32.o
  CC    qemu-char.o
  CC    page_cache.o
  CC    accel.o
  CC    bt-host.o
  CC    bt-vhci.o
  CC    dma-helpers.o
  CC    vl.o
  CC    tpm.o
  CC    device_tree.o
  GEN   qmp-marshal.c
  CC    qmp.o
  CC    hmp.o
  CC    tcg-runtime.o
  CC    cpus-common.o
  CC    audio/audio.o
  CC    audio/noaudio.o
  CC    audio/wavaudio.o
  CC    audio/mixeng.o
  CC    audio/sdlaudio.o
  CC    audio/dsoundaudio.o
  CC    audio/audio_win_int.o
  CC    audio/wavcapture.o
  CC    backends/rng.o
  CC    backends/rng-egd.o
  CC    backends/msmouse.o
  CC    backends/testdev.o
  CC    backends/tpm.o
  CC    backends/hostmem.o
  CC    backends/hostmem-ram.o
  CC    block/stream.o
  CC    disas/arm.o
  CXX   disas/arm-a64.o
  CC    disas/i386.o
  CXX   disas/libvixl/vixl/utils.o
  CXX   disas/libvixl/vixl/compiler-intrinsics.o
  CXX   disas/libvixl/vixl/a64/instructions-a64.o
  CXX   disas/libvixl/vixl/a64/decoder-a64.o
  CXX   disas/libvixl/vixl/a64/disasm-a64.o
  CC    hw/acpi/core.o
  CC    hw/acpi/piix4.o
  CC    hw/acpi/pcihp.o
  CC    hw/acpi/ich9.o
  CC    hw/acpi/tco.o
  CC    hw/acpi/cpu_hotplug.o
  CC    hw/acpi/memory_hotplug.o
  CC    hw/acpi/memory_hotplug_acpi_table.o
  CC    hw/acpi/cpu.o
  CC    hw/acpi/acpi_interface.o
  CC    hw/acpi/bios-linker-loader.o
  CC    hw/acpi/aml-build.o
  CC    hw/acpi/ipmi.o
  CC    hw/audio/sb16.o
  CC    hw/audio/es1370.o
  CC    hw/audio/ac97.o
  CC    hw/audio/fmopl.o
  CC    hw/audio/adlib.o
  CC    hw/audio/gus.o
  CC    hw/audio/gusemu_hal.o
  CC    hw/audio/gusemu_mixer.o
  CC    hw/audio/cs4231a.o
  CC    hw/audio/intel-hda.o
  CC    hw/audio/hda-codec.o
  CC    hw/audio/pcspk.o
  CC    hw/audio/wm8750.o
  CC    hw/audio/pl041.o
  CC    hw/audio/lm4549.o
  CC    hw/audio/marvell_88w8618.o
  CC    hw/block/block.o
  CC    hw/block/cdrom.o
  CC    hw/block/hd-geometry.o
  CC    hw/block/fdc.o
  CC    hw/block/m25p80.o
  CC    hw/block/nand.o
  CC    hw/block/pflash_cfi01.o
  CC    hw/block/ecc.o
  CC    hw/block/pflash_cfi02.o
  CC    hw/block/onenand.o
  CC    hw/block/nvme.o
  CC    hw/bt/core.o
  CC    hw/bt/l2cap.o
  CC    hw/bt/sdp.o
  CC    hw/bt/hci.o
  CC    hw/bt/hid.o
  CC    hw/bt/hci-csr.o
  CC    hw/char/ipoctal232.o
  CC    hw/char/parallel.o
  CC    hw/char/pl011.o
  CC    hw/char/serial.o
  CC    hw/char/serial-isa.o
  CC    hw/char/serial-pci.o
  CC    hw/char/virtio-console.o
  CC    hw/char/cadence_uart.o
  CC    hw/char/debugcon.o
  CC    hw/char/imx_serial.o
  CC    hw/core/qdev.o
  CC    hw/core/qdev-properties.o
  CC    hw/core/bus.o
  CC    hw/core/fw-path-provider.o
  CC    hw/core/irq.o
  CC    hw/core/hotplug.o
  CC    hw/core/ptimer.o
  CC    hw/core/sysbus.o
  CC    hw/core/machine.o
  CC    hw/core/loader.o
  CC    hw/core/null-machine.o
  CC    hw/core/qdev-properties-system.o
  CC    hw/core/register.o
  CC    hw/core/platform-bus.o
  CC    hw/display/ads7846.o
  CC    hw/display/cirrus_vga.o
  CC    hw/display/pl110.o
  CC    hw/display/ssd0303.o
  CC    hw/display/ssd0323.o
  CC    hw/display/vga-pci.o
  CC    hw/display/vga-isa.o
  CC    hw/display/vmware_vga.o
  CC    hw/display/blizzard.o
  CC    hw/display/exynos4210_fimd.o
  CC    hw/display/framebuffer.o
  CC    hw/display/tc6393xb.o
  CC    hw/dma/pl080.o
  CC    hw/dma/pl330.o
  CC    hw/dma/i8257.o
  CC    hw/dma/xlnx-zynq-devcfg.o
  CC    hw/gpio/max7310.o
  CC    hw/gpio/pl061.o
  CC    hw/gpio/zaurus.o
  CC    hw/gpio/gpio_key.o
  CC    hw/i2c/core.o
  CC    hw/i2c/smbus.o
  CC    hw/i2c/smbus_eeprom.o
  CC    hw/i2c/i2c-ddc.o
  CC    hw/i2c/versatile_i2c.o
  CC    hw/i2c/smbus_ich9.o
  CC    hw/i2c/pm_smbus.o
  CC    hw/i2c/bitbang_i2c.o
  CC    hw/i2c/exynos4210_i2c.o
  CC    hw/i2c/imx_i2c.o
  CC    hw/i2c/aspeed_i2c.o
  CC    hw/ide/core.o
  CC    hw/ide/atapi.o
  CC    hw/ide/qdev.o
  CC    hw/ide/pci.o
  CC    hw/ide/isa.o
  CC    hw/ide/piix.o
  CC    hw/ide/microdrive.o
  CC    hw/ide/ahci.o
  CC    hw/ide/ich.o
  CC    hw/input/hid.o
  CC    hw/input/lm832x.o
  CC    hw/input/pckbd.o
  CC    hw/input/pl050.o
  CC    hw/input/ps2.o
  CC    hw/input/stellaris_input.o
  CC    hw/input/tsc2005.o
  CC    hw/input/vmmouse.o
  CC    hw/input/virtio-input.o
  CC    hw/input/virtio-input-hid.o
  CC    hw/intc/i8259_common.o
  CC    hw/intc/i8259.o
  CC    hw/intc/pl190.o
  CC    hw/intc/imx_avic.o
  CC    hw/intc/realview_gic.o
  CC    hw/intc/ioapic_common.o
In file included from /tmp/qemu-test/src/hw/input/virtio-input.c:13:0:
/tmp/qemu-test/src/hw/input/virtio-input.c:299:55: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
 VMSTATE_VIRTIO_DEVICE(input, VIRTIO_INPUT_VM_VERSION, virtio_input_load,
                                                       ^
/tmp/qemu-test/src/include/hw/virtio/virtio.h:190:32: note: in definition of macro 'VMSTATE_VIRTIO_DEVICE'
                         .get = getf,          \
                                ^~~~
/tmp/qemu-test/src/hw/input/virtio-input.c:299:55: note: (near initialization for '(anonymous).get')
 VMSTATE_VIRTIO_DEVICE(input, VIRTIO_INPUT_VM_VERSION, virtio_input_load,
                                                       ^
/tmp/qemu-test/src/include/hw/virtio/virtio.h:190:32: note: in definition of macro 'VMSTATE_VIRTIO_DEVICE'
                         .get = getf,          \
                                ^~~~
/tmp/qemu-test/src/hw/input/virtio-input.c:300:23: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
                       virtio_vmstate_save);
                       ^
/tmp/qemu-test/src/include/hw/virtio/virtio.h:191:32: note: in definition of macro 'VMSTATE_VIRTIO_DEVICE'
                         .put = putf,          \
                                ^~~~
/tmp/qemu-test/src/hw/input/virtio-input.c:300:23: note: (near initialization for '(anonymous).put')
                       virtio_vmstate_save);
                       ^
/tmp/qemu-test/src/include/hw/virtio/virtio.h:191:32: note: in definition of macro 'VMSTATE_VIRTIO_DEVICE'
                         .put = putf,          \
                                ^~~~
cc1: all warnings being treated as errors
/tmp/qemu-test/src/rules.mak:60: recipe for target 'hw/input/virtio-input.o' failed
make: *** [hw/input/virtio-input.o] Error 1
make: *** Waiting for unfinished jobs....
tests/docker/Makefile.include:107: recipe for target 'docker-run-test-mingw@fedora' failed
make: *** [docker-run-test-mingw@fedora] Error 2
=== OUTPUT END ===

Test command exited with code: 2


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

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

* Re: [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together
  2016-10-03 18:24 [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together Jianjun Duan
                   ` (7 preceding siblings ...)
  2016-10-03 19:00 ` no-reply
@ 2016-10-03 19:11 ` Jianjun Duan
  8 siblings, 0 replies; 66+ messages in thread
From: Jianjun Duan @ 2016-10-03 19:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-ppc, dmitry, peter.maydell, kraxel, mst, david, pbonzini,
	veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth, aurelien,
	leon.alrae, blauwirbel, mark.cave-ayland, mdroth, dgilbert

I will address the style issues together with any other possible
comments. The build test failed on code not in my patches.

Thanks,
Jianjun

On 10/03/2016 11:24 AM, Jianjun Duan wrote:
> Hi all,
>    The previous patches seem to get buried deep somewhere. I am sending the lated rebased version. Comments are welcome.
> 
> v5: - Rebased to David's ppc-for-2.8. Previous versions are:
> 
> v4: - Introduce a way to set customized instance_id in SaveStateEntry. Use it
>       to set instance_id for DRC using its unique index to address David 
>       Gibson's concern.
>     - Rename VMS_CSTM to VMS_LINKED based on Paolo Bonzini's suggestions.
>     - Clean up qjson stuff in put_qtailq. 
>     - Add trace for put_qtailq and get_qtailq based on David Gilbert's 
>       suggestion.
> 
>     - Based on David's ppc-for-2.7. 
> 
> v3: - Simplify overall design followng discussion with Paolo. No longer need
>       metadata to migrate QTAILQ.
>     - Extend VMStateInfo instead of adding similar fields to VMStateField.
>     - Clean up macros in qemu/queue.h.
> (link: https://lists.nongnu.org/archive/html/qemu-devel/2016-05/msg05695.html)
> 
> v2: - Introduce a general approach to migrate QTAILQ in qemu/queue.h.
>     - Migrate signalled field in the DRC state.
>     - Put the newly added migrating fields in subsections so that backward 
>       migration is not broken.  
>     - Set detach_cb field right after migration so that a migrated hot-unplug
>       event could finish its course.
> (link: https://lists.nongnu.org/archive/html/qemu-devel/2016-05/msg04188.html)
> 
> v1: - Inital version.
> (link: https://lists.nongnu.org/archive/html/qemu-devel/2016-04/msg02601.html)
> 
> To make guest device (PCI, CPU and memory) hotplug work together 
> with guest migration, spapr drc state needs be transmitted in
> migration. This patch defines the VMStateDescription struct for
> spapr drc state to enable it.
> 
> To fix the potential racing between hotplug events on guest and 
> guest migration, ccs_list and pending_events of spapr state need be 
> transmitted in migration. This patch also takes care of it.
> 
> Jianjun Duan (6):
>   migration: alternative way to set instance_id in SaveStateEntry
>   migration: spapr_drc: defined VMStateDescription struct
>   migration: extend VMStateInfo
>   migration: migrate QTAILQ
>   migration: spapr: migrate ccs_list in spapr state
>   migration: spapr: migrate pending_events of spapr state
> 
>  hw/net/vmxnet3.c            |  18 +++--
>  hw/nvram/eeprom93xx.c       |   6 +-
>  hw/nvram/fw_cfg.c           |   6 +-
>  hw/pci/msix.c               |   6 +-
>  hw/pci/pci.c                |  12 ++--
>  hw/pci/shpc.c               |   5 +-
>  hw/ppc/spapr.c              |  67 ++++++++++++++++++
>  hw/ppc/spapr_drc.c          |  69 +++++++++++++++++++
>  hw/ppc/spapr_events.c       |  22 +++---
>  hw/ppc/spapr_pci.c          |  22 ++++++
>  hw/scsi/scsi-bus.c          |   6 +-
>  hw/timer/twl92230.c         |   6 +-
>  hw/usb/redirect.c           |  18 +++--
>  hw/virtio/virtio-pci.c      |   6 +-
>  hw/virtio/virtio.c          |   6 +-
>  include/hw/ppc/spapr.h      |   3 +-
>  include/hw/ppc/spapr_drc.h  |   9 +++
>  include/hw/qdev-core.h      |   6 ++
>  include/migration/vmstate.h |  36 ++++++++--
>  include/qemu/queue.h        |  32 +++++++++
>  migration/savevm.c          |  25 +++++--
>  migration/trace-events      |   4 ++
>  migration/vmstate.c         | 161 ++++++++++++++++++++++++++++++++++----------
>  target-alpha/machine.c      |   5 +-
>  target-arm/machine.c        |  12 ++--
>  target-i386/machine.c       |  21 ++++--
>  target-mips/machine.c       |  10 +--
>  target-ppc/machine.c        |  10 +--
>  target-sparc/machine.c      |   5 +-
>  29 files changed, 505 insertions(+), 109 deletions(-)
> 

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

* Re: [Qemu-devel] [QEMU PATCH v5 1/6] migration: alternative way to set instance_id in SaveStateEntry
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 1/6] migration: alternative way to set instance_id in SaveStateEntry Jianjun Duan
@ 2016-10-05 10:12   ` Dr. David Alan Gilbert
  2016-10-05 16:44     ` Jianjun Duan
  2016-10-05 16:46     ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
  0 siblings, 2 replies; 66+ messages in thread
From: Dr. David Alan Gilbert @ 2016-10-05 10:12 UTC (permalink / raw)
  To: Jianjun Duan
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth

* Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> In QOM(QEMU Object Model) migrated objects are identified with instance_id
> which is calculated automatically using their path in the QOM composition
> tree. For some objects, this path could change from source to target in
> migration. To migrate such objects, we need to make sure the instance_id does
> not change from source to target. We add a hook in DeviceClass to do customized
> instance_id calculation in such cases.

Can you explain a bit about why the path changes from source to destination;
the path here should be a feature of the guest state not the host, and so I
don't understand why it changes.

> As a result, in these cases compat will not be set in the concerned
> SaveStateEntry. This will prevent the inconsistent idstr to be sent over in
> migration. We could have set alias_id in a similar way. But that will be
> overloading the purpose of alias_id.
> 
> The first application will be setting instance_id for DRC using its unique
> index. Doing this makes the instance_id of DRC to be consistent across migration
> and supports flexible management of DRC objects in migration.

Is there a reason to use a custom instance_id rather than a custom idstr?

> 
> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
> ---
>  include/hw/qdev-core.h |  6 ++++++
>  migration/savevm.c     | 20 ++++++++++++++++++--
>  2 files changed, 24 insertions(+), 2 deletions(-)
> 
> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> index 2c97347..a012e8e 100644
> --- a/include/hw/qdev-core.h
> +++ b/include/hw/qdev-core.h
> @@ -139,6 +139,12 @@ typedef struct DeviceClass {
>      qdev_initfn init; /* TODO remove, once users are converted to realize */
>      qdev_event exit; /* TODO remove, once users are converted to unrealize */
>      const char *bus_type;
> +
> +    /* When this field is set, qemu will use it to get an unique instance_id
> +     * instead of calculating an auto idstr and instanc_id for the relevant
> +     * SaveStateEntry
> +     */
> +    int (*dev_get_instance_id)(DeviceState *dev);
>  } DeviceClass;
>  
>  typedef struct NamedGPIOList NamedGPIOList;
> diff --git a/migration/savevm.c b/migration/savevm.c
> index 33a2911..ef5c3d1 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -495,6 +495,11 @@ int register_savevm_live(DeviceState *dev,
>                           void *opaque)
>  {
>      SaveStateEntry *se;
> +    /* when it is a device and it provides a way to get instance_id,
> +     * we will use it and skip setting idstr and compat.
> +     */
> +    bool flag = (dev != NULL) &&
> +                (DEVICE_GET_CLASS(dev)->dev_get_instance_id != NULL);

We must be able to get a more descriptive name than 'flag'; how about
 'has_custom_id'

>      se = g_new0(SaveStateEntry, 1);
>      se->version_id = version_id;
> @@ -507,7 +512,7 @@ int register_savevm_live(DeviceState *dev,
>          se->is_ram = 1;
>      }
>  
> -    if (dev) {
> +    if (dev && !flag) {
>          char *id = qdev_get_dev_path(dev);
>          if (id) {
>              pstrcpy(se->idstr, sizeof(se->idstr), id);
> @@ -523,6 +528,9 @@ int register_savevm_live(DeviceState *dev,
>      }
>      pstrcat(se->idstr, sizeof(se->idstr), idstr);
>  
> +    if (flag) {
> +        instance_id = DEVICE_GET_CLASS(dev)->dev_get_instance_id(dev);
> +    }
>      if (instance_id == -1) {
>          se->instance_id = calculate_new_instance_id(se->idstr);
>      } else {
> @@ -580,6 +588,11 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
>                                     int required_for_version)
>  {
>      SaveStateEntry *se;
> +    /* when it is a device and it provides a way to get instance_id,
> +     * we will use it and skip setting idstr and compat.
> +     */
> +    bool flag = (dev != NULL) &&
> +                (DEVICE_GET_CLASS(dev)->dev_get_instance_id != NULL);
>  
>      /* If this triggers, alias support can be dropped for the vmsd. */
>      assert(alias_id == -1 || required_for_version >= vmsd->minimum_version_id);
> @@ -591,7 +604,7 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
>      se->vmsd = vmsd;
>      se->alias_id = alias_id;
>  
> -    if (dev) {
> +    if (dev && !flag) {
>          char *id = qdev_get_dev_path(dev);
>          if (id) {
>              pstrcpy(se->idstr, sizeof(se->idstr), id);
> @@ -607,6 +620,9 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
>      }
>      pstrcat(se->idstr, sizeof(se->idstr), vmsd->name);
>  
> +    if (flag) {
> +        instance_id = DEVICE_GET_CLASS(dev)->dev_get_instance_id(dev);
> +    }
>      if (instance_id == -1) {
>          se->instance_id = calculate_new_instance_id(se->idstr);
>      } else {
> -- 
> 1.9.1

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

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

* Re: [Qemu-devel] [QEMU PATCH v5 2/6] migration: spapr_drc: defined VMStateDescription struct
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 2/6] migration: spapr_drc: defined VMStateDescription struct Jianjun Duan
@ 2016-10-05 11:38   ` Dr. David Alan Gilbert
  2016-10-07  3:17     ` David Gibson
  2016-10-07  3:12   ` David Gibson
  1 sibling, 1 reply; 66+ messages in thread
From: Dr. David Alan Gilbert @ 2016-10-05 11:38 UTC (permalink / raw)
  To: Jianjun Duan
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth

* Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> To manage hotplug/unplug of dynamic resources such as PCI cards,
> memory, and CPU on sPAPR guests, a firmware abstraction known as
> a Dynamic Resource Connector (DRC) is used to assign a particular
> dynamic resource to the guest, and provide an interface for the
> guest to manage configuration/removal of the resource associated
> with it.
> 
> To migrate the hotplugged resources in migration, the
> associated DRC state need be migrated. To migrate the DRC state,
> we defined the VMStateDescription struct for spapr_drc to enable
> the transmission of spapr_drc state in migration.
> 
> Not all the elements in the DRC state are migrated. Only those
> ones modifiable or needed by guest actions or device add/remove
> operation are migrated. From the perspective of device
> hotplugging, if we hotplug a device on the source, we need to
> "coldplug" it on the target. The states across two hosts for the
> same device are not the same. Ideally we want the states be same
> after migration so that the device would function as hotplugged
> on the target. For example we can unplug it. The minimum DRC
> state we need to transfer should cover all the pieces changed by
> hotplugging. Out of the elements of the DRC state, isolation_state,
> allocation_sate, and configured are involved in the DR state
> transition diagram from PAPR+ 2.7, 13.4. configured and signalled
> are needed in attaching and detaching devices. indicator_state
> provides users with hardware state information. These 6 elements
> are migrated.
> 
> detach_cb in the DRC state is a function pointer that cannot be
> migrated. We set it right after DRC state is migrated so that
> a migrated hot-unplug event could finish its work.

Be careful with that; it'll get tricky if you have a bunch of different
possible callbacks.   If you want to explicitly migrate it then you'd
have to have an enum of different functions that could be called rather
than storing the pointer explicitly.

> The instance_id is used to identify objects in migration. We set
> instance_id of DRC using the unique index so that it is the same
> across migration.
> 
> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>

I think this is OK from a migration point of view; I'll leave
it to someone else to check the Power side of things.

> ---
>  hw/ppc/spapr_drc.c         | 69 ++++++++++++++++++++++++++++++++++++++++++++++
>  hw/ppc/spapr_pci.c         | 22 +++++++++++++++
>  include/hw/ppc/spapr_drc.h |  9 ++++++
>  3 files changed, 100 insertions(+)
> 
> diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
> index 6e54fd4..369ec02 100644
> --- a/hw/ppc/spapr_drc.c
> +++ b/hw/ppc/spapr_drc.c
> @@ -615,6 +615,71 @@ static void spapr_dr_connector_instance_init(Object *obj)
>                          NULL, NULL, NULL, NULL);
>  }
>  
> +static bool spapr_drc_needed(void *opaque)
> +{
> +    sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;
> +    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
> +    bool rc = false;
> +    sPAPRDREntitySense value;
> +
> +    drck->entity_sense(drc, &value);
> +    /* If no dev is plugged in there is no need to migrate the DRC state */
> +    if (value != SPAPR_DR_ENTITY_SENSE_PRESENT) {
> +        return false;
> +    }
> +    /*
> +     * If there is dev plugged in, we need to migrate the DRC state when
> +     * it is different from cold-plugged state
> +     */
> +    switch(drc->type) {
> +    /* for PCI type */
> +    case SPAPR_DR_CONNECTOR_TYPE_PCI:
> +        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) &&
> +               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) &&
> +               drc->configured && drc->signalled && !drc->awaiting_release);
> +        break;
> +    /* for LMB type */
> +    case SPAPR_DR_CONNECTOR_TYPE_LMB:
> +        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) &&
> +               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) &&
> +               drc->configured && drc->signalled && !drc->awaiting_release);
> +        break;
> +    default:
> +        ;
> +    }
> +
> +    return rc;
> +}
> +
> +/* detach_cb needs be set since it is not migrated */
> +static void postmigrate_set_detach_cb(sPAPRDRConnector *drc,
> +                                      spapr_drc_detach_cb *detach_cb)
> +{
> +    drc->detach_cb = detach_cb;
> +}
> +
> +/* return the unique drc index as instance_id for qom interfaces*/
> +static int get_instance_id(DeviceState *dev)
> +{
> +    return (int)get_index(SPAPR_DR_CONNECTOR(OBJECT(dev)));
> +}
> +
> +static const VMStateDescription vmstate_spapr_drc = {
> +    .name = "spapr_drc",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .needed = spapr_drc_needed,
> +    .fields  = (VMStateField []) {
> +        VMSTATE_UINT32(isolation_state, sPAPRDRConnector),
> +        VMSTATE_UINT32(allocation_state, sPAPRDRConnector),
> +        VMSTATE_UINT32(indicator_state, sPAPRDRConnector),
> +        VMSTATE_BOOL(configured, sPAPRDRConnector),
> +        VMSTATE_BOOL(awaiting_release, sPAPRDRConnector),
> +        VMSTATE_BOOL(signalled, sPAPRDRConnector),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
>  static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
>  {
>      DeviceClass *dk = DEVICE_CLASS(k);
> @@ -623,6 +688,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
>      dk->reset = reset;
>      dk->realize = realize;
>      dk->unrealize = unrealize;
> +    dk->vmsd = &vmstate_spapr_drc;
> +    dk->dev_get_instance_id = get_instance_id;
>      drck->set_isolation_state = set_isolation_state;
>      drck->set_indicator_state = set_indicator_state;
>      drck->set_allocation_state = set_allocation_state;
> @@ -636,6 +703,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
>      drck->detach = detach;
>      drck->release_pending = release_pending;
>      drck->set_signalled = set_signalled;
> +    drck->postmigrate_set_detach_cb = postmigrate_set_detach_cb;
> +
>      /*
>       * Reason: it crashes FIXME find and document the real reason
>       */
> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> index 4f00865..080471c 100644
> --- a/hw/ppc/spapr_pci.c
> +++ b/hw/ppc/spapr_pci.c
> @@ -1594,11 +1594,33 @@ static void spapr_pci_pre_save(void *opaque)
>      }
>  }
>  
> +/*
> + * detach_cb in the DRC state is a function pointer that cannot be
> + * migrated. We set it right after migration so that a migrated
> + * hot-unplug event could finish its work.
> + */
> +static void spapr_pci_set_detach_cb(PCIBus *bus, PCIDevice *pdev,
> +                                 void *opaque)
> +{
> +    sPAPRPHBState *sphb = opaque;
> +    sPAPRDRConnector *drc = spapr_phb_get_pci_drc(sphb, pdev);
> +    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
> +    drck->postmigrate_set_detach_cb(drc, spapr_phb_remove_pci_device_cb);
> +}
> +
>  static int spapr_pci_post_load(void *opaque, int version_id)
>  {
>      sPAPRPHBState *sphb = opaque;
>      gpointer key, value;
>      int i;
> +    PCIBus *bus = PCI_HOST_BRIDGE(sphb)->bus;
> +    unsigned int bus_no = 0;
> +
> +    /* Set detach_cb for the drc unconditionally after migration */
> +    if (bus) {
> +        pci_for_each_device(bus, pci_bus_num(bus), spapr_pci_set_detach_cb,
> +                            &bus_no);
> +    }
>  
>      for (i = 0; i < sphb->msi_devs_num; ++i) {
>          key = g_memdup(&sphb->msi_devs[i].key,
> diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h
> index fa531d5..17589c8 100644
> --- a/include/hw/ppc/spapr_drc.h
> +++ b/include/hw/ppc/spapr_drc.h
> @@ -192,6 +192,15 @@ typedef struct sPAPRDRConnectorClass {
>                     void *detach_cb_opaque, Error **errp);
>      bool (*release_pending)(sPAPRDRConnector *drc);
>      void (*set_signalled)(sPAPRDRConnector *drc);
> +
> +    /*
> +     * QEMU interface for setting detach_cb after migration.
> +     * detach_cb in the DRC state is a function pointer that cannot be
> +     * migrated. We set it right after migration so that a migrated
> +     * hot-unplug event could finish its work.
> +     */
> +    void (*postmigrate_set_detach_cb)(sPAPRDRConnector *drc,
> +                                      spapr_drc_detach_cb *detach_cb);
>  } sPAPRDRConnectorClass;
>  
>  sPAPRDRConnector *spapr_dr_connector_new(Object *owner,
> -- 
> 1.9.1
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [Qemu-devel] [QEMU PATCH v5 1/6] migration: alternative way to set instance_id in SaveStateEntry
  2016-10-05 10:12   ` Dr. David Alan Gilbert
@ 2016-10-05 16:44     ` Jianjun Duan
  2016-10-07  2:54       ` David Gibson
  2016-10-05 16:46     ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
  1 sibling, 1 reply; 66+ messages in thread
From: Jianjun Duan @ 2016-10-05 16:44 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth

Please see comments below:

On 10/05/2016 03:12 AM, Dr. David Alan Gilbert wrote:
> * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
>> In QOM(QEMU Object Model) migrated objects are identified with instance_id
>> which is calculated automatically using their path in the QOM composition
>> tree. For some objects, this path could change from source to target in
>> migration. To migrate such objects, we need to make sure the instance_id does
>> not change from source to target. We add a hook in DeviceClass to do customized
>> instance_id calculation in such cases.
> 
> Can you explain a bit about why the path changes from source to destination;
> the path here should be a feature of the guest state not the host, and so I
> don't understand why it changes.
Please see the discussion with David in the previous versions:
http://lists.nongnu.org/archive/html/qemu-ppc/2016-06/msg00062.html


>> As a result, in these cases compat will not be set in the concerned
>> SaveStateEntry. This will prevent the inconsistent idstr to be sent over in
>> migration. We could have set alias_id in a similar way. But that will be
>> overloading the purpose of alias_id.
>>
>> The first application will be setting instance_id for DRC using its unique
>> index. Doing this makes the instance_id of DRC to be consistent across migration
>> and supports flexible management of DRC objects in migration.
> 
> Is there a reason to use a custom instance_id rather than a custom idstr

It can be done either way. But it is easier to deal with a integer than
a string.


>>
>> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
>> ---
>>  include/hw/qdev-core.h |  6 ++++++
>>  migration/savevm.c     | 20 ++++++++++++++++++--
>>  2 files changed, 24 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
>> index 2c97347..a012e8e 100644
>> --- a/include/hw/qdev-core.h
>> +++ b/include/hw/qdev-core.h
>> @@ -139,6 +139,12 @@ typedef struct DeviceClass {
>>      qdev_initfn init; /* TODO remove, once users are converted to realize */
>>      qdev_event exit; /* TODO remove, once users are converted to unrealize */
>>      const char *bus_type;
>> +
>> +    /* When this field is set, qemu will use it to get an unique instance_id
>> +     * instead of calculating an auto idstr and instanc_id for the relevant
>> +     * SaveStateEntry
>> +     */
>> +    int (*dev_get_instance_id)(DeviceState *dev);
>>  } DeviceClass;
>>  
>>  typedef struct NamedGPIOList NamedGPIOList;
>> diff --git a/migration/savevm.c b/migration/savevm.c
>> index 33a2911..ef5c3d1 100644
>> --- a/migration/savevm.c
>> +++ b/migration/savevm.c
>> @@ -495,6 +495,11 @@ int register_savevm_live(DeviceState *dev,
>>                           void *opaque)
>>  {
>>      SaveStateEntry *se;
>> +    /* when it is a device and it provides a way to get instance_id,
>> +     * we will use it and skip setting idstr and compat.
>> +     */
>> +    bool flag = (dev != NULL) &&
>> +                (DEVICE_GET_CLASS(dev)->dev_get_instance_id != NULL);
> 
> We must be able to get a more descriptive name than 'flag'; how about
>  'has_custom_id'
> 
>>      se = g_new0(SaveStateEntry, 1);
>>      se->version_id = version_id;
>> @@ -507,7 +512,7 @@ int register_savevm_live(DeviceState *dev,
>>          se->is_ram = 1;
>>      }
>>  
>> -    if (dev) {
>> +    if (dev && !flag) {
>>          char *id = qdev_get_dev_path(dev);
>>          if (id) {
>>              pstrcpy(se->idstr, sizeof(se->idstr), id);
>> @@ -523,6 +528,9 @@ int register_savevm_live(DeviceState *dev,
>>      }
>>      pstrcat(se->idstr, sizeof(se->idstr), idstr);
>>  
>> +    if (flag) {
>> +        instance_id = DEVICE_GET_CLASS(dev)->dev_get_instance_id(dev);
>> +    }
>>      if (instance_id == -1) {
>>          se->instance_id = calculate_new_instance_id(se->idstr);
>>      } else {
>> @@ -580,6 +588,11 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
>>                                     int required_for_version)
>>  {
>>      SaveStateEntry *se;
>> +    /* when it is a device and it provides a way to get instance_id,
>> +     * we will use it and skip setting idstr and compat.
>> +     */
>> +    bool flag = (dev != NULL) &&
>> +                (DEVICE_GET_CLASS(dev)->dev_get_instance_id != NULL);
>>  
>>      /* If this triggers, alias support can be dropped for the vmsd. */
>>      assert(alias_id == -1 || required_for_version >= vmsd->minimum_version_id);
>> @@ -591,7 +604,7 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
>>      se->vmsd = vmsd;
>>      se->alias_id = alias_id;
>>  
>> -    if (dev) {
>> +    if (dev && !flag) {
>>          char *id = qdev_get_dev_path(dev);
>>          if (id) {
>>              pstrcpy(se->idstr, sizeof(se->idstr), id);
>> @@ -607,6 +620,9 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
>>      }
>>      pstrcat(se->idstr, sizeof(se->idstr), vmsd->name);
>>  
>> +    if (flag) {
>> +        instance_id = DEVICE_GET_CLASS(dev)->dev_get_instance_id(dev);
>> +    }
>>      if (instance_id == -1) {
>>          se->instance_id = calculate_new_instance_id(se->idstr);
>>      } else {
>> -- 
>> 1.9.1
> 
> Dave
>>
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
> 


Thanks,
Jianjun

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 1/6] migration: alternative way to set instance_id in SaveStateEntry
  2016-10-05 10:12   ` Dr. David Alan Gilbert
  2016-10-05 16:44     ` Jianjun Duan
@ 2016-10-05 16:46     ` Jianjun Duan
  1 sibling, 0 replies; 66+ messages in thread
From: Jianjun Duan @ 2016-10-05 16:46 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: veroniabahaa, peter.maydell, mdroth, mst, quintela, qemu-devel,
	mreitz, blauwirbel, amit.shah, qemu-ppc, kraxel, kwolf, dmitry,
	pbonzini, rth, leon.alrae, david



On 10/05/2016 03:12 AM, Dr. David Alan Gilbert wrote:
> * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
>> In QOM(QEMU Object Model) migrated objects are identified with instance_id
>> which is calculated automatically using their path in the QOM composition
>> tree. For some objects, this path could change from source to target in
>> migration. To migrate such objects, we need to make sure the instance_id does
>> not change from source to target. We add a hook in DeviceClass to do customized
>> instance_id calculation in such cases.
> 
> Can you explain a bit about why the path changes from source to destination;
> the path here should be a feature of the guest state not the host, and so I
> don't understand why it changes.
> 
>> As a result, in these cases compat will not be set in the concerned
>> SaveStateEntry. This will prevent the inconsistent idstr to be sent over in
>> migration. We could have set alias_id in a similar way. But that will be
>> overloading the purpose of alias_id.
>>
>> The first application will be setting instance_id for DRC using its unique
>> index. Doing this makes the instance_id of DRC to be consistent across migration
>> and supports flexible management of DRC objects in migration.
> 
> Is there a reason to use a custom instance_id rather than a custom idstr?
> 
>>
>> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
>> ---
>>  include/hw/qdev-core.h |  6 ++++++
>>  migration/savevm.c     | 20 ++++++++++++++++++--
>>  2 files changed, 24 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
>> index 2c97347..a012e8e 100644
>> --- a/include/hw/qdev-core.h
>> +++ b/include/hw/qdev-core.h
>> @@ -139,6 +139,12 @@ typedef struct DeviceClass {
>>      qdev_initfn init; /* TODO remove, once users are converted to realize */
>>      qdev_event exit; /* TODO remove, once users are converted to unrealize */
>>      const char *bus_type;
>> +
>> +    /* When this field is set, qemu will use it to get an unique instance_id
>> +     * instead of calculating an auto idstr and instanc_id for the relevant
>> +     * SaveStateEntry
>> +     */
>> +    int (*dev_get_instance_id)(DeviceState *dev);
>>  } DeviceClass;
>>  
>>  typedef struct NamedGPIOList NamedGPIOList;
>> diff --git a/migration/savevm.c b/migration/savevm.c
>> index 33a2911..ef5c3d1 100644
>> --- a/migration/savevm.c
>> +++ b/migration/savevm.c
>> @@ -495,6 +495,11 @@ int register_savevm_live(DeviceState *dev,
>>                           void *opaque)
>>  {
>>      SaveStateEntry *se;
>> +    /* when it is a device and it provides a way to get instance_id,
>> +     * we will use it and skip setting idstr and compat.
>> +     */
>> +    bool flag = (dev != NULL) &&
>> +                (DEVICE_GET_CLASS(dev)->dev_get_instance_id != NULL);
> 
> We must be able to get a more descriptive name than 'flag'; how about
>  'has_custom_id'
Sure. Will wait for more comments and address them together.

>>      se = g_new0(SaveStateEntry, 1);
>>      se->version_id = version_id;
>> @@ -507,7 +512,7 @@ int register_savevm_live(DeviceState *dev,
>>          se->is_ram = 1;
>>      }
>>  
>> -    if (dev) {
>> +    if (dev && !flag) {
>>          char *id = qdev_get_dev_path(dev);
>>          if (id) {
>>              pstrcpy(se->idstr, sizeof(se->idstr), id);
>> @@ -523,6 +528,9 @@ int register_savevm_live(DeviceState *dev,
>>      }
>>      pstrcat(se->idstr, sizeof(se->idstr), idstr);
>>  
>> +    if (flag) {
>> +        instance_id = DEVICE_GET_CLASS(dev)->dev_get_instance_id(dev);
>> +    }
>>      if (instance_id == -1) {
>>          se->instance_id = calculate_new_instance_id(se->idstr);
>>      } else {
>> @@ -580,6 +588,11 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
>>                                     int required_for_version)
>>  {
>>      SaveStateEntry *se;
>> +    /* when it is a device and it provides a way to get instance_id,
>> +     * we will use it and skip setting idstr and compat.
>> +     */
>> +    bool flag = (dev != NULL) &&
>> +                (DEVICE_GET_CLASS(dev)->dev_get_instance_id != NULL);
>>  
>>      /* If this triggers, alias support can be dropped for the vmsd. */
>>      assert(alias_id == -1 || required_for_version >= vmsd->minimum_version_id);
>> @@ -591,7 +604,7 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
>>      se->vmsd = vmsd;
>>      se->alias_id = alias_id;
>>  
>> -    if (dev) {
>> +    if (dev && !flag) {
>>          char *id = qdev_get_dev_path(dev);
>>          if (id) {
>>              pstrcpy(se->idstr, sizeof(se->idstr), id);
>> @@ -607,6 +620,9 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
>>      }
>>      pstrcat(se->idstr, sizeof(se->idstr), vmsd->name);
>>  
>> +    if (flag) {
>> +        instance_id = DEVICE_GET_CLASS(dev)->dev_get_instance_id(dev);
>> +    }
>>      if (instance_id == -1) {
>>          se->instance_id = calculate_new_instance_id(se->idstr);
>>      } else {
>> -- 
>> 1.9.1
> 
> Dave
>>
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
> 
Thanks,
Jianjun

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

* Re: [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ Jianjun Duan
@ 2016-10-05 16:56   ` Dr. David Alan Gilbert
  2016-10-05 17:19     ` Jianjun Duan
  2016-10-06 11:05     ` [Qemu-devel] " Paolo Bonzini
  0 siblings, 2 replies; 66+ messages in thread
From: Dr. David Alan Gilbert @ 2016-10-05 16:56 UTC (permalink / raw)
  To: Jianjun Duan
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth

* Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> Currently we cannot directly transfer a QTAILQ instance because of the
> limitation in the migration code. Here we introduce an approach to
> transfer such structures. In our approach such a structure is tagged
> with VMS_LINKED. We then modified vmstate_save_state and vmstate_load_state
> so that when VMS_LINKED is encountered, put and get from VMStateInfo are
> called respectively. We created VMStateInfo vmstate_info_qtailq for QTAILQ.
> Similar VMStateInfo can be created for other data structures such as list.
> This approach will be used to transfer pending_events and ccs_list in spapr
> state.
> 
> We also create some macros in qemu/queue.h to access a QTAILQ using pointer
> arithmetic. This ensures that we do not depend on the implementation
> details about QTAILQ in the migration code.

I think we're going to need a way to have a more flexible
loops; and thus my choice here wouldn't be to use the .get/.put together
with the VMSD; but I think we'll end up needing a new
data structure, maybe a VMStateLoop *loop in VMStateField.

So would it be easier if you added that new member, then you wouldn't have to
modify every get() and put() function that already exists in the previous patch.

Specifically, your format of QTAILQ is perfectly reasonable - a
byte before each entry which is 1 to indicate there's an entry or 0
to indicate termination, but there are lots of other variants, e.g.

   a) put_scsi_requests uses that byte to hold a flag, so it's 0,1,2
      0 still means terminate but 1 or 2 set a flag in the structure.

   b) slirp_state_load also uses a null byte termination but not off a QTAILQ
      (although I think it could be flipped for one) (it uses '42' for the
      non-0 value, but looks like it could become 1)

   c) virtio_blk also rolls it's own linked list but again with the 0/1 byte

  Now how would I modify your QTAILQ load/store to do (a) without copying the whole
thing?

Dave

> 
> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
> ---
>  include/migration/vmstate.h | 26 ++++++++++++++++++
>  include/qemu/queue.h        | 32 ++++++++++++++++++++++
>  migration/trace-events      |  4 +++
>  migration/vmstate.c         | 66 +++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 128 insertions(+)
> 
> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
> index 459dd4a..e60c994 100644
> --- a/include/migration/vmstate.h
> +++ b/include/migration/vmstate.h
> @@ -186,6 +186,12 @@ enum VMStateFlags {
>       * to determine the number of entries in the array. Only valid in
>       * combination with one of VMS_VARRAY*. */
>      VMS_MULTIPLY_ELEMENTS = 0x4000,
> +    /* For fields which need customized handling, such as QTAILQ in queue.h.
> +     * When this flag is set in VMStateField, info->get/put will
> +     * be used in vmstate_load/save_state instead of recursive call.
> +     * User should implement set info to handle the concerned data structure.
> +     */
> +    VMS_LINKED            = 0x8000,
>  };
>  
>  struct VMStateField {
> @@ -246,6 +252,7 @@ extern const VMStateInfo vmstate_info_timer;
>  extern const VMStateInfo vmstate_info_buffer;
>  extern const VMStateInfo vmstate_info_unused_buffer;
>  extern const VMStateInfo vmstate_info_bitmap;
> +extern const VMStateInfo vmstate_info_qtailq;
>  
>  #define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0)
>  #define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0)
> @@ -657,6 +664,25 @@ extern const VMStateInfo vmstate_info_bitmap;
>      .offset       = offsetof(_state, _field),                        \
>  }
>  
> +/* For QTAILQ that need customized handling
> + * _type: type of QTAILQ element
> + * _next: name of QTAILQ entry field in QTAILQ element
> + * _vmsd: VMSD for QTAILQ element
> + * size: size of QTAILQ element
> + * start: offset of QTAILQ entry in QTAILQ element
> + */
> +#define VMSTATE_QTAILQ_V(_field, _state, _version, _vmsd, _type, _next)  \
> +{                                                                        \
> +    .name         = (stringify(_field)),                                 \
> +    .version_id   = (_version),                                          \
> +    .vmsd         = &(_vmsd),                                            \
> +    .size         = sizeof(_type),                                       \
> +    .info         = &vmstate_info_qtailq,                                \
> +    .flags        = VMS_LINKED,                                          \
> +    .offset       = offsetof(_state, _field),                            \
> +    .start        = offsetof(_type, _next),                              \
> +}
> +
>  /* _f : field name
>     _f_n : num of elements field_name
>     _n : num of elements
> diff --git a/include/qemu/queue.h b/include/qemu/queue.h
> index 342073f..12c3f80 100644
> --- a/include/qemu/queue.h
> +++ b/include/qemu/queue.h
> @@ -438,4 +438,36 @@ struct {                                                                \
>  #define QTAILQ_PREV(elm, headname, field) \
>          (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
>  
> +/*
> + * Offsets of layout of a tail queue head.
> + */
> +#define QTAILQ_FIRST_OFFSET 0
> +#define QTAILQ_LAST_OFFSET (sizeof(void *))
> +
> +/*
> + * Offsets of layout of a tail queue element.
> + */
> +#define QTAILQ_NEXT_OFFSET 0
> +#define QTAILQ_PREV_OFFSET (sizeof(void *))
> +
> +/*
> + * Tail queue tranversal using pointer arithmetic.
> + */
> +#define QTAILQ_RAW_FOREACH(elm, head, entry)                                   \
> +        for ((elm) = *((void **) ((char *) (head) + QTAILQ_FIRST_OFFSET));     \
> +             (elm);                                                            \
> +             (elm) =                                                           \
> +                 *((void **) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET)))
> +/*
> + * Tail queue insertion using pointer arithmetic.
> + */
> +#define QTAILQ_RAW_INSERT_TAIL(head, elm, entry) do {                          \
> +        *((void **) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET)) = NULL;   \
> +        *((void **) ((char *) (elm) + (entry) + QTAILQ_PREV_OFFSET)) =         \
> +            *((void **) ((char *) (head) +QTAILQ_LAST_OFFSET));                \
> +        **((void ***)((char *) (head) +QTAILQ_LAST_OFFSET)) = (elm);           \
> +        *((void **) ((char *) (head) + QTAILQ_LAST_OFFSET)) =                  \
> +            (void *) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET);          \
> +} while (/*CONSTCOND*/0)
> +
>  #endif /* QEMU_SYS_QUEUE_H */
> diff --git a/migration/trace-events b/migration/trace-events
> index dfee75a..9a6ec59 100644
> --- a/migration/trace-events
> +++ b/migration/trace-events
> @@ -52,6 +52,10 @@ vmstate_n_elems(const char *name, int n_elems) "%s: %d"
>  vmstate_subsection_load(const char *parent) "%s"
>  vmstate_subsection_load_bad(const char *parent,  const char *sub, const char *sub2) "%s: %s/%s"
>  vmstate_subsection_load_good(const char *parent) "%s"
> +get_qtailq(const char *name, int version_id) "%s v%d"
> +get_qtailq_end(const char *name, const char *reason, int val) "%s %s/%d"
> +put_qtailq(const char *name, int version_id) "%s v%d"
> +put_qtailq_end(const char *name, const char *reason) "%s %s"
>  
>  # migration/qemu-file.c
>  qemu_file_fclose(void) ""
> diff --git a/migration/vmstate.c b/migration/vmstate.c
> index 66802cb..192db8a 100644
> --- a/migration/vmstate.c
> +++ b/migration/vmstate.c
> @@ -5,7 +5,9 @@
>  #include "migration/vmstate.h"
>  #include "qemu/bitops.h"
>  #include "qemu/error-report.h"
> +#include "qemu/queue.h"
>  #include "trace.h"
> +#include "migration/qjson.h"
>  
>  static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
>                                      void *opaque, QJSON *vmdesc);
> @@ -121,6 +123,8 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
>                  if (field->flags & VMS_STRUCT) {
>                      ret = vmstate_load_state(f, field->vmsd, addr,
>                                               field->vmsd->version_id);
> +                } else if (field->flags & VMS_LINKED) {
> +                    ret = field->info->get(f, addr, size, field);
>                  } else {
>                      ret = field->info->get(f, addr, size, NULL);
>  
> @@ -193,6 +197,8 @@ static const char *vmfield_get_type_name(VMStateField *field)
>  
>      if (field->flags & VMS_STRUCT) {
>          type = "struct";
> +    } else if (field->flags & VMS_LINKED) {
> +        type = "linked";
>      } else if (field->info->name) {
>          type = field->info->name;
>      }
> @@ -327,6 +333,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
>                  }
>                  if (field->flags & VMS_STRUCT) {
>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
> +                } else if  (field->flags & VMS_LINKED) {
> +                    field->info->put(f, addr, size, field, vmdesc_loop);
>                  } else {
>                      field->info->put(f, addr, size, NULL, NULL);
>                  }
> @@ -939,3 +947,61 @@ const VMStateInfo vmstate_info_bitmap = {
>      .get = get_bitmap,
>      .put = put_bitmap,
>  };
> +
> +/*get for QTAILQ */
> +static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
> +                      VMStateField *field)
> +{
> +    int ret = 0;
> +    const VMStateDescription *vmsd = field->vmsd;
> +    size_t size = field->size;
> +    size_t entry = field->start;
> +    int version_id = field->version_id;
> +    void *elm;
> +
> +    trace_get_qtailq(vmsd->name, version_id);
> +    if (version_id > vmsd->version_id) {
> +        trace_get_qtailq_end(vmsd->name, "too new", -EINVAL);

Can you make those error_report's please - if it fails we want to
see why in the log.

Dave

> +        return -EINVAL;
> +    }
> +    if (version_id < vmsd->minimum_version_id) {
> +        trace_get_qtailq_end(vmsd->name, "too old", -EINVAL);
> +        return -EINVAL;
> +    }
> +
> +    while (qemu_get_byte(f)) {
> +        elm =  g_malloc(size);
> +        ret = vmstate_load_state(f, vmsd, elm, version_id);
> +        if (ret) {
> +            return ret;
> +        }
> +        QTAILQ_RAW_INSERT_TAIL(pv, elm, entry);
> +    }
> +
> +    trace_get_qtailq_end(vmsd->name, "end", ret);
> +    return ret;
> +}
> +
> +/* put for QTAILQ */
> +static void put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
> +                       VMStateField *field, QJSON *vmdesc)
> +{
> +    const VMStateDescription *vmsd = field->vmsd;
> +    size_t entry = field->start;
> +    void *elm;
> +
> +    trace_put_qtailq(vmsd->name, vmsd->version_id);
> +
> +    QTAILQ_RAW_FOREACH(elm, pv, entry) {
> +        qemu_put_byte(f, true);
> +        vmstate_save_state(f, vmsd, elm, vmdesc);
> +    }
> +    qemu_put_byte(f, false);
> +
> +    trace_put_qtailq_end(vmsd->name, "end");
> +}
> +const VMStateInfo vmstate_info_qtailq = {
> +    .name = "qtailq",
> +    .get  = get_qtailq,
> +    .put  = put_qtailq,
> +};
> -- 
> 1.9.1
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-05 16:56   ` Dr. David Alan Gilbert
@ 2016-10-05 17:19     ` Jianjun Duan
  2016-10-06 19:01       ` Dr. David Alan Gilbert
  2016-10-06 11:05     ` [Qemu-devel] " Paolo Bonzini
  1 sibling, 1 reply; 66+ messages in thread
From: Jianjun Duan @ 2016-10-05 17:19 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth



On 10/05/2016 09:56 AM, Dr. David Alan Gilbert wrote:
> * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
>> Currently we cannot directly transfer a QTAILQ instance because of the
>> limitation in the migration code. Here we introduce an approach to
>> transfer such structures. In our approach such a structure is tagged
>> with VMS_LINKED. We then modified vmstate_save_state and vmstate_load_state
>> so that when VMS_LINKED is encountered, put and get from VMStateInfo are
>> called respectively. We created VMStateInfo vmstate_info_qtailq for QTAILQ.
>> Similar VMStateInfo can be created for other data structures such as list.
>> This approach will be used to transfer pending_events and ccs_list in spapr
>> state.
>>
>> We also create some macros in qemu/queue.h to access a QTAILQ using pointer
>> arithmetic. This ensures that we do not depend on the implementation
>> details about QTAILQ in the migration code.
> 
> I think we're going to need a way to have a more flexible
> loops; and thus my choice here wouldn't be to use the .get/.put together
> with the VMSD; but I think we'll end up needing a new
> data structure, maybe a VMStateLoop *loop in VMStateField.
> 
> So would it be easier if you added that new member, then you wouldn't have to
> modify every get() and put() function that already exists in the previous patch.
> 
> Specifically, your format of QTAILQ is perfectly reasonable - a
> byte before each entry which is 1 to indicate there's an entry or 0
> to indicate termination, but there are lots of other variants, e.g.
> 
>    a) put_scsi_requests uses that byte to hold a flag, so it's 0,1,2
>       0 still means terminate but 1 or 2 set a flag in the structure.

I quickly take a look of put_scsi_requests. It is transferring a QTAILQ of
SCSIRequest. However it goes into the structure inside to dump the
elements out.
If using my approach, I would have a VMSD for SCSIRequest. The
additional byte used to indicate the end of the queue would lie outside
the SCSCIRequest data block, so there would be no confusion.

>    b) slirp_state_load also uses a null byte termination but not off a QTAILQ
>       (although I think it could be flipped for one) (it uses '42' for the
>       non-0 value, but looks like it could become 1)

>    c) virtio_blk also rolls it's own linked list but again with the 0/1 byte
> 
>   Now how would I modify your QTAILQ load/store to do (a) without copying the whole
> thing?
> 
> Dave
> 
>>
>> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
>> ---
>>  include/migration/vmstate.h | 26 ++++++++++++++++++
>>  include/qemu/queue.h        | 32 ++++++++++++++++++++++
>>  migration/trace-events      |  4 +++
>>  migration/vmstate.c         | 66 +++++++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 128 insertions(+)
>>
>> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
>> index 459dd4a..e60c994 100644
>> --- a/include/migration/vmstate.h
>> +++ b/include/migration/vmstate.h
>> @@ -186,6 +186,12 @@ enum VMStateFlags {
>>       * to determine the number of entries in the array. Only valid in
>>       * combination with one of VMS_VARRAY*. */
>>      VMS_MULTIPLY_ELEMENTS = 0x4000,
>> +    /* For fields which need customized handling, such as QTAILQ in queue.h.
>> +     * When this flag is set in VMStateField, info->get/put will
>> +     * be used in vmstate_load/save_state instead of recursive call.
>> +     * User should implement set info to handle the concerned data structure.
>> +     */
>> +    VMS_LINKED            = 0x8000,
>>  };
>>  
>>  struct VMStateField {
>> @@ -246,6 +252,7 @@ extern const VMStateInfo vmstate_info_timer;
>>  extern const VMStateInfo vmstate_info_buffer;
>>  extern const VMStateInfo vmstate_info_unused_buffer;
>>  extern const VMStateInfo vmstate_info_bitmap;
>> +extern const VMStateInfo vmstate_info_qtailq;
>>  
>>  #define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0)
>>  #define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0)
>> @@ -657,6 +664,25 @@ extern const VMStateInfo vmstate_info_bitmap;
>>      .offset       = offsetof(_state, _field),                        \
>>  }
>>  
>> +/* For QTAILQ that need customized handling
>> + * _type: type of QTAILQ element
>> + * _next: name of QTAILQ entry field in QTAILQ element
>> + * _vmsd: VMSD for QTAILQ element
>> + * size: size of QTAILQ element
>> + * start: offset of QTAILQ entry in QTAILQ element
>> + */
>> +#define VMSTATE_QTAILQ_V(_field, _state, _version, _vmsd, _type, _next)  \
>> +{                                                                        \
>> +    .name         = (stringify(_field)),                                 \
>> +    .version_id   = (_version),                                          \
>> +    .vmsd         = &(_vmsd),                                            \
>> +    .size         = sizeof(_type),                                       \
>> +    .info         = &vmstate_info_qtailq,                                \
>> +    .flags        = VMS_LINKED,                                          \
>> +    .offset       = offsetof(_state, _field),                            \
>> +    .start        = offsetof(_type, _next),                              \
>> +}
>> +
>>  /* _f : field name
>>     _f_n : num of elements field_name
>>     _n : num of elements
>> diff --git a/include/qemu/queue.h b/include/qemu/queue.h
>> index 342073f..12c3f80 100644
>> --- a/include/qemu/queue.h
>> +++ b/include/qemu/queue.h
>> @@ -438,4 +438,36 @@ struct {                                                                \
>>  #define QTAILQ_PREV(elm, headname, field) \
>>          (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
>>  
>> +/*
>> + * Offsets of layout of a tail queue head.
>> + */
>> +#define QTAILQ_FIRST_OFFSET 0
>> +#define QTAILQ_LAST_OFFSET (sizeof(void *))
>> +
>> +/*
>> + * Offsets of layout of a tail queue element.
>> + */
>> +#define QTAILQ_NEXT_OFFSET 0
>> +#define QTAILQ_PREV_OFFSET (sizeof(void *))
>> +
>> +/*
>> + * Tail queue tranversal using pointer arithmetic.
>> + */
>> +#define QTAILQ_RAW_FOREACH(elm, head, entry)                                   \
>> +        for ((elm) = *((void **) ((char *) (head) + QTAILQ_FIRST_OFFSET));     \
>> +             (elm);                                                            \
>> +             (elm) =                                                           \
>> +                 *((void **) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET)))
>> +/*
>> + * Tail queue insertion using pointer arithmetic.
>> + */
>> +#define QTAILQ_RAW_INSERT_TAIL(head, elm, entry) do {                          \
>> +        *((void **) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET)) = NULL;   \
>> +        *((void **) ((char *) (elm) + (entry) + QTAILQ_PREV_OFFSET)) =         \
>> +            *((void **) ((char *) (head) +QTAILQ_LAST_OFFSET));                \
>> +        **((void ***)((char *) (head) +QTAILQ_LAST_OFFSET)) = (elm);           \
>> +        *((void **) ((char *) (head) + QTAILQ_LAST_OFFSET)) =                  \
>> +            (void *) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET);          \
>> +} while (/*CONSTCOND*/0)
>> +
>>  #endif /* QEMU_SYS_QUEUE_H */
>> diff --git a/migration/trace-events b/migration/trace-events
>> index dfee75a..9a6ec59 100644
>> --- a/migration/trace-events
>> +++ b/migration/trace-events
>> @@ -52,6 +52,10 @@ vmstate_n_elems(const char *name, int n_elems) "%s: %d"
>>  vmstate_subsection_load(const char *parent) "%s"
>>  vmstate_subsection_load_bad(const char *parent,  const char *sub, const char *sub2) "%s: %s/%s"
>>  vmstate_subsection_load_good(const char *parent) "%s"
>> +get_qtailq(const char *name, int version_id) "%s v%d"
>> +get_qtailq_end(const char *name, const char *reason, int val) "%s %s/%d"
>> +put_qtailq(const char *name, int version_id) "%s v%d"
>> +put_qtailq_end(const char *name, const char *reason) "%s %s"
>>  
>>  # migration/qemu-file.c
>>  qemu_file_fclose(void) ""
>> diff --git a/migration/vmstate.c b/migration/vmstate.c
>> index 66802cb..192db8a 100644
>> --- a/migration/vmstate.c
>> +++ b/migration/vmstate.c
>> @@ -5,7 +5,9 @@
>>  #include "migration/vmstate.h"
>>  #include "qemu/bitops.h"
>>  #include "qemu/error-report.h"
>> +#include "qemu/queue.h"
>>  #include "trace.h"
>> +#include "migration/qjson.h"
>>  
>>  static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
>>                                      void *opaque, QJSON *vmdesc);
>> @@ -121,6 +123,8 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
>>                  if (field->flags & VMS_STRUCT) {
>>                      ret = vmstate_load_state(f, field->vmsd, addr,
>>                                               field->vmsd->version_id);
>> +                } else if (field->flags & VMS_LINKED) {
>> +                    ret = field->info->get(f, addr, size, field);
>>                  } else {
>>                      ret = field->info->get(f, addr, size, NULL);
>>  
>> @@ -193,6 +197,8 @@ static const char *vmfield_get_type_name(VMStateField *field)
>>  
>>      if (field->flags & VMS_STRUCT) {
>>          type = "struct";
>> +    } else if (field->flags & VMS_LINKED) {
>> +        type = "linked";
>>      } else if (field->info->name) {
>>          type = field->info->name;
>>      }
>> @@ -327,6 +333,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
>>                  }
>>                  if (field->flags & VMS_STRUCT) {
>>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
>> +                } else if  (field->flags & VMS_LINKED) {
>> +                    field->info->put(f, addr, size, field, vmdesc_loop);
>>                  } else {
>>                      field->info->put(f, addr, size, NULL, NULL);
>>                  }
>> @@ -939,3 +947,61 @@ const VMStateInfo vmstate_info_bitmap = {
>>      .get = get_bitmap,
>>      .put = put_bitmap,
>>  };
>> +
>> +/*get for QTAILQ */
>> +static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
>> +                      VMStateField *field)
>> +{
>> +    int ret = 0;
>> +    const VMStateDescription *vmsd = field->vmsd;
>> +    size_t size = field->size;
>> +    size_t entry = field->start;
>> +    int version_id = field->version_id;
>> +    void *elm;
>> +
>> +    trace_get_qtailq(vmsd->name, version_id);
>> +    if (version_id > vmsd->version_id) {
>> +        trace_get_qtailq_end(vmsd->name, "too new", -EINVAL);
> 
> Can you make those error_report's please - if it fails we want to
> see why in the log.
> 
> Dave
> 
>> +        return -EINVAL;
>> +    }
>> +    if (version_id < vmsd->minimum_version_id) {
>> +        trace_get_qtailq_end(vmsd->name, "too old", -EINVAL);
>> +        return -EINVAL;
>> +    }
>> +
>> +    while (qemu_get_byte(f)) {
>> +        elm =  g_malloc(size);
>> +        ret = vmstate_load_state(f, vmsd, elm, version_id);
>> +        if (ret) {
>> +            return ret;
>> +        }
>> +        QTAILQ_RAW_INSERT_TAIL(pv, elm, entry);
>> +    }
>> +
>> +    trace_get_qtailq_end(vmsd->name, "end", ret);
>> +    return ret;
>> +}
>> +
>> +/* put for QTAILQ */
>> +static void put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
>> +                       VMStateField *field, QJSON *vmdesc)
>> +{
>> +    const VMStateDescription *vmsd = field->vmsd;
>> +    size_t entry = field->start;
>> +    void *elm;
>> +
>> +    trace_put_qtailq(vmsd->name, vmsd->version_id);
>> +
>> +    QTAILQ_RAW_FOREACH(elm, pv, entry) {
>> +        qemu_put_byte(f, true);
>> +        vmstate_save_state(f, vmsd, elm, vmdesc);
>> +    }
>> +    qemu_put_byte(f, false);
>> +
>> +    trace_put_qtailq_end(vmsd->name, "end");
>> +}
>> +const VMStateInfo vmstate_info_qtailq = {
>> +    .name = "qtailq",
>> +    .get  = get_qtailq,
>> +    .put  = put_qtailq,
>> +};
>> -- 
>> 1.9.1
>>
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
> 
Thanks,
Jianjun

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

* Re: [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-05 16:56   ` Dr. David Alan Gilbert
  2016-10-05 17:19     ` Jianjun Duan
@ 2016-10-06 11:05     ` Paolo Bonzini
  2016-10-06 11:56       ` Dr. David Alan Gilbert
  1 sibling, 1 reply; 66+ messages in thread
From: Paolo Bonzini @ 2016-10-06 11:05 UTC (permalink / raw)
  To: Dr. David Alan Gilbert, Jianjun Duan
  Cc: veroniabahaa, peter.maydell, mdroth, mst, quintela,
	mark.cave-ayland, qemu-devel, mreitz, blauwirbel, amit.shah,
	qemu-ppc, kraxel, kwolf, dmitry, rth, leon.alrae, aurelien,
	david



On 05/10/2016 18:56, Dr. David Alan Gilbert wrote:
> * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
>> Currently we cannot directly transfer a QTAILQ instance because of the
>> limitation in the migration code. Here we introduce an approach to
>> transfer such structures. In our approach such a structure is tagged
>> with VMS_LINKED. We then modified vmstate_save_state and vmstate_load_state
>> so that when VMS_LINKED is encountered, put and get from VMStateInfo are
>> called respectively. We created VMStateInfo vmstate_info_qtailq for QTAILQ.
>> Similar VMStateInfo can be created for other data structures such as list.
>> This approach will be used to transfer pending_events and ccs_list in spapr
>> state.
>>
>> We also create some macros in qemu/queue.h to access a QTAILQ using pointer
>> arithmetic. This ensures that we do not depend on the implementation
>> details about QTAILQ in the migration code.
> 
> I think we're going to need a way to have a more flexible
> loops; and thus my choice here wouldn't be to use the .get/.put together
> with the VMSD; but I think we'll end up needing a new
> data structure, maybe a VMStateLoop *loop in VMStateField.

Or just realize that we already have a Turing-complete programming
language at our disposal, and it's called C. :)

> Specifically, your format of QTAILQ is perfectly reasonable - a
> byte before each entry which is 1 to indicate there's an entry or 0
> to indicate termination, but there are lots of other variants, e.g.
> 
>    a) put_scsi_requests uses that byte to hold a flag, so it's 0,1,2
>       0 still means terminate but 1 or 2 set a flag in the structure.

Seriously, the way I'd implement (a) is to make the QTAILQ reader peek
for the next byte.  If 0, eat it and exit the loop.  Otherwise, go ahead
with vmstate_load_state which will parse the byte again.

Likewise, on saving let the VMState write a non-zero byte at the
beginning, and then write a zero at the end.

Yes, it's sickening but that's what you do to honor backwards compatibility.

The other possibility is just to bump the version and make the SCSI
request flag a separate byte after the "is there another entry" byte.

Paolo

>    b) slirp_state_load also uses a null byte termination but not off a QTAILQ
>       (although I think it could be flipped for one) (it uses '42' for the
>       non-0 value, but looks like it could become 1)
> 
>    c) virtio_blk also rolls it's own linked list but again with the 0/1 byte
> 
>   Now how would I modify your QTAILQ load/store to do (a) without copying the whole
> thing?
> 
> Dave
> 
>>
>> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
>> ---
>>  include/migration/vmstate.h | 26 ++++++++++++++++++
>>  include/qemu/queue.h        | 32 ++++++++++++++++++++++
>>  migration/trace-events      |  4 +++
>>  migration/vmstate.c         | 66 +++++++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 128 insertions(+)
>>
>> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
>> index 459dd4a..e60c994 100644
>> --- a/include/migration/vmstate.h
>> +++ b/include/migration/vmstate.h
>> @@ -186,6 +186,12 @@ enum VMStateFlags {
>>       * to determine the number of entries in the array. Only valid in
>>       * combination with one of VMS_VARRAY*. */
>>      VMS_MULTIPLY_ELEMENTS = 0x4000,
>> +    /* For fields which need customized handling, such as QTAILQ in queue.h.
>> +     * When this flag is set in VMStateField, info->get/put will
>> +     * be used in vmstate_load/save_state instead of recursive call.
>> +     * User should implement set info to handle the concerned data structure.
>> +     */
>> +    VMS_LINKED            = 0x8000,
>>  };
>>  
>>  struct VMStateField {
>> @@ -246,6 +252,7 @@ extern const VMStateInfo vmstate_info_timer;
>>  extern const VMStateInfo vmstate_info_buffer;
>>  extern const VMStateInfo vmstate_info_unused_buffer;
>>  extern const VMStateInfo vmstate_info_bitmap;
>> +extern const VMStateInfo vmstate_info_qtailq;
>>  
>>  #define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0)
>>  #define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0)
>> @@ -657,6 +664,25 @@ extern const VMStateInfo vmstate_info_bitmap;
>>      .offset       = offsetof(_state, _field),                        \
>>  }
>>  
>> +/* For QTAILQ that need customized handling
>> + * _type: type of QTAILQ element
>> + * _next: name of QTAILQ entry field in QTAILQ element
>> + * _vmsd: VMSD for QTAILQ element
>> + * size: size of QTAILQ element
>> + * start: offset of QTAILQ entry in QTAILQ element
>> + */
>> +#define VMSTATE_QTAILQ_V(_field, _state, _version, _vmsd, _type, _next)  \
>> +{                                                                        \
>> +    .name         = (stringify(_field)),                                 \
>> +    .version_id   = (_version),                                          \
>> +    .vmsd         = &(_vmsd),                                            \
>> +    .size         = sizeof(_type),                                       \
>> +    .info         = &vmstate_info_qtailq,                                \
>> +    .flags        = VMS_LINKED,                                          \
>> +    .offset       = offsetof(_state, _field),                            \
>> +    .start        = offsetof(_type, _next),                              \
>> +}
>> +
>>  /* _f : field name
>>     _f_n : num of elements field_name
>>     _n : num of elements
>> diff --git a/include/qemu/queue.h b/include/qemu/queue.h
>> index 342073f..12c3f80 100644
>> --- a/include/qemu/queue.h
>> +++ b/include/qemu/queue.h
>> @@ -438,4 +438,36 @@ struct {                                                                \
>>  #define QTAILQ_PREV(elm, headname, field) \
>>          (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
>>  
>> +/*
>> + * Offsets of layout of a tail queue head.
>> + */
>> +#define QTAILQ_FIRST_OFFSET 0
>> +#define QTAILQ_LAST_OFFSET (sizeof(void *))
>> +
>> +/*
>> + * Offsets of layout of a tail queue element.
>> + */
>> +#define QTAILQ_NEXT_OFFSET 0
>> +#define QTAILQ_PREV_OFFSET (sizeof(void *))
>> +
>> +/*
>> + * Tail queue tranversal using pointer arithmetic.
>> + */
>> +#define QTAILQ_RAW_FOREACH(elm, head, entry)                                   \
>> +        for ((elm) = *((void **) ((char *) (head) + QTAILQ_FIRST_OFFSET));     \
>> +             (elm);                                                            \
>> +             (elm) =                                                           \
>> +                 *((void **) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET)))
>> +/*
>> + * Tail queue insertion using pointer arithmetic.
>> + */
>> +#define QTAILQ_RAW_INSERT_TAIL(head, elm, entry) do {                          \
>> +        *((void **) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET)) = NULL;   \
>> +        *((void **) ((char *) (elm) + (entry) + QTAILQ_PREV_OFFSET)) =         \
>> +            *((void **) ((char *) (head) +QTAILQ_LAST_OFFSET));                \
>> +        **((void ***)((char *) (head) +QTAILQ_LAST_OFFSET)) = (elm);           \
>> +        *((void **) ((char *) (head) + QTAILQ_LAST_OFFSET)) =                  \
>> +            (void *) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET);          \
>> +} while (/*CONSTCOND*/0)
>> +
>>  #endif /* QEMU_SYS_QUEUE_H */
>> diff --git a/migration/trace-events b/migration/trace-events
>> index dfee75a..9a6ec59 100644
>> --- a/migration/trace-events
>> +++ b/migration/trace-events
>> @@ -52,6 +52,10 @@ vmstate_n_elems(const char *name, int n_elems) "%s: %d"
>>  vmstate_subsection_load(const char *parent) "%s"
>>  vmstate_subsection_load_bad(const char *parent,  const char *sub, const char *sub2) "%s: %s/%s"
>>  vmstate_subsection_load_good(const char *parent) "%s"
>> +get_qtailq(const char *name, int version_id) "%s v%d"
>> +get_qtailq_end(const char *name, const char *reason, int val) "%s %s/%d"
>> +put_qtailq(const char *name, int version_id) "%s v%d"
>> +put_qtailq_end(const char *name, const char *reason) "%s %s"
>>  
>>  # migration/qemu-file.c
>>  qemu_file_fclose(void) ""
>> diff --git a/migration/vmstate.c b/migration/vmstate.c
>> index 66802cb..192db8a 100644
>> --- a/migration/vmstate.c
>> +++ b/migration/vmstate.c
>> @@ -5,7 +5,9 @@
>>  #include "migration/vmstate.h"
>>  #include "qemu/bitops.h"
>>  #include "qemu/error-report.h"
>> +#include "qemu/queue.h"
>>  #include "trace.h"
>> +#include "migration/qjson.h"
>>  
>>  static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
>>                                      void *opaque, QJSON *vmdesc);
>> @@ -121,6 +123,8 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
>>                  if (field->flags & VMS_STRUCT) {
>>                      ret = vmstate_load_state(f, field->vmsd, addr,
>>                                               field->vmsd->version_id);
>> +                } else if (field->flags & VMS_LINKED) {
>> +                    ret = field->info->get(f, addr, size, field);
>>                  } else {
>>                      ret = field->info->get(f, addr, size, NULL);
>>  
>> @@ -193,6 +197,8 @@ static const char *vmfield_get_type_name(VMStateField *field)
>>  
>>      if (field->flags & VMS_STRUCT) {
>>          type = "struct";
>> +    } else if (field->flags & VMS_LINKED) {
>> +        type = "linked";
>>      } else if (field->info->name) {
>>          type = field->info->name;
>>      }
>> @@ -327,6 +333,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
>>                  }
>>                  if (field->flags & VMS_STRUCT) {
>>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
>> +                } else if  (field->flags & VMS_LINKED) {
>> +                    field->info->put(f, addr, size, field, vmdesc_loop);
>>                  } else {
>>                      field->info->put(f, addr, size, NULL, NULL);
>>                  }
>> @@ -939,3 +947,61 @@ const VMStateInfo vmstate_info_bitmap = {
>>      .get = get_bitmap,
>>      .put = put_bitmap,
>>  };
>> +
>> +/*get for QTAILQ */
>> +static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
>> +                      VMStateField *field)
>> +{
>> +    int ret = 0;
>> +    const VMStateDescription *vmsd = field->vmsd;
>> +    size_t size = field->size;
>> +    size_t entry = field->start;
>> +    int version_id = field->version_id;
>> +    void *elm;
>> +
>> +    trace_get_qtailq(vmsd->name, version_id);
>> +    if (version_id > vmsd->version_id) {
>> +        trace_get_qtailq_end(vmsd->name, "too new", -EINVAL);
> 
> Can you make those error_report's please - if it fails we want to
> see why in the log.
> 
> Dave
> 
>> +        return -EINVAL;
>> +    }
>> +    if (version_id < vmsd->minimum_version_id) {
>> +        trace_get_qtailq_end(vmsd->name, "too old", -EINVAL);
>> +        return -EINVAL;
>> +    }
>> +
>> +    while (qemu_get_byte(f)) {
>> +        elm =  g_malloc(size);
>> +        ret = vmstate_load_state(f, vmsd, elm, version_id);
>> +        if (ret) {
>> +            return ret;
>> +        }
>> +        QTAILQ_RAW_INSERT_TAIL(pv, elm, entry);
>> +    }
>> +
>> +    trace_get_qtailq_end(vmsd->name, "end", ret);
>> +    return ret;
>> +}
>> +
>> +/* put for QTAILQ */
>> +static void put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
>> +                       VMStateField *field, QJSON *vmdesc)
>> +{
>> +    const VMStateDescription *vmsd = field->vmsd;
>> +    size_t entry = field->start;
>> +    void *elm;
>> +
>> +    trace_put_qtailq(vmsd->name, vmsd->version_id);
>> +
>> +    QTAILQ_RAW_FOREACH(elm, pv, entry) {
>> +        qemu_put_byte(f, true);
>> +        vmstate_save_state(f, vmsd, elm, vmdesc);
>> +    }
>> +    qemu_put_byte(f, false);
>> +
>> +    trace_put_qtailq_end(vmsd->name, "end");
>> +}
>> +const VMStateInfo vmstate_info_qtailq = {
>> +    .name = "qtailq",
>> +    .get  = get_qtailq,
>> +    .put  = put_qtailq,
>> +};
>> -- 
>> 1.9.1
>>
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
> 
> 

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

* Re: [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-06 11:05     ` [Qemu-devel] " Paolo Bonzini
@ 2016-10-06 11:56       ` Dr. David Alan Gilbert
  2016-10-06 12:23         ` Paolo Bonzini
  0 siblings, 1 reply; 66+ messages in thread
From: Dr. David Alan Gilbert @ 2016-10-06 11:56 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Jianjun Duan, veroniabahaa, peter.maydell, mdroth, mst, quintela,
	mark.cave-ayland, qemu-devel, mreitz, blauwirbel, amit.shah,
	qemu-ppc, kraxel, kwolf, dmitry, rth, leon.alrae, aurelien,
	david

* Paolo Bonzini (pbonzini@redhat.com) wrote:
> 
> 
> On 05/10/2016 18:56, Dr. David Alan Gilbert wrote:
> > * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> >> Currently we cannot directly transfer a QTAILQ instance because of the
> >> limitation in the migration code. Here we introduce an approach to
> >> transfer such structures. In our approach such a structure is tagged
> >> with VMS_LINKED. We then modified vmstate_save_state and vmstate_load_state
> >> so that when VMS_LINKED is encountered, put and get from VMStateInfo are
> >> called respectively. We created VMStateInfo vmstate_info_qtailq for QTAILQ.
> >> Similar VMStateInfo can be created for other data structures such as list.
> >> This approach will be used to transfer pending_events and ccs_list in spapr
> >> state.
> >>
> >> We also create some macros in qemu/queue.h to access a QTAILQ using pointer
> >> arithmetic. This ensures that we do not depend on the implementation
> >> details about QTAILQ in the migration code.
> > 
> > I think we're going to need a way to have a more flexible
> > loops; and thus my choice here wouldn't be to use the .get/.put together
> > with the VMSD; but I think we'll end up needing a new
> > data structure, maybe a VMStateLoop *loop in VMStateField.
> 
> Or just realize that we already have a Turing-complete programming
> language at our disposal, and it's called C. :)

Yes, and it does seem that the virtio migration code has used it to its
full abilities.

> > Specifically, your format of QTAILQ is perfectly reasonable - a
> > byte before each entry which is 1 to indicate there's an entry or 0
> > to indicate termination, but there are lots of other variants, e.g.
> > 
> >    a) put_scsi_requests uses that byte to hold a flag, so it's 0,1,2
> >       0 still means terminate but 1 or 2 set a flag in the structure.
> 
> Seriously, the way I'd implement (a) is to make the QTAILQ reader peek
> for the next byte.  If 0, eat it and exit the loop.  Otherwise, go ahead
> with vmstate_load_state which will parse the byte again.
> 
> Likewise, on saving let the VMState write a non-zero byte at the
> beginning, and then write a zero at the end.
> 
> Yes, it's sickening but that's what you do to honor backwards compatibility.

Actually, that's not *that* bad an idea.

Lets go with Jianjun's structure for the moment; we can always expand on it.

It seems we have ~3 concepts that feel partially independent:

    a) The format of the loop on the wire (eg one byte per iteration, 0 terminates)
    b) The way the list is represented (QTAILQ, simple array, device specific linked-list)
    c) The data gathered in each iteration
    d) The allocation of (c)

This patch has a,b,d all wrapped up together in the get/put functions -
where I was hoping to find a way to separate them a bit so that we
could say; I want a loop, with this format, into this data structure, using this allocator.

Dave

> The other possibility is just to bump the version and make the SCSI
> request flag a separate byte after the "is there another entry" byte.
> 
> Paolo
> 
> >    b) slirp_state_load also uses a null byte termination but not off a QTAILQ
> >       (although I think it could be flipped for one) (it uses '42' for the
> >       non-0 value, but looks like it could become 1)
> > 
> >    c) virtio_blk also rolls it's own linked list but again with the 0/1 byte
> > 
> >   Now how would I modify your QTAILQ load/store to do (a) without copying the whole
> > thing?
> > 
> > Dave
> > 
> >>
> >> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
> >> ---
> >>  include/migration/vmstate.h | 26 ++++++++++++++++++
> >>  include/qemu/queue.h        | 32 ++++++++++++++++++++++
> >>  migration/trace-events      |  4 +++
> >>  migration/vmstate.c         | 66 +++++++++++++++++++++++++++++++++++++++++++++
> >>  4 files changed, 128 insertions(+)
> >>
> >> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
> >> index 459dd4a..e60c994 100644
> >> --- a/include/migration/vmstate.h
> >> +++ b/include/migration/vmstate.h
> >> @@ -186,6 +186,12 @@ enum VMStateFlags {
> >>       * to determine the number of entries in the array. Only valid in
> >>       * combination with one of VMS_VARRAY*. */
> >>      VMS_MULTIPLY_ELEMENTS = 0x4000,
> >> +    /* For fields which need customized handling, such as QTAILQ in queue.h.
> >> +     * When this flag is set in VMStateField, info->get/put will
> >> +     * be used in vmstate_load/save_state instead of recursive call.
> >> +     * User should implement set info to handle the concerned data structure.
> >> +     */
> >> +    VMS_LINKED            = 0x8000,
> >>  };
> >>  
> >>  struct VMStateField {
> >> @@ -246,6 +252,7 @@ extern const VMStateInfo vmstate_info_timer;
> >>  extern const VMStateInfo vmstate_info_buffer;
> >>  extern const VMStateInfo vmstate_info_unused_buffer;
> >>  extern const VMStateInfo vmstate_info_bitmap;
> >> +extern const VMStateInfo vmstate_info_qtailq;
> >>  
> >>  #define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0)
> >>  #define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0)
> >> @@ -657,6 +664,25 @@ extern const VMStateInfo vmstate_info_bitmap;
> >>      .offset       = offsetof(_state, _field),                        \
> >>  }
> >>  
> >> +/* For QTAILQ that need customized handling
> >> + * _type: type of QTAILQ element
> >> + * _next: name of QTAILQ entry field in QTAILQ element
> >> + * _vmsd: VMSD for QTAILQ element
> >> + * size: size of QTAILQ element
> >> + * start: offset of QTAILQ entry in QTAILQ element
> >> + */
> >> +#define VMSTATE_QTAILQ_V(_field, _state, _version, _vmsd, _type, _next)  \
> >> +{                                                                        \
> >> +    .name         = (stringify(_field)),                                 \
> >> +    .version_id   = (_version),                                          \
> >> +    .vmsd         = &(_vmsd),                                            \
> >> +    .size         = sizeof(_type),                                       \
> >> +    .info         = &vmstate_info_qtailq,                                \
> >> +    .flags        = VMS_LINKED,                                          \
> >> +    .offset       = offsetof(_state, _field),                            \
> >> +    .start        = offsetof(_type, _next),                              \
> >> +}
> >> +
> >>  /* _f : field name
> >>     _f_n : num of elements field_name
> >>     _n : num of elements
> >> diff --git a/include/qemu/queue.h b/include/qemu/queue.h
> >> index 342073f..12c3f80 100644
> >> --- a/include/qemu/queue.h
> >> +++ b/include/qemu/queue.h
> >> @@ -438,4 +438,36 @@ struct {                                                                \
> >>  #define QTAILQ_PREV(elm, headname, field) \
> >>          (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
> >>  
> >> +/*
> >> + * Offsets of layout of a tail queue head.
> >> + */
> >> +#define QTAILQ_FIRST_OFFSET 0
> >> +#define QTAILQ_LAST_OFFSET (sizeof(void *))
> >> +
> >> +/*
> >> + * Offsets of layout of a tail queue element.
> >> + */
> >> +#define QTAILQ_NEXT_OFFSET 0
> >> +#define QTAILQ_PREV_OFFSET (sizeof(void *))
> >> +
> >> +/*
> >> + * Tail queue tranversal using pointer arithmetic.
> >> + */
> >> +#define QTAILQ_RAW_FOREACH(elm, head, entry)                                   \
> >> +        for ((elm) = *((void **) ((char *) (head) + QTAILQ_FIRST_OFFSET));     \
> >> +             (elm);                                                            \
> >> +             (elm) =                                                           \
> >> +                 *((void **) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET)))
> >> +/*
> >> + * Tail queue insertion using pointer arithmetic.
> >> + */
> >> +#define QTAILQ_RAW_INSERT_TAIL(head, elm, entry) do {                          \
> >> +        *((void **) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET)) = NULL;   \
> >> +        *((void **) ((char *) (elm) + (entry) + QTAILQ_PREV_OFFSET)) =         \
> >> +            *((void **) ((char *) (head) +QTAILQ_LAST_OFFSET));                \
> >> +        **((void ***)((char *) (head) +QTAILQ_LAST_OFFSET)) = (elm);           \
> >> +        *((void **) ((char *) (head) + QTAILQ_LAST_OFFSET)) =                  \
> >> +            (void *) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET);          \
> >> +} while (/*CONSTCOND*/0)
> >> +
> >>  #endif /* QEMU_SYS_QUEUE_H */
> >> diff --git a/migration/trace-events b/migration/trace-events
> >> index dfee75a..9a6ec59 100644
> >> --- a/migration/trace-events
> >> +++ b/migration/trace-events
> >> @@ -52,6 +52,10 @@ vmstate_n_elems(const char *name, int n_elems) "%s: %d"
> >>  vmstate_subsection_load(const char *parent) "%s"
> >>  vmstate_subsection_load_bad(const char *parent,  const char *sub, const char *sub2) "%s: %s/%s"
> >>  vmstate_subsection_load_good(const char *parent) "%s"
> >> +get_qtailq(const char *name, int version_id) "%s v%d"
> >> +get_qtailq_end(const char *name, const char *reason, int val) "%s %s/%d"
> >> +put_qtailq(const char *name, int version_id) "%s v%d"
> >> +put_qtailq_end(const char *name, const char *reason) "%s %s"
> >>  
> >>  # migration/qemu-file.c
> >>  qemu_file_fclose(void) ""
> >> diff --git a/migration/vmstate.c b/migration/vmstate.c
> >> index 66802cb..192db8a 100644
> >> --- a/migration/vmstate.c
> >> +++ b/migration/vmstate.c
> >> @@ -5,7 +5,9 @@
> >>  #include "migration/vmstate.h"
> >>  #include "qemu/bitops.h"
> >>  #include "qemu/error-report.h"
> >> +#include "qemu/queue.h"
> >>  #include "trace.h"
> >> +#include "migration/qjson.h"
> >>  
> >>  static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
> >>                                      void *opaque, QJSON *vmdesc);
> >> @@ -121,6 +123,8 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
> >>                  if (field->flags & VMS_STRUCT) {
> >>                      ret = vmstate_load_state(f, field->vmsd, addr,
> >>                                               field->vmsd->version_id);
> >> +                } else if (field->flags & VMS_LINKED) {
> >> +                    ret = field->info->get(f, addr, size, field);
> >>                  } else {
> >>                      ret = field->info->get(f, addr, size, NULL);
> >>  
> >> @@ -193,6 +197,8 @@ static const char *vmfield_get_type_name(VMStateField *field)
> >>  
> >>      if (field->flags & VMS_STRUCT) {
> >>          type = "struct";
> >> +    } else if (field->flags & VMS_LINKED) {
> >> +        type = "linked";
> >>      } else if (field->info->name) {
> >>          type = field->info->name;
> >>      }
> >> @@ -327,6 +333,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
> >>                  }
> >>                  if (field->flags & VMS_STRUCT) {
> >>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
> >> +                } else if  (field->flags & VMS_LINKED) {
> >> +                    field->info->put(f, addr, size, field, vmdesc_loop);
> >>                  } else {
> >>                      field->info->put(f, addr, size, NULL, NULL);
> >>                  }
> >> @@ -939,3 +947,61 @@ const VMStateInfo vmstate_info_bitmap = {
> >>      .get = get_bitmap,
> >>      .put = put_bitmap,
> >>  };
> >> +
> >> +/*get for QTAILQ */
> >> +static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
> >> +                      VMStateField *field)
> >> +{
> >> +    int ret = 0;
> >> +    const VMStateDescription *vmsd = field->vmsd;
> >> +    size_t size = field->size;
> >> +    size_t entry = field->start;
> >> +    int version_id = field->version_id;
> >> +    void *elm;
> >> +
> >> +    trace_get_qtailq(vmsd->name, version_id);
> >> +    if (version_id > vmsd->version_id) {
> >> +        trace_get_qtailq_end(vmsd->name, "too new", -EINVAL);
> > 
> > Can you make those error_report's please - if it fails we want to
> > see why in the log.
> > 
> > Dave
> > 
> >> +        return -EINVAL;
> >> +    }
> >> +    if (version_id < vmsd->minimum_version_id) {
> >> +        trace_get_qtailq_end(vmsd->name, "too old", -EINVAL);
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    while (qemu_get_byte(f)) {
> >> +        elm =  g_malloc(size);
> >> +        ret = vmstate_load_state(f, vmsd, elm, version_id);
> >> +        if (ret) {
> >> +            return ret;
> >> +        }
> >> +        QTAILQ_RAW_INSERT_TAIL(pv, elm, entry);
> >> +    }
> >> +
> >> +    trace_get_qtailq_end(vmsd->name, "end", ret);
> >> +    return ret;
> >> +}
> >> +
> >> +/* put for QTAILQ */
> >> +static void put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
> >> +                       VMStateField *field, QJSON *vmdesc)
> >> +{
> >> +    const VMStateDescription *vmsd = field->vmsd;
> >> +    size_t entry = field->start;
> >> +    void *elm;
> >> +
> >> +    trace_put_qtailq(vmsd->name, vmsd->version_id);
> >> +
> >> +    QTAILQ_RAW_FOREACH(elm, pv, entry) {
> >> +        qemu_put_byte(f, true);
> >> +        vmstate_save_state(f, vmsd, elm, vmdesc);
> >> +    }
> >> +    qemu_put_byte(f, false);
> >> +
> >> +    trace_put_qtailq_end(vmsd->name, "end");
> >> +}
> >> +const VMStateInfo vmstate_info_qtailq = {
> >> +    .name = "qtailq",
> >> +    .get  = get_qtailq,
> >> +    .put  = put_qtailq,
> >> +};
> >> -- 
> >> 1.9.1
> >>
> > --
> > Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
> > 
> > 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-06 11:56       ` Dr. David Alan Gilbert
@ 2016-10-06 12:23         ` Paolo Bonzini
  2016-10-06 15:21           ` Dr. David Alan Gilbert
  0 siblings, 1 reply; 66+ messages in thread
From: Paolo Bonzini @ 2016-10-06 12:23 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Jianjun Duan, veroniabahaa, peter.maydell, mdroth, mst, quintela,
	mark.cave-ayland, qemu-devel, mreitz, blauwirbel, amit.shah,
	qemu-ppc, kraxel, kwolf, dmitry, rth, leon.alrae, aurelien,
	david



On 06/10/2016 13:56, Dr. David Alan Gilbert wrote:
>> > Yes, it's sickening but that's what you do to honor backwards compatibility.
> Actually, that's not *that* bad an idea.
> 
> Lets go with Jianjun's structure for the moment; we can always expand on it.
> 
> It seems we have ~3 concepts that feel partially independent:
> 
>     a) The format of the loop on the wire (eg one byte per iteration, 0 terminates)
>     b) The way the list is represented (QTAILQ, simple array, device specific linked-list)
>     c) The data gathered in each iteration
>     d) The allocation of (c)
> 
> This patch has a,b,d all wrapped up together in the get/put functions -
> where I was hoping to find a way to separate them a bit so that we
> could say; I want a loop, with this format, into this data structure, using this allocator.

Yes, the sickening part is when the format of the loop intersects with
the format of the datastructure.

I agree with moving the allocator out of VMStateInfo and back into
VMStateField, but only as long as VMStateAllocator could replace other
VMS_* flags.

I'm not sure about the value in separating (a) and (b), but we can do
things one step at a time.

By the way, regarding this:

> The other possibility is just to bump the version and make the SCSI
> request flag a separate byte after the "is there another entry" byte.

There is another way to do it that is much more backwards-compatible.
Choose a "default" value of retry corresponding to what QEMU encodes as
a "1".  If it's different, use a subsection to encode that.  Migration
from old to new will fail if the wrong value of retry is used, because
it will see a 2 where the QTAILQ loop expects a zero or one.  Migration
from new to old will fail if the wrong value of retry is used, because
it will see a subsection header where the QTAILQ loop expects a zero or one.

I think this is acceptable, and it would only affect migration of USB
storage devices.

Paolo

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

* Re: [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-06 12:23         ` Paolo Bonzini
@ 2016-10-06 15:21           ` Dr. David Alan Gilbert
  0 siblings, 0 replies; 66+ messages in thread
From: Dr. David Alan Gilbert @ 2016-10-06 15:21 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Jianjun Duan, veroniabahaa, peter.maydell, mdroth, mst, quintela,
	mark.cave-ayland, qemu-devel, mreitz, blauwirbel, amit.shah,
	qemu-ppc, kraxel, kwolf, dmitry, rth, leon.alrae, aurelien,
	david

* Paolo Bonzini (pbonzini@redhat.com) wrote:
> 
> 
> On 06/10/2016 13:56, Dr. David Alan Gilbert wrote:
> >> > Yes, it's sickening but that's what you do to honor backwards compatibility.
> > Actually, that's not *that* bad an idea.
> > 
> > Lets go with Jianjun's structure for the moment; we can always expand on it.
> > 
> > It seems we have ~3 concepts that feel partially independent:
> > 
> >     a) The format of the loop on the wire (eg one byte per iteration, 0 terminates)
> >     b) The way the list is represented (QTAILQ, simple array, device specific linked-list)
> >     c) The data gathered in each iteration
> >     d) The allocation of (c)
> > 
> > This patch has a,b,d all wrapped up together in the get/put functions -
> > where I was hoping to find a way to separate them a bit so that we
> > could say; I want a loop, with this format, into this data structure, using this allocator.
> 
> Yes, the sickening part is when the format of the loop intersects with
> the format of the datastructure.

Yes.

> I agree with moving the allocator out of VMStateInfo and back into
> VMStateField, but only as long as VMStateAllocator could replace other
> VMS_* flags.
> 
> I'm not sure about the value in separating (a) and (b), but we can do
> things one step at a time.

The other observation is that in many of the cases the loop body uses
some state present in the outer state or in a value read prior to the
start of the loop.
For example virtio_blk_load_device uses the vdev pointer inside
the loop during the initialisation of each loaded request (I can see
some hacky ways of avoiding it but it's messy).

> By the way, regarding this:
> 
> > The other possibility is just to bump the version and make the SCSI
> > request flag a separate byte after the "is there another entry" byte.
> 
> There is another way to do it that is much more backwards-compatible.
> Choose a "default" value of retry corresponding to what QEMU encodes as
> a "1".  If it's different, use a subsection to encode that.  Migration
> from old to new will fail if the wrong value of retry is used, because
> it will see a 2 where the QTAILQ loop expects a zero or one.  Migration
> from new to old will fail if the wrong value of retry is used, because
> it will see a subsection header where the QTAILQ loop expects a zero or one.
> 
> I think this is acceptable, and it would only affect migration of USB
> storage devices.

Yes, it might be worth it in some of these cases; although I do try
and avoid breaking format at almost all costs.

Dave

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

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

* Re: [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-05 17:19     ` Jianjun Duan
@ 2016-10-06 19:01       ` Dr. David Alan Gilbert
  2016-10-06 19:49         ` Jianjun Duan
                           ` (2 more replies)
  0 siblings, 3 replies; 66+ messages in thread
From: Dr. David Alan Gilbert @ 2016-10-06 19:01 UTC (permalink / raw)
  To: Jianjun Duan
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth

* Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> 
> 
> On 10/05/2016 09:56 AM, Dr. David Alan Gilbert wrote:
> > * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> >> Currently we cannot directly transfer a QTAILQ instance because of the
> >> limitation in the migration code. Here we introduce an approach to
> >> transfer such structures. In our approach such a structure is tagged
> >> with VMS_LINKED. We then modified vmstate_save_state and vmstate_load_state
> >> so that when VMS_LINKED is encountered, put and get from VMStateInfo are
> >> called respectively. We created VMStateInfo vmstate_info_qtailq for QTAILQ.
> >> Similar VMStateInfo can be created for other data structures such as list.
> >> This approach will be used to transfer pending_events and ccs_list in spapr
> >> state.
> >>
> >> We also create some macros in qemu/queue.h to access a QTAILQ using pointer
> >> arithmetic. This ensures that we do not depend on the implementation
> >> details about QTAILQ in the migration code.
> > 
> > I think we're going to need a way to have a more flexible
> > loops; and thus my choice here wouldn't be to use the .get/.put together
> > with the VMSD; but I think we'll end up needing a new
> > data structure, maybe a VMStateLoop *loop in VMStateField.
> > 
> > So would it be easier if you added that new member, then you wouldn't have to
> > modify every get() and put() function that already exists in the previous patch.
> > 
> > Specifically, your format of QTAILQ is perfectly reasonable - a
> > byte before each entry which is 1 to indicate there's an entry or 0
> > to indicate termination, but there are lots of other variants, e.g.
> > 
> >    a) put_scsi_requests uses that byte to hold a flag, so it's 0,1,2
> >       0 still means terminate but 1 or 2 set a flag in the structure.
> 
> I quickly take a look of put_scsi_requests. It is transferring a QTAILQ of
> SCSIRequest. However it goes into the structure inside to dump the
> elements out.
> If using my approach, I would have a VMSD for SCSIRequest. The
> additional byte used to indicate the end of the queue would lie outside
> the SCSCIRequest data block, so there would be no confusion.

Hmm OK; I don't think it's that easy but we'll see.

However, can I make one much simpler request; please split this patch
so that the VMSTATE_LINKED and vmstate_save_state/vmstate_load_state/vmfield_get_type_name
are in one patch, while the QTAILQ patches are in a separate patch.
(I'd be OK if you moved the VMSTATE_LINKED into the previous patch).

I've just been thinking about a different use for the same mechanism;
I want to do a:
  VMSTATE_WITH_TMP(t1*, type1, type2, vmsd)

which also sets the LINKED, where the .get/.put allocate a temporary
structure (of type/size type2), set up *tmp = t1 and then do the vmstate_load/save
using the vmsd on the temporary; something like (untested):

static int get_tmp(QEMUFile *f, void *pv, size_t unused_size, VMStateField *field)
{
    const VMStateDescription *vmsd = field->vmsd;
    size_t size = field->size;
    int version_id = field->version_id;
    void *tmp = gmalloc(size);
    int ret;
    
    *(void **)tmp = pv;
    ret = vmstate_load_state(f, vmsd, tmp, version_id);
    gfree(tmp);
    return ret;
}

This can be in a generic macro; and we would impose that type2 must be a struct
with the first element is 'type1* parent' (compile checked).
This would work nicely for where we have to do some maths to generate some
temporary results prior to migration; the .pre_save of the vmsd can read the data
from pv->parent and write it to the other fields but not have to use
qemu_get_*/qemu_put_* at all.

Dave

> 
> >    b) slirp_state_load also uses a null byte termination but not off a QTAILQ
> >       (although I think it could be flipped for one) (it uses '42' for the
> >       non-0 value, but looks like it could become 1)
> 
> >    c) virtio_blk also rolls it's own linked list but again with the 0/1 byte
> > 
> >   Now how would I modify your QTAILQ load/store to do (a) without copying the whole
> > thing?
> > 
> > Dave
> > 
> >>
> >> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
> >> ---
> >>  include/migration/vmstate.h | 26 ++++++++++++++++++
> >>  include/qemu/queue.h        | 32 ++++++++++++++++++++++
> >>  migration/trace-events      |  4 +++
> >>  migration/vmstate.c         | 66 +++++++++++++++++++++++++++++++++++++++++++++
> >>  4 files changed, 128 insertions(+)
> >>
> >> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
> >> index 459dd4a..e60c994 100644
> >> --- a/include/migration/vmstate.h
> >> +++ b/include/migration/vmstate.h
> >> @@ -186,6 +186,12 @@ enum VMStateFlags {
> >>       * to determine the number of entries in the array. Only valid in
> >>       * combination with one of VMS_VARRAY*. */
> >>      VMS_MULTIPLY_ELEMENTS = 0x4000,
> >> +    /* For fields which need customized handling, such as QTAILQ in queue.h.
> >> +     * When this flag is set in VMStateField, info->get/put will
> >> +     * be used in vmstate_load/save_state instead of recursive call.
> >> +     * User should implement set info to handle the concerned data structure.
> >> +     */
> >> +    VMS_LINKED            = 0x8000,
> >>  };
> >>  
> >>  struct VMStateField {
> >> @@ -246,6 +252,7 @@ extern const VMStateInfo vmstate_info_timer;
> >>  extern const VMStateInfo vmstate_info_buffer;
> >>  extern const VMStateInfo vmstate_info_unused_buffer;
> >>  extern const VMStateInfo vmstate_info_bitmap;
> >> +extern const VMStateInfo vmstate_info_qtailq;
> >>  
> >>  #define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0)
> >>  #define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0)
> >> @@ -657,6 +664,25 @@ extern const VMStateInfo vmstate_info_bitmap;
> >>      .offset       = offsetof(_state, _field),                        \
> >>  }
> >>  
> >> +/* For QTAILQ that need customized handling
> >> + * _type: type of QTAILQ element
> >> + * _next: name of QTAILQ entry field in QTAILQ element
> >> + * _vmsd: VMSD for QTAILQ element
> >> + * size: size of QTAILQ element
> >> + * start: offset of QTAILQ entry in QTAILQ element
> >> + */
> >> +#define VMSTATE_QTAILQ_V(_field, _state, _version, _vmsd, _type, _next)  \
> >> +{                                                                        \
> >> +    .name         = (stringify(_field)),                                 \
> >> +    .version_id   = (_version),                                          \
> >> +    .vmsd         = &(_vmsd),                                            \
> >> +    .size         = sizeof(_type),                                       \
> >> +    .info         = &vmstate_info_qtailq,                                \
> >> +    .flags        = VMS_LINKED,                                          \
> >> +    .offset       = offsetof(_state, _field),                            \
> >> +    .start        = offsetof(_type, _next),                              \
> >> +}
> >> +
> >>  /* _f : field name
> >>     _f_n : num of elements field_name
> >>     _n : num of elements
> >> diff --git a/include/qemu/queue.h b/include/qemu/queue.h
> >> index 342073f..12c3f80 100644
> >> --- a/include/qemu/queue.h
> >> +++ b/include/qemu/queue.h
> >> @@ -438,4 +438,36 @@ struct {                                                                \
> >>  #define QTAILQ_PREV(elm, headname, field) \
> >>          (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
> >>  
> >> +/*
> >> + * Offsets of layout of a tail queue head.
> >> + */
> >> +#define QTAILQ_FIRST_OFFSET 0
> >> +#define QTAILQ_LAST_OFFSET (sizeof(void *))
> >> +
> >> +/*
> >> + * Offsets of layout of a tail queue element.
> >> + */
> >> +#define QTAILQ_NEXT_OFFSET 0
> >> +#define QTAILQ_PREV_OFFSET (sizeof(void *))
> >> +
> >> +/*
> >> + * Tail queue tranversal using pointer arithmetic.
> >> + */
> >> +#define QTAILQ_RAW_FOREACH(elm, head, entry)                                   \
> >> +        for ((elm) = *((void **) ((char *) (head) + QTAILQ_FIRST_OFFSET));     \
> >> +             (elm);                                                            \
> >> +             (elm) =                                                           \
> >> +                 *((void **) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET)))
> >> +/*
> >> + * Tail queue insertion using pointer arithmetic.
> >> + */
> >> +#define QTAILQ_RAW_INSERT_TAIL(head, elm, entry) do {                          \
> >> +        *((void **) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET)) = NULL;   \
> >> +        *((void **) ((char *) (elm) + (entry) + QTAILQ_PREV_OFFSET)) =         \
> >> +            *((void **) ((char *) (head) +QTAILQ_LAST_OFFSET));                \
> >> +        **((void ***)((char *) (head) +QTAILQ_LAST_OFFSET)) = (elm);           \
> >> +        *((void **) ((char *) (head) + QTAILQ_LAST_OFFSET)) =                  \
> >> +            (void *) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET);          \
> >> +} while (/*CONSTCOND*/0)
> >> +
> >>  #endif /* QEMU_SYS_QUEUE_H */
> >> diff --git a/migration/trace-events b/migration/trace-events
> >> index dfee75a..9a6ec59 100644
> >> --- a/migration/trace-events
> >> +++ b/migration/trace-events
> >> @@ -52,6 +52,10 @@ vmstate_n_elems(const char *name, int n_elems) "%s: %d"
> >>  vmstate_subsection_load(const char *parent) "%s"
> >>  vmstate_subsection_load_bad(const char *parent,  const char *sub, const char *sub2) "%s: %s/%s"
> >>  vmstate_subsection_load_good(const char *parent) "%s"
> >> +get_qtailq(const char *name, int version_id) "%s v%d"
> >> +get_qtailq_end(const char *name, const char *reason, int val) "%s %s/%d"
> >> +put_qtailq(const char *name, int version_id) "%s v%d"
> >> +put_qtailq_end(const char *name, const char *reason) "%s %s"
> >>  
> >>  # migration/qemu-file.c
> >>  qemu_file_fclose(void) ""
> >> diff --git a/migration/vmstate.c b/migration/vmstate.c
> >> index 66802cb..192db8a 100644
> >> --- a/migration/vmstate.c
> >> +++ b/migration/vmstate.c
> >> @@ -5,7 +5,9 @@
> >>  #include "migration/vmstate.h"
> >>  #include "qemu/bitops.h"
> >>  #include "qemu/error-report.h"
> >> +#include "qemu/queue.h"
> >>  #include "trace.h"
> >> +#include "migration/qjson.h"
> >>  
> >>  static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
> >>                                      void *opaque, QJSON *vmdesc);
> >> @@ -121,6 +123,8 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
> >>                  if (field->flags & VMS_STRUCT) {
> >>                      ret = vmstate_load_state(f, field->vmsd, addr,
> >>                                               field->vmsd->version_id);
> >> +                } else if (field->flags & VMS_LINKED) {
> >> +                    ret = field->info->get(f, addr, size, field);
> >>                  } else {
> >>                      ret = field->info->get(f, addr, size, NULL);
> >>  
> >> @@ -193,6 +197,8 @@ static const char *vmfield_get_type_name(VMStateField *field)
> >>  
> >>      if (field->flags & VMS_STRUCT) {
> >>          type = "struct";
> >> +    } else if (field->flags & VMS_LINKED) {
> >> +        type = "linked";
> >>      } else if (field->info->name) {
> >>          type = field->info->name;
> >>      }
> >> @@ -327,6 +333,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
> >>                  }
> >>                  if (field->flags & VMS_STRUCT) {
> >>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
> >> +                } else if  (field->flags & VMS_LINKED) {
> >> +                    field->info->put(f, addr, size, field, vmdesc_loop);
> >>                  } else {
> >>                      field->info->put(f, addr, size, NULL, NULL);
> >>                  }
> >> @@ -939,3 +947,61 @@ const VMStateInfo vmstate_info_bitmap = {
> >>      .get = get_bitmap,
> >>      .put = put_bitmap,
> >>  };
> >> +
> >> +/*get for QTAILQ */
> >> +static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
> >> +                      VMStateField *field)
> >> +{
> >> +    int ret = 0;
> >> +    const VMStateDescription *vmsd = field->vmsd;
> >> +    size_t size = field->size;
> >> +    size_t entry = field->start;
> >> +    int version_id = field->version_id;
> >> +    void *elm;
> >> +
> >> +    trace_get_qtailq(vmsd->name, version_id);
> >> +    if (version_id > vmsd->version_id) {
> >> +        trace_get_qtailq_end(vmsd->name, "too new", -EINVAL);
> > 
> > Can you make those error_report's please - if it fails we want to
> > see why in the log.
> > 
> > Dave
> > 
> >> +        return -EINVAL;
> >> +    }
> >> +    if (version_id < vmsd->minimum_version_id) {
> >> +        trace_get_qtailq_end(vmsd->name, "too old", -EINVAL);
> >> +        return -EINVAL;
> >> +    }
> >> +
> >> +    while (qemu_get_byte(f)) {
> >> +        elm =  g_malloc(size);
> >> +        ret = vmstate_load_state(f, vmsd, elm, version_id);
> >> +        if (ret) {
> >> +            return ret;
> >> +        }
> >> +        QTAILQ_RAW_INSERT_TAIL(pv, elm, entry);
> >> +    }
> >> +
> >> +    trace_get_qtailq_end(vmsd->name, "end", ret);
> >> +    return ret;
> >> +}
> >> +
> >> +/* put for QTAILQ */
> >> +static void put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
> >> +                       VMStateField *field, QJSON *vmdesc)
> >> +{
> >> +    const VMStateDescription *vmsd = field->vmsd;
> >> +    size_t entry = field->start;
> >> +    void *elm;
> >> +
> >> +    trace_put_qtailq(vmsd->name, vmsd->version_id);
> >> +
> >> +    QTAILQ_RAW_FOREACH(elm, pv, entry) {
> >> +        qemu_put_byte(f, true);
> >> +        vmstate_save_state(f, vmsd, elm, vmdesc);
> >> +    }
> >> +    qemu_put_byte(f, false);
> >> +
> >> +    trace_put_qtailq_end(vmsd->name, "end");
> >> +}
> >> +const VMStateInfo vmstate_info_qtailq = {
> >> +    .name = "qtailq",
> >> +    .get  = get_qtailq,
> >> +    .put  = put_qtailq,
> >> +};
> >> -- 
> >> 1.9.1
> >>
> > --
> > Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
> > 
> Thanks,
> Jianjun
> 
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-06 19:01       ` Dr. David Alan Gilbert
@ 2016-10-06 19:49         ` Jianjun Duan
  2016-10-07  3:25         ` David Gibson
  2016-10-07 14:31         ` Paolo Bonzini
  2 siblings, 0 replies; 66+ messages in thread
From: Jianjun Duan @ 2016-10-06 19:49 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: veroniabahaa, peter.maydell, mdroth, mst, quintela,
	mark.cave-ayland, qemu-devel, mreitz, blauwirbel, amit.shah,
	qemu-ppc, kraxel, kwolf, dmitry, pbonzini, rth, leon.alrae,
	aurelien, david



On 10/06/2016 12:01 PM, Dr. David Alan Gilbert wrote:
> * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
>>
>>
>> On 10/05/2016 09:56 AM, Dr. David Alan Gilbert wrote:
>>> * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
>>>> Currently we cannot directly transfer a QTAILQ instance because of the
>>>> limitation in the migration code. Here we introduce an approach to
>>>> transfer such structures. In our approach such a structure is tagged
>>>> with VMS_LINKED. We then modified vmstate_save_state and vmstate_load_state
>>>> so that when VMS_LINKED is encountered, put and get from VMStateInfo are
>>>> called respectively. We created VMStateInfo vmstate_info_qtailq for QTAILQ.
>>>> Similar VMStateInfo can be created for other data structures such as list.
>>>> This approach will be used to transfer pending_events and ccs_list in spapr
>>>> state.
>>>>
>>>> We also create some macros in qemu/queue.h to access a QTAILQ using pointer
>>>> arithmetic. This ensures that we do not depend on the implementation
>>>> details about QTAILQ in the migration code.
>>>
>>> I think we're going to need a way to have a more flexible
>>> loops; and thus my choice here wouldn't be to use the .get/.put together
>>> with the VMSD; but I think we'll end up needing a new
>>> data structure, maybe a VMStateLoop *loop in VMStateField.
>>>
>>> So would it be easier if you added that new member, then you wouldn't have to
>>> modify every get() and put() function that already exists in the previous patch.
>>>
>>> Specifically, your format of QTAILQ is perfectly reasonable - a
>>> byte before each entry which is 1 to indicate there's an entry or 0
>>> to indicate termination, but there are lots of other variants, e.g.
>>>
>>>    a) put_scsi_requests uses that byte to hold a flag, so it's 0,1,2
>>>       0 still means terminate but 1 or 2 set a flag in the structure.
>>
>> I quickly take a look of put_scsi_requests. It is transferring a QTAILQ of
>> SCSIRequest. However it goes into the structure inside to dump the
>> elements out.
>> If using my approach, I would have a VMSD for SCSIRequest. The
>> additional byte used to indicate the end of the queue would lie outside
>> the SCSCIRequest data block, so there would be no confusion.
> 
> Hmm OK; I don't think it's that easy but we'll see.
> 
It is more complicated if we want to use the exact stream as is now.
IMO VMStateInfo provides enough flexibility and is used for migrating
scsi_requests. I would stick with it if the same stream layout is to be
used.
> However, can I make one much simpler request; please split this patch
> so that the VMSTATE_LINKED and vmstate_save_state/vmstate_load_state/vmfield_get_type_name
> are in one patch, while the QTAILQ patches are in a separate patch.
> (I'd be OK if you moved the VMSTATE_LINKED into the previous patch).
>

OK.

> I've just been thinking about a different use for the same mechanism;
> I want to do a:
>   VMSTATE_WITH_TMP(t1*, type1, type2, vmsd)
> 
> which also sets the LINKED, where the .get/.put allocate a temporary
> structure (of type/size type2), set up *tmp = t1 and then do the vmstate_load/save
> using the vmsd on the temporary; something like (untested):
> 
> static int get_tmp(QEMUFile *f, void *pv, size_t unused_size, VMStateField *field)
> {
>     const VMStateDescription *vmsd = field->vmsd;
>     size_t size = field->size;
>     int version_id = field->version_id;
>     void *tmp = gmalloc(size);
>     int ret;
>     
>     *(void **)tmp = pv;
>     ret = vmstate_load_state(f, vmsd, tmp, version_id);
>     gfree(tmp);
>     return ret;
> }
> 
> This can be in a generic macro; and we would impose that type2 must be a struct
> with the first element is 'type1* parent' (compile checked).
> This would work nicely for where we have to do some maths to generate some
> temporary results prior to migration; the .pre_save of the vmsd can read the data
> from pv->parent and write it to the other fields but not have to use
> qemu_get_*/qemu_put_* at all.
>

This could be a special instance of VMStateInfo.

> Dave
> 
>>
>>>    b) slirp_state_load also uses a null byte termination but not off a QTAILQ
>>>       (although I think it could be flipped for one) (it uses '42' for the
>>>       non-0 value, but looks like it could become 1)
>>
>>>    c) virtio_blk also rolls it's own linked list but again with the 0/1 byte
>>>
>>>   Now how would I modify your QTAILQ load/store to do (a) without copying the whole
>>> thing?
>>>
>>> Dave
>>>
>>>>
>>>> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
>>>> ---
>>>>  include/migration/vmstate.h | 26 ++++++++++++++++++
>>>>  include/qemu/queue.h        | 32 ++++++++++++++++++++++
>>>>  migration/trace-events      |  4 +++
>>>>  migration/vmstate.c         | 66 +++++++++++++++++++++++++++++++++++++++++++++
>>>>  4 files changed, 128 insertions(+)
>>>>
>>>> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
>>>> index 459dd4a..e60c994 100644
>>>> --- a/include/migration/vmstate.h
>>>> +++ b/include/migration/vmstate.h
>>>> @@ -186,6 +186,12 @@ enum VMStateFlags {
>>>>       * to determine the number of entries in the array. Only valid in
>>>>       * combination with one of VMS_VARRAY*. */
>>>>      VMS_MULTIPLY_ELEMENTS = 0x4000,
>>>> +    /* For fields which need customized handling, such as QTAILQ in queue.h.
>>>> +     * When this flag is set in VMStateField, info->get/put will
>>>> +     * be used in vmstate_load/save_state instead of recursive call.
>>>> +     * User should implement set info to handle the concerned data structure.
>>>> +     */
>>>> +    VMS_LINKED            = 0x8000,
>>>>  };
>>>>  
>>>>  struct VMStateField {
>>>> @@ -246,6 +252,7 @@ extern const VMStateInfo vmstate_info_timer;
>>>>  extern const VMStateInfo vmstate_info_buffer;
>>>>  extern const VMStateInfo vmstate_info_unused_buffer;
>>>>  extern const VMStateInfo vmstate_info_bitmap;
>>>> +extern const VMStateInfo vmstate_info_qtailq;
>>>>  
>>>>  #define type_check_2darray(t1,t2,n,m) ((t1(*)[n][m])0 - (t2*)0)
>>>>  #define type_check_array(t1,t2,n) ((t1(*)[n])0 - (t2*)0)
>>>> @@ -657,6 +664,25 @@ extern const VMStateInfo vmstate_info_bitmap;
>>>>      .offset       = offsetof(_state, _field),                        \
>>>>  }
>>>>  
>>>> +/* For QTAILQ that need customized handling
>>>> + * _type: type of QTAILQ element
>>>> + * _next: name of QTAILQ entry field in QTAILQ element
>>>> + * _vmsd: VMSD for QTAILQ element
>>>> + * size: size of QTAILQ element
>>>> + * start: offset of QTAILQ entry in QTAILQ element
>>>> + */
>>>> +#define VMSTATE_QTAILQ_V(_field, _state, _version, _vmsd, _type, _next)  \
>>>> +{                                                                        \
>>>> +    .name         = (stringify(_field)),                                 \
>>>> +    .version_id   = (_version),                                          \
>>>> +    .vmsd         = &(_vmsd),                                            \
>>>> +    .size         = sizeof(_type),                                       \
>>>> +    .info         = &vmstate_info_qtailq,                                \
>>>> +    .flags        = VMS_LINKED,                                          \
>>>> +    .offset       = offsetof(_state, _field),                            \
>>>> +    .start        = offsetof(_type, _next),                              \
>>>> +}
>>>> +
>>>>  /* _f : field name
>>>>     _f_n : num of elements field_name
>>>>     _n : num of elements
>>>> diff --git a/include/qemu/queue.h b/include/qemu/queue.h
>>>> index 342073f..12c3f80 100644
>>>> --- a/include/qemu/queue.h
>>>> +++ b/include/qemu/queue.h
>>>> @@ -438,4 +438,36 @@ struct {                                                                \
>>>>  #define QTAILQ_PREV(elm, headname, field) \
>>>>          (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
>>>>  
>>>> +/*
>>>> + * Offsets of layout of a tail queue head.
>>>> + */
>>>> +#define QTAILQ_FIRST_OFFSET 0
>>>> +#define QTAILQ_LAST_OFFSET (sizeof(void *))
>>>> +
>>>> +/*
>>>> + * Offsets of layout of a tail queue element.
>>>> + */
>>>> +#define QTAILQ_NEXT_OFFSET 0
>>>> +#define QTAILQ_PREV_OFFSET (sizeof(void *))
>>>> +
>>>> +/*
>>>> + * Tail queue tranversal using pointer arithmetic.
>>>> + */
>>>> +#define QTAILQ_RAW_FOREACH(elm, head, entry)                                   \
>>>> +        for ((elm) = *((void **) ((char *) (head) + QTAILQ_FIRST_OFFSET));     \
>>>> +             (elm);                                                            \
>>>> +             (elm) =                                                           \
>>>> +                 *((void **) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET)))
>>>> +/*
>>>> + * Tail queue insertion using pointer arithmetic.
>>>> + */
>>>> +#define QTAILQ_RAW_INSERT_TAIL(head, elm, entry) do {                          \
>>>> +        *((void **) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET)) = NULL;   \
>>>> +        *((void **) ((char *) (elm) + (entry) + QTAILQ_PREV_OFFSET)) =         \
>>>> +            *((void **) ((char *) (head) +QTAILQ_LAST_OFFSET));                \
>>>> +        **((void ***)((char *) (head) +QTAILQ_LAST_OFFSET)) = (elm);           \
>>>> +        *((void **) ((char *) (head) + QTAILQ_LAST_OFFSET)) =                  \
>>>> +            (void *) ((char *) (elm) + (entry) + QTAILQ_NEXT_OFFSET);          \
>>>> +} while (/*CONSTCOND*/0)
>>>> +
>>>>  #endif /* QEMU_SYS_QUEUE_H */
>>>> diff --git a/migration/trace-events b/migration/trace-events
>>>> index dfee75a..9a6ec59 100644
>>>> --- a/migration/trace-events
>>>> +++ b/migration/trace-events
>>>> @@ -52,6 +52,10 @@ vmstate_n_elems(const char *name, int n_elems) "%s: %d"
>>>>  vmstate_subsection_load(const char *parent) "%s"
>>>>  vmstate_subsection_load_bad(const char *parent,  const char *sub, const char *sub2) "%s: %s/%s"
>>>>  vmstate_subsection_load_good(const char *parent) "%s"
>>>> +get_qtailq(const char *name, int version_id) "%s v%d"
>>>> +get_qtailq_end(const char *name, const char *reason, int val) "%s %s/%d"
>>>> +put_qtailq(const char *name, int version_id) "%s v%d"
>>>> +put_qtailq_end(const char *name, const char *reason) "%s %s"
>>>>  
>>>>  # migration/qemu-file.c
>>>>  qemu_file_fclose(void) ""
>>>> diff --git a/migration/vmstate.c b/migration/vmstate.c
>>>> index 66802cb..192db8a 100644
>>>> --- a/migration/vmstate.c
>>>> +++ b/migration/vmstate.c
>>>> @@ -5,7 +5,9 @@
>>>>  #include "migration/vmstate.h"
>>>>  #include "qemu/bitops.h"
>>>>  #include "qemu/error-report.h"
>>>> +#include "qemu/queue.h"
>>>>  #include "trace.h"
>>>> +#include "migration/qjson.h"
>>>>  
>>>>  static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
>>>>                                      void *opaque, QJSON *vmdesc);
>>>> @@ -121,6 +123,8 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
>>>>                  if (field->flags & VMS_STRUCT) {
>>>>                      ret = vmstate_load_state(f, field->vmsd, addr,
>>>>                                               field->vmsd->version_id);
>>>> +                } else if (field->flags & VMS_LINKED) {
>>>> +                    ret = field->info->get(f, addr, size, field);
>>>>                  } else {
>>>>                      ret = field->info->get(f, addr, size, NULL);
>>>>  
>>>> @@ -193,6 +197,8 @@ static const char *vmfield_get_type_name(VMStateField *field)
>>>>  
>>>>      if (field->flags & VMS_STRUCT) {
>>>>          type = "struct";
>>>> +    } else if (field->flags & VMS_LINKED) {
>>>> +        type = "linked";
>>>>      } else if (field->info->name) {
>>>>          type = field->info->name;
>>>>      }
>>>> @@ -327,6 +333,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
>>>>                  }
>>>>                  if (field->flags & VMS_STRUCT) {
>>>>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
>>>> +                } else if  (field->flags & VMS_LINKED) {
>>>> +                    field->info->put(f, addr, size, field, vmdesc_loop);
>>>>                  } else {
>>>>                      field->info->put(f, addr, size, NULL, NULL);
>>>>                  }
>>>> @@ -939,3 +947,61 @@ const VMStateInfo vmstate_info_bitmap = {
>>>>      .get = get_bitmap,
>>>>      .put = put_bitmap,
>>>>  };
>>>> +
>>>> +/*get for QTAILQ */
>>>> +static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
>>>> +                      VMStateField *field)
>>>> +{
>>>> +    int ret = 0;
>>>> +    const VMStateDescription *vmsd = field->vmsd;
>>>> +    size_t size = field->size;
>>>> +    size_t entry = field->start;
>>>> +    int version_id = field->version_id;
>>>> +    void *elm;
>>>> +
>>>> +    trace_get_qtailq(vmsd->name, version_id);
>>>> +    if (version_id > vmsd->version_id) {
>>>> +        trace_get_qtailq_end(vmsd->name, "too new", -EINVAL);
>>>
>>> Can you make those error_report's please - if it fails we want to
>>> see why in the log.
>>>
>>> Dave
>>>
>>>> +        return -EINVAL;
>>>> +    }
>>>> +    if (version_id < vmsd->minimum_version_id) {
>>>> +        trace_get_qtailq_end(vmsd->name, "too old", -EINVAL);
>>>> +        return -EINVAL;
>>>> +    }
>>>> +
>>>> +    while (qemu_get_byte(f)) {
>>>> +        elm =  g_malloc(size);
>>>> +        ret = vmstate_load_state(f, vmsd, elm, version_id);
>>>> +        if (ret) {
>>>> +            return ret;
>>>> +        }
>>>> +        QTAILQ_RAW_INSERT_TAIL(pv, elm, entry);
>>>> +    }
>>>> +
>>>> +    trace_get_qtailq_end(vmsd->name, "end", ret);
>>>> +    return ret;
>>>> +}
>>>> +
>>>> +/* put for QTAILQ */
>>>> +static void put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
>>>> +                       VMStateField *field, QJSON *vmdesc)
>>>> +{
>>>> +    const VMStateDescription *vmsd = field->vmsd;
>>>> +    size_t entry = field->start;
>>>> +    void *elm;
>>>> +
>>>> +    trace_put_qtailq(vmsd->name, vmsd->version_id);
>>>> +
>>>> +    QTAILQ_RAW_FOREACH(elm, pv, entry) {
>>>> +        qemu_put_byte(f, true);
>>>> +        vmstate_save_state(f, vmsd, elm, vmdesc);
>>>> +    }
>>>> +    qemu_put_byte(f, false);
>>>> +
>>>> +    trace_put_qtailq_end(vmsd->name, "end");
>>>> +}
>>>> +const VMStateInfo vmstate_info_qtailq = {
>>>> +    .name = "qtailq",
>>>> +    .get  = get_qtailq,
>>>> +    .put  = put_qtailq,
>>>> +};
>>>> -- 
>>>> 1.9.1
>>>>
>>> --
>>> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
>>>
>> Thanks,
>> Jianjun
>>
>>
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
> 
Thanks,
Jianjun

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

* Re: [Qemu-devel] [QEMU PATCH v5 1/6] migration: alternative way to set instance_id in SaveStateEntry
  2016-10-05 16:44     ` Jianjun Duan
@ 2016-10-07  2:54       ` David Gibson
  2016-10-07  8:07         ` Dr. David Alan Gilbert
  2016-11-15 23:45         ` Michael Roth
  0 siblings, 2 replies; 66+ messages in thread
From: David Gibson @ 2016-10-07  2:54 UTC (permalink / raw)
  To: Jianjun Duan
  Cc: Dr. David Alan Gilbert, qemu-devel, qemu-ppc, dmitry,
	peter.maydell, kraxel, mst, pbonzini, veroniabahaa, quintela,
	amit.shah, mreitz, kwolf, rth, aurelien, leon.alrae, blauwirbel,
	mark.cave-ayland, mdroth

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

On Wed, Oct 05, 2016 at 09:44:57AM -0700, Jianjun Duan wrote:
> Please see comments below:
> 
> On 10/05/2016 03:12 AM, Dr. David Alan Gilbert wrote:
> > * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> >> In QOM(QEMU Object Model) migrated objects are identified with instance_id
> >> which is calculated automatically using their path in the QOM composition
> >> tree. For some objects, this path could change from source to target in
> >> migration. To migrate such objects, we need to make sure the instance_id does
> >> not change from source to target. We add a hook in DeviceClass to do customized
> >> instance_id calculation in such cases.
> > 
> > Can you explain a bit about why the path changes from source to destination;
> > the path here should be a feature of the guest state not the host, and so I
> > don't understand why it changes.
> Please see the discussion with David in the previous versions:
> http://lists.nongnu.org/archive/html/qemu-ppc/2016-06/msg00062.html

Um.. your description above really isn't an accurate summary of that
discussion.

The point is not that the qom path will vary from source to
destination for some arbitrary reason, but rather that we anticipate
future changes in the QOM structure.  Specifically we're considering
eliminating the DRC objects, and folding their (limited) state into an
array in the parent object (either the machine or a PCI host bridge).

That would change the qom paths, and hence the auto-generated instance
ids, which would break migration between qemu versions before and
after the restructure.

I'm not sure that changing the instance ids is enough though, anyway,
since we're talking about eliminating the object entirely, the
class/type information in the migration stream also wouldn't match.

Dave, if you have ideas on how to deal with that, I'd love to hear
them

> 
> >> As a result, in these cases compat will not be set in the concerned
> >> SaveStateEntry. This will prevent the inconsistent idstr to be sent over in
> >> migration. We could have set alias_id in a similar way. But that will be
> >> overloading the purpose of alias_id.
> >>
> >> The first application will be setting instance_id for DRC using its unique
> >> index. Doing this makes the instance_id of DRC to be consistent across migration
> >> and supports flexible management of DRC objects in migration.
> > 
> > Is there a reason to use a custom instance_id rather than a custom idstr
> 
> It can be done either way. But it is easier to deal with a integer than
> a string.

A bit, but I don't think that's a good enough reason to introduce a
second mechanism for overriding instance id allocations.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [Qemu-devel] [QEMU PATCH v5 2/6] migration: spapr_drc: defined VMStateDescription struct
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 2/6] migration: spapr_drc: defined VMStateDescription struct Jianjun Duan
  2016-10-05 11:38   ` Dr. David Alan Gilbert
@ 2016-10-07  3:12   ` David Gibson
  2016-10-07 17:17     ` Jianjun Duan
  1 sibling, 1 reply; 66+ messages in thread
From: David Gibson @ 2016-10-07  3:12 UTC (permalink / raw)
  To: Jianjun Duan
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth,
	dgilbert

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

On Mon, Oct 03, 2016 at 11:24:53AM -0700, Jianjun Duan wrote:
> To manage hotplug/unplug of dynamic resources such as PCI cards,
> memory, and CPU on sPAPR guests, a firmware abstraction known as
> a Dynamic Resource Connector (DRC) is used to assign a particular
> dynamic resource to the guest, and provide an interface for the
> guest to manage configuration/removal of the resource associated
> with it.
> 
> To migrate the hotplugged resources in migration, the
> associated DRC state need be migrated. To migrate the DRC state,
> we defined the VMStateDescription struct for spapr_drc to enable
> the transmission of spapr_drc state in migration.
> 
> Not all the elements in the DRC state are migrated. Only those
> ones modifiable or needed by guest actions or device add/remove
> operation are migrated. From the perspective of device
> hotplugging, if we hotplug a device on the source, we need to
> "coldplug" it on the target. The states across two hosts for the
> same device are not the same. Ideally we want the states be same
> after migration so that the device would function as hotplugged
> on the target. For example we can unplug it. The minimum DRC
> state we need to transfer should cover all the pieces changed by
> hotplugging. Out of the elements of the DRC state, isolation_state,
> allocation_sate, and configured are involved in the DR state
> transition diagram from PAPR+ 2.7, 13.4. configured and signalled
> are needed in attaching and detaching devices. indicator_state
> provides users with hardware state information. These 6 elements
> are migrated.

Hmm.. are you saying that the DRC state of a coldplugged device (after
we've fully booted) is different from the DRC state of a hotplugged
device (after all the hotplug operations have fully completed)?

If that's correct that sounds like a general bug in the DRC state
management, not something only related to migration.

Looking at the code, though, that doesn't really seem to be what it's
doing.

> detach_cb in the DRC state is a function pointer that cannot be
> migrated. We set it right after DRC state is migrated so that
> a migrated hot-unplug event could finish its work.
> 
> The instance_id is used to identify objects in migration. We set
> instance_id of DRC using the unique index so that it is the same
> across migration.
> 
> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
> ---
>  hw/ppc/spapr_drc.c         | 69 ++++++++++++++++++++++++++++++++++++++++++++++
>  hw/ppc/spapr_pci.c         | 22 +++++++++++++++
>  include/hw/ppc/spapr_drc.h |  9 ++++++
>  3 files changed, 100 insertions(+)
> 
> diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
> index 6e54fd4..369ec02 100644
> --- a/hw/ppc/spapr_drc.c
> +++ b/hw/ppc/spapr_drc.c
> @@ -615,6 +615,71 @@ static void spapr_dr_connector_instance_init(Object *obj)
>                          NULL, NULL, NULL, NULL);
>  }
>  
> +static bool spapr_drc_needed(void *opaque)
> +{
> +    sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;
> +    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
> +    bool rc = false;
> +    sPAPRDREntitySense value;
> +
> +    drck->entity_sense(drc, &value);
> +    /* If no dev is plugged in there is no need to migrate the DRC state */
> +    if (value != SPAPR_DR_ENTITY_SENSE_PRESENT) {
> +        return false;
> +    }
> +    /*
> +     * If there is dev plugged in, we need to migrate the DRC state when
> +     * it is different from cold-plugged state
> +     */
> +    switch(drc->type) {
> +    /* for PCI type */
> +    case SPAPR_DR_CONNECTOR_TYPE_PCI:
> +        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) &&
> +               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) &&
> +               drc->configured && drc->signalled && !drc->awaiting_release);
> +        break;
> +    /* for LMB type */
> +    case SPAPR_DR_CONNECTOR_TYPE_LMB:
> +        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) &&
> +               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) &&
> +               drc->configured && drc->signalled && !drc->awaiting_release);
> +        break;

What about CPU type?z

> +    default:
> +        ;
> +    }
> +
> +    return rc;
> +}
> +
> +/* detach_cb needs be set since it is not migrated */
> +static void postmigrate_set_detach_cb(sPAPRDRConnector *drc,
> +                                      spapr_drc_detach_cb *detach_cb)
> +{
> +    drc->detach_cb = detach_cb;
> +}
> +
> +/* return the unique drc index as instance_id for qom interfaces*/
> +static int get_instance_id(DeviceState *dev)
> +{
> +    return (int)get_index(SPAPR_DR_CONNECTOR(OBJECT(dev)));
> +}
> +
> +static const VMStateDescription vmstate_spapr_drc = {
> +    .name = "spapr_drc",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .needed = spapr_drc_needed,
> +    .fields  = (VMStateField []) {
> +        VMSTATE_UINT32(isolation_state, sPAPRDRConnector),
> +        VMSTATE_UINT32(allocation_state, sPAPRDRConnector),
> +        VMSTATE_UINT32(indicator_state, sPAPRDRConnector),
> +        VMSTATE_BOOL(configured, sPAPRDRConnector),
> +        VMSTATE_BOOL(awaiting_release, sPAPRDRConnector),
> +        VMSTATE_BOOL(signalled, sPAPRDRConnector),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
>  static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
>  {
>      DeviceClass *dk = DEVICE_CLASS(k);
> @@ -623,6 +688,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
>      dk->reset = reset;
>      dk->realize = realize;
>      dk->unrealize = unrealize;
> +    dk->vmsd = &vmstate_spapr_drc;
> +    dk->dev_get_instance_id = get_instance_id;
>      drck->set_isolation_state = set_isolation_state;
>      drck->set_indicator_state = set_indicator_state;
>      drck->set_allocation_state = set_allocation_state;
> @@ -636,6 +703,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
>      drck->detach = detach;
>      drck->release_pending = release_pending;
>      drck->set_signalled = set_signalled;
> +    drck->postmigrate_set_detach_cb = postmigrate_set_detach_cb;
> +
>      /*
>       * Reason: it crashes FIXME find and document the real reason
>       */
> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> index 4f00865..080471c 100644
> --- a/hw/ppc/spapr_pci.c
> +++ b/hw/ppc/spapr_pci.c
> @@ -1594,11 +1594,33 @@ static void spapr_pci_pre_save(void *opaque)
>      }
>  }
>  
> +/*
> + * detach_cb in the DRC state is a function pointer that cannot be
> + * migrated. We set it right after migration so that a migrated
> + * hot-unplug event could finish its work.
> + */
> +static void spapr_pci_set_detach_cb(PCIBus *bus, PCIDevice *pdev,
> +                                 void *opaque)
> +{
> +    sPAPRPHBState *sphb = opaque;
> +    sPAPRDRConnector *drc = spapr_phb_get_pci_drc(sphb, pdev);
> +    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
> +    drck->postmigrate_set_detach_cb(drc, spapr_phb_remove_pci_device_cb);

Why is spapr_phb_remove_pci_device_cb the right callback rather than
something else?  This doesn't seem sensible.

More to the point, you're not restoring detach_cb_opaque, which means
the detach_cb callback won't work properly anyway.

> +}
> +
>  static int spapr_pci_post_load(void *opaque, int version_id)
>  {
>      sPAPRPHBState *sphb = opaque;
>      gpointer key, value;
>      int i;
> +    PCIBus *bus = PCI_HOST_BRIDGE(sphb)->bus;
> +    unsigned int bus_no = 0;
> +
> +    /* Set detach_cb for the drc unconditionally after migration */
> +    if (bus) {
> +        pci_for_each_device(bus, pci_bus_num(bus), spapr_pci_set_detach_cb,
> +                            &bus_no);
> +    }
>  
>      for (i = 0; i < sphb->msi_devs_num; ++i) {
>          key = g_memdup(&sphb->msi_devs[i].key,
> diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h
> index fa531d5..17589c8 100644
> --- a/include/hw/ppc/spapr_drc.h
> +++ b/include/hw/ppc/spapr_drc.h
> @@ -192,6 +192,15 @@ typedef struct sPAPRDRConnectorClass {
>                     void *detach_cb_opaque, Error **errp);
>      bool (*release_pending)(sPAPRDRConnector *drc);
>      void (*set_signalled)(sPAPRDRConnector *drc);
> +
> +    /*
> +     * QEMU interface for setting detach_cb after migration.
> +     * detach_cb in the DRC state is a function pointer that cannot be
> +     * migrated. We set it right after migration so that a migrated
> +     * hot-unplug event could finish its work.
> +     */
> +    void (*postmigrate_set_detach_cb)(sPAPRDRConnector *drc,
> +                                      spapr_drc_detach_cb *detach_cb);
>  } sPAPRDRConnectorClass;
>  
>  sPAPRDRConnector *spapr_dr_connector_new(Object *owner,

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [Qemu-devel] [QEMU PATCH v5 2/6] migration: spapr_drc: defined VMStateDescription struct
  2016-10-05 11:38   ` Dr. David Alan Gilbert
@ 2016-10-07  3:17     ` David Gibson
  0 siblings, 0 replies; 66+ messages in thread
From: David Gibson @ 2016-10-07  3:17 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Jianjun Duan, qemu-devel, qemu-ppc, dmitry, peter.maydell,
	kraxel, mst, pbonzini, veroniabahaa, quintela, amit.shah, mreitz,
	kwolf, rth, aurelien, leon.alrae, blauwirbel, mark.cave-ayland,
	mdroth

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

On Wed, Oct 05, 2016 at 12:38:53PM +0100, Dr. David Alan Gilbert wrote:
> * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> > To manage hotplug/unplug of dynamic resources such as PCI cards,
> > memory, and CPU on sPAPR guests, a firmware abstraction known as
> > a Dynamic Resource Connector (DRC) is used to assign a particular
> > dynamic resource to the guest, and provide an interface for the
> > guest to manage configuration/removal of the resource associated
> > with it.
> > 
> > To migrate the hotplugged resources in migration, the
> > associated DRC state need be migrated. To migrate the DRC state,
> > we defined the VMStateDescription struct for spapr_drc to enable
> > the transmission of spapr_drc state in migration.
> > 
> > Not all the elements in the DRC state are migrated. Only those
> > ones modifiable or needed by guest actions or device add/remove
> > operation are migrated. From the perspective of device
> > hotplugging, if we hotplug a device on the source, we need to
> > "coldplug" it on the target. The states across two hosts for the
> > same device are not the same. Ideally we want the states be same
> > after migration so that the device would function as hotplugged
> > on the target. For example we can unplug it. The minimum DRC
> > state we need to transfer should cover all the pieces changed by
> > hotplugging. Out of the elements of the DRC state, isolation_state,
> > allocation_sate, and configured are involved in the DR state
> > transition diagram from PAPR+ 2.7, 13.4. configured and signalled
> > are needed in attaching and detaching devices. indicator_state
> > provides users with hardware state information. These 6 elements
> > are migrated.
> > 
> > detach_cb in the DRC state is a function pointer that cannot be
> > migrated. We set it right after DRC state is migrated so that
> > a migrated hot-unplug event could finish its work.
> 
> Be careful with that; it'll get tricky if you have a bunch of different
> possible callbacks.   If you want to explicitly migrate it then you'd
> have to have an enum of different functions that could be called rather
> than storing the pointer explicitly.

Quite.  Looking at the code, I'm quite baffled as to how detach_cb and
detach_cb_opaque get populated in the first place anyway.  All the
assignments I can see seem to be assigning the same variable to itself
(loaded in the caller, passed to another function, stored back to the
same place in the callee).

> 
> > The instance_id is used to identify objects in migration. We set
> > instance_id of DRC using the unique index so that it is the same
> > across migration.
> > 
> > Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
> 
> I think this is OK from a migration point of view; I'll leave
> it to someone else to check the Power side of things.
> 
> > ---
> >  hw/ppc/spapr_drc.c         | 69 ++++++++++++++++++++++++++++++++++++++++++++++
> >  hw/ppc/spapr_pci.c         | 22 +++++++++++++++
> >  include/hw/ppc/spapr_drc.h |  9 ++++++
> >  3 files changed, 100 insertions(+)
> > 
> > diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
> > index 6e54fd4..369ec02 100644
> > --- a/hw/ppc/spapr_drc.c
> > +++ b/hw/ppc/spapr_drc.c
> > @@ -615,6 +615,71 @@ static void spapr_dr_connector_instance_init(Object *obj)
> >                          NULL, NULL, NULL, NULL);
> >  }
> >  
> > +static bool spapr_drc_needed(void *opaque)
> > +{
> > +    sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;
> > +    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
> > +    bool rc = false;
> > +    sPAPRDREntitySense value;
> > +
> > +    drck->entity_sense(drc, &value);
> > +    /* If no dev is plugged in there is no need to migrate the DRC state */
> > +    if (value != SPAPR_DR_ENTITY_SENSE_PRESENT) {
> > +        return false;
> > +    }
> > +    /*
> > +     * If there is dev plugged in, we need to migrate the DRC state when
> > +     * it is different from cold-plugged state
> > +     */
> > +    switch(drc->type) {
> > +    /* for PCI type */
> > +    case SPAPR_DR_CONNECTOR_TYPE_PCI:
> > +        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) &&
> > +               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) &&
> > +               drc->configured && drc->signalled && !drc->awaiting_release);
> > +        break;
> > +    /* for LMB type */
> > +    case SPAPR_DR_CONNECTOR_TYPE_LMB:
> > +        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) &&
> > +               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) &&
> > +               drc->configured && drc->signalled && !drc->awaiting_release);
> > +        break;
> > +    default:
> > +        ;
> > +    }
> > +
> > +    return rc;
> > +}
> > +
> > +/* detach_cb needs be set since it is not migrated */
> > +static void postmigrate_set_detach_cb(sPAPRDRConnector *drc,
> > +                                      spapr_drc_detach_cb *detach_cb)
> > +{
> > +    drc->detach_cb = detach_cb;
> > +}
> > +
> > +/* return the unique drc index as instance_id for qom interfaces*/
> > +static int get_instance_id(DeviceState *dev)
> > +{
> > +    return (int)get_index(SPAPR_DR_CONNECTOR(OBJECT(dev)));
> > +}
> > +
> > +static const VMStateDescription vmstate_spapr_drc = {
> > +    .name = "spapr_drc",
> > +    .version_id = 1,
> > +    .minimum_version_id = 1,
> > +    .needed = spapr_drc_needed,
> > +    .fields  = (VMStateField []) {
> > +        VMSTATE_UINT32(isolation_state, sPAPRDRConnector),
> > +        VMSTATE_UINT32(allocation_state, sPAPRDRConnector),
> > +        VMSTATE_UINT32(indicator_state, sPAPRDRConnector),
> > +        VMSTATE_BOOL(configured, sPAPRDRConnector),
> > +        VMSTATE_BOOL(awaiting_release, sPAPRDRConnector),
> > +        VMSTATE_BOOL(signalled, sPAPRDRConnector),
> > +        VMSTATE_END_OF_LIST()
> > +    }
> > +};
> > +
> >  static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
> >  {
> >      DeviceClass *dk = DEVICE_CLASS(k);
> > @@ -623,6 +688,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
> >      dk->reset = reset;
> >      dk->realize = realize;
> >      dk->unrealize = unrealize;
> > +    dk->vmsd = &vmstate_spapr_drc;
> > +    dk->dev_get_instance_id = get_instance_id;
> >      drck->set_isolation_state = set_isolation_state;
> >      drck->set_indicator_state = set_indicator_state;
> >      drck->set_allocation_state = set_allocation_state;
> > @@ -636,6 +703,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
> >      drck->detach = detach;
> >      drck->release_pending = release_pending;
> >      drck->set_signalled = set_signalled;
> > +    drck->postmigrate_set_detach_cb = postmigrate_set_detach_cb;
> > +
> >      /*
> >       * Reason: it crashes FIXME find and document the real reason
> >       */
> > diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> > index 4f00865..080471c 100644
> > --- a/hw/ppc/spapr_pci.c
> > +++ b/hw/ppc/spapr_pci.c
> > @@ -1594,11 +1594,33 @@ static void spapr_pci_pre_save(void *opaque)
> >      }
> >  }
> >  
> > +/*
> > + * detach_cb in the DRC state is a function pointer that cannot be
> > + * migrated. We set it right after migration so that a migrated
> > + * hot-unplug event could finish its work.
> > + */
> > +static void spapr_pci_set_detach_cb(PCIBus *bus, PCIDevice *pdev,
> > +                                 void *opaque)
> > +{
> > +    sPAPRPHBState *sphb = opaque;
> > +    sPAPRDRConnector *drc = spapr_phb_get_pci_drc(sphb, pdev);
> > +    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
> > +    drck->postmigrate_set_detach_cb(drc, spapr_phb_remove_pci_device_cb);
> > +}
> > +
> >  static int spapr_pci_post_load(void *opaque, int version_id)
> >  {
> >      sPAPRPHBState *sphb = opaque;
> >      gpointer key, value;
> >      int i;
> > +    PCIBus *bus = PCI_HOST_BRIDGE(sphb)->bus;
> > +    unsigned int bus_no = 0;
> > +
> > +    /* Set detach_cb for the drc unconditionally after migration */
> > +    if (bus) {
> > +        pci_for_each_device(bus, pci_bus_num(bus), spapr_pci_set_detach_cb,
> > +                            &bus_no);
> > +    }
> >  
> >      for (i = 0; i < sphb->msi_devs_num; ++i) {
> >          key = g_memdup(&sphb->msi_devs[i].key,
> > diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h
> > index fa531d5..17589c8 100644
> > --- a/include/hw/ppc/spapr_drc.h
> > +++ b/include/hw/ppc/spapr_drc.h
> > @@ -192,6 +192,15 @@ typedef struct sPAPRDRConnectorClass {
> >                     void *detach_cb_opaque, Error **errp);
> >      bool (*release_pending)(sPAPRDRConnector *drc);
> >      void (*set_signalled)(sPAPRDRConnector *drc);
> > +
> > +    /*
> > +     * QEMU interface for setting detach_cb after migration.
> > +     * detach_cb in the DRC state is a function pointer that cannot be
> > +     * migrated. We set it right after migration so that a migrated
> > +     * hot-unplug event could finish its work.
> > +     */
> > +    void (*postmigrate_set_detach_cb)(sPAPRDRConnector *drc,
> > +                                      spapr_drc_detach_cb *detach_cb);
> >  } sPAPRDRConnectorClass;
> >  
> >  sPAPRDRConnector *spapr_dr_connector_new(Object *owner,

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-06 19:01       ` Dr. David Alan Gilbert
  2016-10-06 19:49         ` Jianjun Duan
@ 2016-10-07  3:25         ` David Gibson
  2016-10-07 14:31         ` Paolo Bonzini
  2 siblings, 0 replies; 66+ messages in thread
From: David Gibson @ 2016-10-07  3:25 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Jianjun Duan, qemu-devel, qemu-ppc, dmitry, peter.maydell,
	kraxel, mst, pbonzini, veroniabahaa, quintela, amit.shah, mreitz,
	kwolf, rth, aurelien, leon.alrae, blauwirbel, mark.cave-ayland,
	mdroth

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

On Thu, Oct 06, 2016 at 08:01:56PM +0100, Dr. David Alan Gilbert wrote:
> * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> > 
> > 
> > On 10/05/2016 09:56 AM, Dr. David Alan Gilbert wrote:
> > > * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> > >> Currently we cannot directly transfer a QTAILQ instance because of the
> > >> limitation in the migration code. Here we introduce an approach to
> > >> transfer such structures. In our approach such a structure is tagged
> > >> with VMS_LINKED. We then modified vmstate_save_state and vmstate_load_state
> > >> so that when VMS_LINKED is encountered, put and get from VMStateInfo are
> > >> called respectively. We created VMStateInfo vmstate_info_qtailq for QTAILQ.
> > >> Similar VMStateInfo can be created for other data structures such as list.
> > >> This approach will be used to transfer pending_events and ccs_list in spapr
> > >> state.
> > >>
> > >> We also create some macros in qemu/queue.h to access a QTAILQ using pointer
> > >> arithmetic. This ensures that we do not depend on the implementation
> > >> details about QTAILQ in the migration code.
> > > 
> > > I think we're going to need a way to have a more flexible
> > > loops; and thus my choice here wouldn't be to use the .get/.put together
> > > with the VMSD; but I think we'll end up needing a new
> > > data structure, maybe a VMStateLoop *loop in VMStateField.
> > > 
> > > So would it be easier if you added that new member, then you wouldn't have to
> > > modify every get() and put() function that already exists in the previous patch.
> > > 
> > > Specifically, your format of QTAILQ is perfectly reasonable - a
> > > byte before each entry which is 1 to indicate there's an entry or 0
> > > to indicate termination, but there are lots of other variants, e.g.
> > > 
> > >    a) put_scsi_requests uses that byte to hold a flag, so it's 0,1,2
> > >       0 still means terminate but 1 or 2 set a flag in the structure.
> > 
> > I quickly take a look of put_scsi_requests. It is transferring a QTAILQ of
> > SCSIRequest. However it goes into the structure inside to dump the
> > elements out.
> > If using my approach, I would have a VMSD for SCSIRequest. The
> > additional byte used to indicate the end of the queue would lie outside
> > the SCSCIRequest data block, so there would be no confusion.
> 
> Hmm OK; I don't think it's that easy but we'll see.
> 
> However, can I make one much simpler request; please split this patch
> so that the VMSTATE_LINKED and vmstate_save_state/vmstate_load_state/vmfield_get_type_name
> are in one patch, while the QTAILQ patches are in a separate patch.
> (I'd be OK if you moved the VMSTATE_LINKED into the previous patch).
> 
> I've just been thinking about a different use for the same mechanism;
> I want to do a:
>   VMSTATE_WITH_TMP(t1*, type1, type2, vmsd)
> 
> which also sets the LINKED, where the .get/.put allocate a temporary
> structure (of type/size type2), set up *tmp = t1 and then do the vmstate_load/save
> using the vmsd on the temporary; something like (untested):
> 
> static int get_tmp(QEMUFile *f, void *pv, size_t unused_size, VMStateField *field)
> {
>     const VMStateDescription *vmsd = field->vmsd;
>     size_t size = field->size;
>     int version_id = field->version_id;
>     void *tmp = gmalloc(size);
>     int ret;
>     
>     *(void **)tmp = pv;
>     ret = vmstate_load_state(f, vmsd, tmp, version_id);
>     gfree(tmp);
>     return ret;
> }
> 
> This can be in a generic macro; and we would impose that type2 must be a struct
> with the first element is 'type1* parent' (compile checked).
> This would work nicely for where we have to do some maths to generate some
> temporary results prior to migration; the .pre_save of the vmsd can read the data
> from pv->parent and write it to the other fields but not have to use
> qemu_get_*/qemu_put_* at all.
> 
> Dave

Oh, I like this idea.  I know there are a number of places where
should-be-obsolete fields are still present in structures purely to
catch incoming migration info which is then converted to the modern
representation in post_load.  This would allow cleaning a bunch of
those up.

It would also mean we don't necessarily need explicit handling of
queues/lists.  I objected to early versions of this series which
dumped the qtailq into an array and used the existing array vmstate
types, because it meant not just an only-for-migration field in the
structure, but a substantial slab of only-for-migration data.

If we added the concept of temporary "catching" structures to the
vmsd, that objection would go away.  I'd be happy enough to
temporarily dump the queue into an array, transfer that over the
stream into another temporary array, then load it into the destination
queue.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [Qemu-devel] [QEMU PATCH v5 5/6] migration: spapr: migrate ccs_list in spapr state
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 5/6] migration: spapr: migrate ccs_list in spapr state Jianjun Duan
@ 2016-10-07  3:36   ` David Gibson
  2016-10-07 14:52     ` Michael Roth
  0 siblings, 1 reply; 66+ messages in thread
From: David Gibson @ 2016-10-07  3:36 UTC (permalink / raw)
  To: Jianjun Duan
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth,
	dgilbert

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

On Mon, Oct 03, 2016 at 11:24:56AM -0700, Jianjun Duan wrote:
> ccs_list in spapr state maintains the device tree related
> information on the rtas side for hotplugged devices. In racing
> situations between hotplug events and migration operation, a rtas
> hotplug event could be migrated from the source guest to target
> guest, or the source guest could have not yet finished fetching
> the device tree when migration is started, the target will try
> to finish fetching the device tree. By migrating ccs_list, the
> target can fetch the device tree properly.
> 
> ccs_list is put in a subsection in the spapr state VMSD to make
> sure migration across different versions is not broken.
> 
> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>

I'm still not entirely convinced we need to migrate the ccs_list.
What would happen if we did this:

   * Keep a flag which indicates whether the guest is in the middle of
     the configure_connector process.
       - I'm not sure if that would need to be a new bit of state, or
         if we could deduce it from the value of the isolation and
	 allocation states
       - If it's new state, we'd need to migrate it, obviously not if
         we can derive it from other state flags

   * On the destination during post_load, if there was an in-progress
     configure_connector on the source, we set another "stale
     configure" flag

   * When a configure_connector call is attempted on the destination
     with the stale configure flag set, return an error

The question is, if we choose the right error, can we get the guest to
either restart the configure from scratch, or fail gracefully, so the
operator can restart the hotplug

> ---
>  hw/ppc/spapr.c | 34 ++++++++++++++++++++++++++++++++++
>  1 file changed, 34 insertions(+)
> 
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 63b6a0d..1847d35 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -1255,6 +1255,36 @@ static bool version_before_3(void *opaque, int version_id)
>      return version_id < 3;
>  }
>  
> +static bool spapr_ccs_list_needed(void *opaque)
> +{
> +    sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
> +    return !QTAILQ_EMPTY(&spapr->ccs_list);
> +}
> +
> +static const VMStateDescription vmstate_spapr_ccs = {
> +    .name = "spaprconfigureconnectorstate",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT32(drc_index, sPAPRConfigureConnectorState),
> +        VMSTATE_INT32(fdt_offset, sPAPRConfigureConnectorState),
> +        VMSTATE_INT32(fdt_depth, sPAPRConfigureConnectorState),
> +        VMSTATE_END_OF_LIST()
> +    },
> +};
> +
> +static const VMStateDescription vmstate_spapr_ccs_list = {
> +    .name = "spaprccslist",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .needed = spapr_ccs_list_needed,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_QTAILQ_V(ccs_list, sPAPRMachineState, 1,
> +                         vmstate_spapr_ccs, sPAPRConfigureConnectorState, next),
> +        VMSTATE_END_OF_LIST()
> +    },
> +};
> +
>  static const VMStateDescription vmstate_spapr = {
>      .name = "spapr",
>      .version_id = 3,
> @@ -1270,6 +1300,10 @@ static const VMStateDescription vmstate_spapr = {
>          VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2),
>          VMSTATE_END_OF_LIST()
>      },
> +    .subsections = (const VMStateDescription*[]) {
> +        &vmstate_spapr_ccs_list,
> +        NULL
> +    }
>  };
>  
>  static int htab_save_setup(QEMUFile *f, void *opaque)

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [Qemu-devel] [QEMU PATCH v5 1/6] migration: alternative way to set instance_id in SaveStateEntry
  2016-10-07  2:54       ` David Gibson
@ 2016-10-07  8:07         ` Dr. David Alan Gilbert
  2016-10-10  5:31           ` David Gibson
  2016-11-15 23:45         ` Michael Roth
  1 sibling, 1 reply; 66+ messages in thread
From: Dr. David Alan Gilbert @ 2016-10-07  8:07 UTC (permalink / raw)
  To: David Gibson
  Cc: Jianjun Duan, qemu-devel, qemu-ppc, dmitry, peter.maydell,
	kraxel, mst, pbonzini, veroniabahaa, quintela, amit.shah, mreitz,
	kwolf, rth, aurelien, leon.alrae, blauwirbel, mark.cave-ayland,
	mdroth

* David Gibson (david@gibson.dropbear.id.au) wrote:
> On Wed, Oct 05, 2016 at 09:44:57AM -0700, Jianjun Duan wrote:
> > Please see comments below:
> > 
> > On 10/05/2016 03:12 AM, Dr. David Alan Gilbert wrote:
> > > * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> > >> In QOM(QEMU Object Model) migrated objects are identified with instance_id
> > >> which is calculated automatically using their path in the QOM composition
> > >> tree. For some objects, this path could change from source to target in
> > >> migration. To migrate such objects, we need to make sure the instance_id does
> > >> not change from source to target. We add a hook in DeviceClass to do customized
> > >> instance_id calculation in such cases.
> > > 
> > > Can you explain a bit about why the path changes from source to destination;
> > > the path here should be a feature of the guest state not the host, and so I
> > > don't understand why it changes.
> > Please see the discussion with David in the previous versions:
> > http://lists.nongnu.org/archive/html/qemu-ppc/2016-06/msg00062.html
> 
> Um.. your description above really isn't an accurate summary of that
> discussion.
> 
> The point is not that the qom path will vary from source to
> destination for some arbitrary reason, but rather that we anticipate
> future changes in the QOM structure.  Specifically we're considering
> eliminating the DRC objects, and folding their (limited) state into an
> array in the parent object (either the machine or a PCI host bridge).
> 
> That would change the qom paths, and hence the auto-generated instance
> ids, which would break migration between qemu versions before and
> after the restructure.
> 
> I'm not sure that changing the instance ids is enough though, anyway,
> since we're talking about eliminating the object entirely, the
> class/type information in the migration stream also wouldn't match.
> 
> Dave, if you have ideas on how to deal with that, I'd love to hear
> them

Eliminating the object entirely would be tricky to deal with;
allowing the structure to change would work if instead of a custom instance_id
you had a custom idstr.

However, the question then becomes why is the structure changing so much;
ideally things in the migration stream should represent some tangible object
that corresponds to something real, but (again ideally) the contents
of the stream should reflect the state of those objects not the current
implementation - so if you want to change the implementation the stream
doesn't change.  Is it your implementation, or the understanding of what
the objects actually represent that's in flux?

Dave

> 
> > 
> > >> As a result, in these cases compat will not be set in the concerned
> > >> SaveStateEntry. This will prevent the inconsistent idstr to be sent over in
> > >> migration. We could have set alias_id in a similar way. But that will be
> > >> overloading the purpose of alias_id.
> > >>
> > >> The first application will be setting instance_id for DRC using its unique
> > >> index. Doing this makes the instance_id of DRC to be consistent across migration
> > >> and supports flexible management of DRC objects in migration.
> > > 
> > > Is there a reason to use a custom instance_id rather than a custom idstr
> > 
> > It can be done either way. But it is easier to deal with a integer than
> > a string.
> 
> A bit, but I don't think that's a good enough reason to introduce a
> second mechanism for overriding instance id allocations.
> 
> -- 
> David Gibson			| I'll have my music baroque, and my code
> david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
> 				| _way_ _around_!
> http://www.ozlabs.org/~dgibson


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

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

* Re: [Qemu-devel] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 3/6] migration: extend VMStateInfo Jianjun Duan
@ 2016-10-07 12:08   ` Dr. David Alan Gilbert
  2016-10-07 16:35     ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
  2016-10-12 11:59   ` [Qemu-devel] " Halil Pasic
  1 sibling, 1 reply; 66+ messages in thread
From: Dr. David Alan Gilbert @ 2016-10-07 12:08 UTC (permalink / raw)
  To: Jianjun Duan
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth

* Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> Current migration code cannot handle some data structures such as
> QTAILQ in qemu/queue.h. Here we extend the signatures of put/get
> in VMStateInfo so that customized handling is supported.
> 
> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
> ---
>  hw/net/vmxnet3.c            | 18 ++++++---
>  hw/nvram/eeprom93xx.c       |  6 ++-
>  hw/nvram/fw_cfg.c           |  6 ++-
>  hw/pci/msix.c               |  6 ++-
>  hw/pci/pci.c                | 12 ++++--
>  hw/pci/shpc.c               |  5 ++-
>  hw/scsi/scsi-bus.c          |  6 ++-
>  hw/timer/twl92230.c         |  6 ++-
>  hw/usb/redirect.c           | 18 ++++++---
>  hw/virtio/virtio-pci.c      |  6 ++-
>  hw/virtio/virtio.c          |  6 ++-
>  include/migration/vmstate.h | 10 +++--
>  migration/savevm.c          |  5 ++-
>  migration/vmstate.c         | 95 ++++++++++++++++++++++++++++-----------------
>  target-alpha/machine.c      |  5 ++-
>  target-arm/machine.c        | 12 ++++--
>  target-i386/machine.c       | 21 ++++++----
>  target-mips/machine.c       | 10 +++--
>  target-ppc/machine.c        | 10 +++--
>  target-sparc/machine.c      |  5 ++-
>  20 files changed, 171 insertions(+), 97 deletions(-)
> 

<snip>

> diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
> index 444672a..2ca4b46 100644
> --- a/hw/usb/redirect.c
> +++ b/hw/usb/redirect.c
> @@ -2154,7 +2154,8 @@ static int usbredir_post_load(void *priv, int version_id)
>  }
>  
>  /* For usbredirparser migration */
> -static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
> +static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused,
> +                                void *opaque, QJSON *vmdesc)
>  {
>      USBRedirDevice *dev = priv;
>      uint8_t *data;
> @@ -2174,7 +2175,8 @@ static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
>      free(data);
>  }
>  
> -static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused)
> +static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused,
> +                               void *opaque)

Neither of these built for me; I had to change those to VMStateField rather than void *;

also is this series tested ontop of Halil's patches - because without them
I'm finding I also had to fix up most of the other virtio devices.

Dave


>      USBRedirDevice *dev = priv;
>      uint8_t *data;
> @@ -2217,7 +2219,8 @@ static const VMStateInfo usbredir_parser_vmstate_info = {
>  
>  
>  /* For buffered packets (iso/irq) queue migration */
> -static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
> +static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused,
> +                               VMStateField *field, QJSON *vmdesc)
>  {
>      struct endp_data *endp = priv;
>      USBRedirDevice *dev = endp->dev;
> @@ -2237,7 +2240,8 @@ static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
>      assert(i == endp->bufpq_size);
>  }
>  
> -static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused)
> +static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused,
> +                              VMStateField *field)
>  {
>      struct endp_data *endp = priv;
>      USBRedirDevice *dev = endp->dev;
> @@ -2340,7 +2344,8 @@ static const VMStateDescription usbredir_ep_vmstate = {
>  
>  
>  /* For PacketIdQueue migration */
> -static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused)
> +static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused,
> +                                     VMStateField *field, QJSON *vmdesc)
>  {
>      struct PacketIdQueue *q = priv;
>      USBRedirDevice *dev = q->dev;
> @@ -2356,7 +2361,8 @@ static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused)
>      assert(remain == 0);
>  }
>  
> -static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused)
> +static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused,
> +                                    VMStateField *field)
>  {
>      struct PacketIdQueue *q = priv;
>      USBRedirDevice *dev = q->dev;
> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> index 2d60a00..38a7abd 100644
> --- a/hw/virtio/virtio-pci.c
> +++ b/hw/virtio/virtio-pci.c
> @@ -108,7 +108,8 @@ static bool virtio_pci_has_extra_state(DeviceState *d)
>      return proxy->flags & VIRTIO_PCI_FLAG_MIGRATE_EXTRA;
>  }
>  
> -static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size)
> +static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size,
> +                                       VMStateField *field)
>  {
>      VirtIOPCIProxy *proxy = pv;
>      int i;
> @@ -137,7 +138,8 @@ static void virtio_pci_save_modern_queue_state(VirtIOPCIQueue *vq,
>      qemu_put_be32(f, vq->used[1]);
>  }
>  
> -static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size)
> +static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size,
> +                                        VMStateField *field, QJSON *vmdesc)
>  {
>      VirtIOPCIProxy *proxy = pv;
>      int i;
> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> index 18ce333..ade2683 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -1467,7 +1467,8 @@ static const VMStateDescription vmstate_virtio_ringsize = {
>      }
>  };
>  
> -static int get_extra_state(QEMUFile *f, void *pv, size_t size)
> +static int get_extra_state(QEMUFile *f, void *pv, size_t size,
> +                           VMStateField *field)
>  {
>      VirtIODevice *vdev = pv;
>      BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
> @@ -1480,7 +1481,8 @@ static int get_extra_state(QEMUFile *f, void *pv, size_t size)
>      }
>  }
>  
> -static void put_extra_state(QEMUFile *f, void *pv, size_t size)
> +static void put_extra_state(QEMUFile *f, void *pv, size_t size,
> +                            VMStateField *field, QJSON *vmdesc)
>  {
>      VirtIODevice *vdev = pv;
>      BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
> index 1638ee5..459dd4a 100644
> --- a/include/migration/vmstate.h
> +++ b/include/migration/vmstate.h
> @@ -81,11 +81,13 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque);
>  
>  typedef struct VMStateInfo VMStateInfo;
>  typedef struct VMStateDescription VMStateDescription;
> +typedef struct VMStateField VMStateField;
>  
>  struct VMStateInfo {
>      const char *name;
> -    int (*get)(QEMUFile *f, void *pv, size_t size);
> -    void (*put)(QEMUFile *f, void *pv, size_t size);
> +    int (*get)(QEMUFile *f, void *pv, size_t size, VMStateField *field);
> +    void (*put)(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                QJSON *vmdesc);
>  };
>  
>  enum VMStateFlags {
> @@ -186,7 +188,7 @@ enum VMStateFlags {
>      VMS_MULTIPLY_ELEMENTS = 0x4000,
>  };
>  
> -typedef struct {
> +struct VMStateField {
>      const char *name;
>      size_t offset;
>      size_t size;
> @@ -199,7 +201,7 @@ typedef struct {
>      const VMStateDescription *vmsd;
>      int version_id;
>      bool (*field_exists)(void *opaque, int version_id);
> -} VMStateField;
> +};
>  
>  struct VMStateDescription {
>      const char *name;
> diff --git a/migration/savevm.c b/migration/savevm.c
> index ef5c3d1..13b53ad 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -220,14 +220,15 @@ void timer_get(QEMUFile *f, QEMUTimer *ts)
>   * Not in vmstate.c to not add qemu-timer.c as dependency to vmstate.c
>   */
>  
> -static int get_timer(QEMUFile *f, void *pv, size_t size)
> +static int get_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      QEMUTimer *v = pv;
>      timer_get(f, v);
>      return 0;
>  }
>  
> -static void put_timer(QEMUFile *f, void *pv, size_t size)
> +static void put_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                QJSON *vmdesc)
>  {
>      QEMUTimer *v = pv;
>      timer_put(f, v);
> diff --git a/migration/vmstate.c b/migration/vmstate.c
> index fc29acf..66802cb 100644
> --- a/migration/vmstate.c
> +++ b/migration/vmstate.c
> @@ -122,7 +122,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
>                      ret = vmstate_load_state(f, field->vmsd, addr,
>                                               field->vmsd->version_id);
>                  } else {
> -                    ret = field->info->get(f, addr, size);
> +                    ret = field->info->get(f, addr, size, NULL);
>  
>                  }
>                  if (ret >= 0) {
> @@ -328,7 +328,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
>                  if (field->flags & VMS_STRUCT) {
>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
>                  } else {
> -                    field->info->put(f, addr, size);
> +                    field->info->put(f, addr, size, NULL, NULL);
>                  }
>  
>                  written_bytes = qemu_ftell_fast(f) - old_offset;
> @@ -461,14 +461,15 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
>  
>  /* bool */
>  
> -static int get_bool(QEMUFile *f, void *pv, size_t size)
> +static int get_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      bool *v = pv;
>      *v = qemu_get_byte(f);
>      return 0;
>  }
>  
> -static void put_bool(QEMUFile *f, void *pv, size_t size)
> +static void put_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                     QJSON *vmdesc)
>  {
>      bool *v = pv;
>      qemu_put_byte(f, *v);
> @@ -482,14 +483,15 @@ const VMStateInfo vmstate_info_bool = {
>  
>  /* 8 bit int */
>  
> -static int get_int8(QEMUFile *f, void *pv, size_t size)
> +static int get_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      int8_t *v = pv;
>      qemu_get_s8s(f, v);
>      return 0;
>  }
>  
> -static void put_int8(QEMUFile *f, void *pv, size_t size)
> +static void put_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                     QJSON *vmdesc)
>  {
>      int8_t *v = pv;
>      qemu_put_s8s(f, v);
> @@ -503,14 +505,15 @@ const VMStateInfo vmstate_info_int8 = {
>  
>  /* 16 bit int */
>  
> -static int get_int16(QEMUFile *f, void *pv, size_t size)
> +static int get_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      int16_t *v = pv;
>      qemu_get_sbe16s(f, v);
>      return 0;
>  }
>  
> -static void put_int16(QEMUFile *f, void *pv, size_t size)
> +static void put_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                      QJSON *vmdesc)
>  {
>      int16_t *v = pv;
>      qemu_put_sbe16s(f, v);
> @@ -524,14 +527,15 @@ const VMStateInfo vmstate_info_int16 = {
>  
>  /* 32 bit int */
>  
> -static int get_int32(QEMUFile *f, void *pv, size_t size)
> +static int get_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      int32_t *v = pv;
>      qemu_get_sbe32s(f, v);
>      return 0;
>  }
>  
> -static void put_int32(QEMUFile *f, void *pv, size_t size)
> +static void put_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                      QJSON *vmdesc)
>  {
>      int32_t *v = pv;
>      qemu_put_sbe32s(f, v);
> @@ -546,7 +550,8 @@ const VMStateInfo vmstate_info_int32 = {
>  /* 32 bit int. See that the received value is the same than the one
>     in the field */
>  
> -static int get_int32_equal(QEMUFile *f, void *pv, size_t size)
> +static int get_int32_equal(QEMUFile *f, void *pv, size_t size,
> +                           VMStateField *field)
>  {
>      int32_t *v = pv;
>      int32_t v2;
> @@ -568,7 +573,7 @@ const VMStateInfo vmstate_info_int32_equal = {
>   * and less than or equal to the one in the field.
>   */
>  
> -static int get_int32_le(QEMUFile *f, void *pv, size_t size)
> +static int get_int32_le(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      int32_t *cur = pv;
>      int32_t loaded;
> @@ -589,14 +594,15 @@ const VMStateInfo vmstate_info_int32_le = {
>  
>  /* 64 bit int */
>  
> -static int get_int64(QEMUFile *f, void *pv, size_t size)
> +static int get_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      int64_t *v = pv;
>      qemu_get_sbe64s(f, v);
>      return 0;
>  }
>  
> -static void put_int64(QEMUFile *f, void *pv, size_t size)
> +static void put_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                      QJSON *vmdesc)
>  {
>      int64_t *v = pv;
>      qemu_put_sbe64s(f, v);
> @@ -610,14 +616,15 @@ const VMStateInfo vmstate_info_int64 = {
>  
>  /* 8 bit unsigned int */
>  
> -static int get_uint8(QEMUFile *f, void *pv, size_t size)
> +static int get_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      uint8_t *v = pv;
>      qemu_get_8s(f, v);
>      return 0;
>  }
>  
> -static void put_uint8(QEMUFile *f, void *pv, size_t size)
> +static void put_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                      QJSON *vmdesc)
>  {
>      uint8_t *v = pv;
>      qemu_put_8s(f, v);
> @@ -631,14 +638,15 @@ const VMStateInfo vmstate_info_uint8 = {
>  
>  /* 16 bit unsigned int */
>  
> -static int get_uint16(QEMUFile *f, void *pv, size_t size)
> +static int get_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      uint16_t *v = pv;
>      qemu_get_be16s(f, v);
>      return 0;
>  }
>  
> -static void put_uint16(QEMUFile *f, void *pv, size_t size)
> +static void put_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                       QJSON *vmdesc)
>  {
>      uint16_t *v = pv;
>      qemu_put_be16s(f, v);
> @@ -652,14 +660,15 @@ const VMStateInfo vmstate_info_uint16 = {
>  
>  /* 32 bit unsigned int */
>  
> -static int get_uint32(QEMUFile *f, void *pv, size_t size)
> +static int get_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      uint32_t *v = pv;
>      qemu_get_be32s(f, v);
>      return 0;
>  }
>  
> -static void put_uint32(QEMUFile *f, void *pv, size_t size)
> +static void put_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                       QJSON *vmdesc)
>  {
>      uint32_t *v = pv;
>      qemu_put_be32s(f, v);
> @@ -674,7 +683,8 @@ const VMStateInfo vmstate_info_uint32 = {
>  /* 32 bit uint. See that the received value is the same than the one
>     in the field */
>  
> -static int get_uint32_equal(QEMUFile *f, void *pv, size_t size)
> +static int get_uint32_equal(QEMUFile *f, void *pv, size_t size,
> +                            VMStateField *field)
>  {
>      uint32_t *v = pv;
>      uint32_t v2;
> @@ -694,14 +704,15 @@ const VMStateInfo vmstate_info_uint32_equal = {
>  
>  /* 64 bit unsigned int */
>  
> -static int get_uint64(QEMUFile *f, void *pv, size_t size)
> +static int get_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      uint64_t *v = pv;
>      qemu_get_be64s(f, v);
>      return 0;
>  }
>  
> -static void put_uint64(QEMUFile *f, void *pv, size_t size)
> +static void put_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                       QJSON *vmdesc)
>  {
>      uint64_t *v = pv;
>      qemu_put_be64s(f, v);
> @@ -716,7 +727,8 @@ const VMStateInfo vmstate_info_uint64 = {
>  /* 64 bit unsigned int. See that the received value is the same than the one
>     in the field */
>  
> -static int get_uint64_equal(QEMUFile *f, void *pv, size_t size)
> +static int get_uint64_equal(QEMUFile *f, void *pv, size_t size,
> +                            VMStateField *field)
>  {
>      uint64_t *v = pv;
>      uint64_t v2;
> @@ -737,7 +749,8 @@ const VMStateInfo vmstate_info_uint64_equal = {
>  /* 8 bit int. See that the received value is the same than the one
>     in the field */
>  
> -static int get_uint8_equal(QEMUFile *f, void *pv, size_t size)
> +static int get_uint8_equal(QEMUFile *f, void *pv, size_t size,
> +                           VMStateField *field)
>  {
>      uint8_t *v = pv;
>      uint8_t v2;
> @@ -758,7 +771,8 @@ const VMStateInfo vmstate_info_uint8_equal = {
>  /* 16 bit unsigned int int. See that the received value is the same than the one
>     in the field */
>  
> -static int get_uint16_equal(QEMUFile *f, void *pv, size_t size)
> +static int get_uint16_equal(QEMUFile *f, void *pv, size_t size,
> +                            VMStateField *field)
>  {
>      uint16_t *v = pv;
>      uint16_t v2;
> @@ -778,7 +792,8 @@ const VMStateInfo vmstate_info_uint16_equal = {
>  
>  /* floating point */
>  
> -static int get_float64(QEMUFile *f, void *pv, size_t size)
> +static int get_float64(QEMUFile *f, void *pv, size_t size,
> +                       VMStateField *field)
>  {
>      float64 *v = pv;
>  
> @@ -786,7 +801,8 @@ static int get_float64(QEMUFile *f, void *pv, size_t size)
>      return 0;
>  }
>  
> -static void put_float64(QEMUFile *f, void *pv, size_t size)
> +static void put_float64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                        QJSON *vmdesc)
>  {
>      uint64_t *v = pv;
>  
> @@ -801,7 +817,8 @@ const VMStateInfo vmstate_info_float64 = {
>  
>  /* CPU_DoubleU type */
>  
> -static int get_cpudouble(QEMUFile *f, void *pv, size_t size)
> +static int get_cpudouble(QEMUFile *f, void *pv, size_t size,
> +                         VMStateField *field)
>  {
>      CPU_DoubleU *v = pv;
>      qemu_get_be32s(f, &v->l.upper);
> @@ -809,7 +826,8 @@ static int get_cpudouble(QEMUFile *f, void *pv, size_t size)
>      return 0;
>  }
>  
> -static void put_cpudouble(QEMUFile *f, void *pv, size_t size)
> +static void put_cpudouble(QEMUFile *f, void *pv, size_t size,
> +                          VMStateField *field, QJSON *vmdesc)
>  {
>      CPU_DoubleU *v = pv;
>      qemu_put_be32s(f, &v->l.upper);
> @@ -824,14 +842,16 @@ const VMStateInfo vmstate_info_cpudouble = {
>  
>  /* uint8_t buffers */
>  
> -static int get_buffer(QEMUFile *f, void *pv, size_t size)
> +static int get_buffer(QEMUFile *f, void *pv, size_t size,
> +                      VMStateField *field)
>  {
>      uint8_t *v = pv;
>      qemu_get_buffer(f, v, size);
>      return 0;
>  }
>  
> -static void put_buffer(QEMUFile *f, void *pv, size_t size)
> +static void put_buffer(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                       QJSON *vmdesc)
>  {
>      uint8_t *v = pv;
>      qemu_put_buffer(f, v, size);
> @@ -846,7 +866,8 @@ const VMStateInfo vmstate_info_buffer = {
>  /* unused buffers: space that was used for some fields that are
>     not useful anymore */
>  
> -static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
> +static int get_unused_buffer(QEMUFile *f, void *pv, size_t size,
> +                             VMStateField *field)
>  {
>      uint8_t buf[1024];
>      int block_len;
> @@ -859,7 +880,8 @@ static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
>     return 0;
>  }
>  
> -static void put_unused_buffer(QEMUFile *f, void *pv, size_t size)
> +static void put_unused_buffer(QEMUFile *f, void *pv, size_t size,
> +                              VMStateField *field, QJSON *vmdesc)
>  {
>      static const uint8_t buf[1024];
>      int block_len;
> @@ -884,7 +906,7 @@ const VMStateInfo vmstate_info_unused_buffer = {
>   */
>  /* This is the number of 64 bit words sent over the wire */
>  #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
> -static int get_bitmap(QEMUFile *f, void *pv, size_t size)
> +static int get_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      unsigned long *bmp = pv;
>      int i, idx = 0;
> @@ -898,7 +920,8 @@ static int get_bitmap(QEMUFile *f, void *pv, size_t size)
>      return 0;
>  }
>  
> -static void put_bitmap(QEMUFile *f, void *pv, size_t size)
> +static void put_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                QJSON *vmdesc)
>  {
>      unsigned long *bmp = pv;
>      int i, idx = 0;
> diff --git a/target-alpha/machine.c b/target-alpha/machine.c
> index 710b783..48e3278 100644
> --- a/target-alpha/machine.c
> +++ b/target-alpha/machine.c
> @@ -5,14 +5,15 @@
>  #include "hw/boards.h"
>  #include "migration/cpu.h"
>  
> -static int get_fpcr(QEMUFile *f, void *opaque, size_t size)
> +static int get_fpcr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
>  {
>      CPUAlphaState *env = opaque;
>      cpu_alpha_store_fpcr(env, qemu_get_be64(f));
>      return 0;
>  }
>  
> -static void put_fpcr(QEMUFile *f, void *opaque, size_t size)
> +static void put_fpcr(QEMUFile *f, void *opaque, size_t size,
> +                     VMStateField *field, QJSON *vmdesc)
>  {
>      CPUAlphaState *env = opaque;
>      qemu_put_be64(f, cpu_alpha_load_fpcr(env));
> diff --git a/target-arm/machine.c b/target-arm/machine.c
> index 7a6ca31..41a0de9 100644
> --- a/target-arm/machine.c
> +++ b/target-arm/machine.c
> @@ -17,7 +17,8 @@ static bool vfp_needed(void *opaque)
>      return arm_feature(env, ARM_FEATURE_VFP);
>  }
>  
> -static int get_fpscr(QEMUFile *f, void *opaque, size_t size)
> +static int get_fpscr(QEMUFile *f, void *opaque, size_t size,
> +                     VMStateField *field)
>  {
>      ARMCPU *cpu = opaque;
>      CPUARMState *env = &cpu->env;
> @@ -27,7 +28,8 @@ static int get_fpscr(QEMUFile *f, void *opaque, size_t size)
>      return 0;
>  }
>  
> -static void put_fpscr(QEMUFile *f, void *opaque, size_t size)
> +static void put_fpscr(QEMUFile *f, void *opaque, size_t size,
> +                      VMStateField *field, QJSON *vmdesc)
>  {
>      ARMCPU *cpu = opaque;
>      CPUARMState *env = &cpu->env;
> @@ -163,7 +165,8 @@ static const VMStateDescription vmstate_pmsav7 = {
>      }
>  };
>  
> -static int get_cpsr(QEMUFile *f, void *opaque, size_t size)
> +static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
> +                    VMStateField *field)
>  {
>      ARMCPU *cpu = opaque;
>      CPUARMState *env = &cpu->env;
> @@ -180,7 +183,8 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size)
>      return 0;
>  }
>  
> -static void put_cpsr(QEMUFile *f, void *opaque, size_t size)
> +static void put_cpsr(QEMUFile *f, void *opaque, size_t size,
> +                     VMStateField *field, QJSON *vmdesc)
>  {
>      ARMCPU *cpu = opaque;
>      CPUARMState *env = &cpu->env;
> diff --git a/target-i386/machine.c b/target-i386/machine.c
> index 71c0e4d..1df19e2 100644
> --- a/target-i386/machine.c
> +++ b/target-i386/machine.c
> @@ -139,7 +139,8 @@ static const VMStateDescription vmstate_mtrr_var = {
>  #define VMSTATE_MTRR_VARS(_field, _state, _n, _v)                    \
>      VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar)
>  
> -static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size)
> +static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size,
> +                            VMStateField *field, QJSON *vmdesc)
>  {
>      fprintf(stderr, "call put_fpreg() with invalid arguments\n");
>      exit(0);
> @@ -167,7 +168,8 @@ static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
>      p->exp = e;
>  }
>  
> -static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
> +static int get_fpreg(QEMUFile *f, void *opaque, size_t size,
> +                     VMStateField *field)
>  {
>      FPReg *fp_reg = opaque;
>      uint64_t mant;
> @@ -179,7 +181,8 @@ static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
>      return 0;
>  }
>  
> -static void put_fpreg(QEMUFile *f, void *opaque, size_t size)
> +static void put_fpreg(QEMUFile *f, void *opaque, size_t size,
> +                      VMStateField *field, QJSON *vmdesc)
>  {
>      FPReg *fp_reg = opaque;
>      uint64_t mant;
> @@ -197,7 +200,8 @@ static const VMStateInfo vmstate_fpreg = {
>      .put  = put_fpreg,
>  };
>  
> -static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size)
> +static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size,
> +                           VMStateField *field)
>  {
>      union x86_longdouble *p = opaque;
>      uint64_t mant;
> @@ -214,7 +218,8 @@ static const VMStateInfo vmstate_fpreg_1_mmx = {
>      .put  = put_fpreg_error,
>  };
>  
> -static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size)
> +static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size,
> +                              VMStateField *field)
>  {
>      union x86_longdouble *p = opaque;
>      uint64_t mant;
> @@ -276,14 +281,16 @@ static bool less_than_7(void *opaque, int version_id)
>      return version_id < 7;
>  }
>  
> -static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
> +static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size,
> +                                VMStateField *field)
>  {
>      uint64_t *v = pv;
>      *v = qemu_get_be32(f);
>      return 0;
>  }
>  
> -static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
> +static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size,
> +                                 VMStateField *field, QJSON *vmdesc)
>  {
>      uint64_t *v = pv;
>      qemu_put_be32(f, *v);
> diff --git a/target-mips/machine.c b/target-mips/machine.c
> index a27f2f1..179084c 100644
> --- a/target-mips/machine.c
> +++ b/target-mips/machine.c
> @@ -20,7 +20,7 @@ static int cpu_post_load(void *opaque, int version_id)
>  
>  /* FPU state */
>  
> -static int get_fpr(QEMUFile *f, void *pv, size_t size)
> +static int get_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      int i;
>      fpr_t *v = pv;
> @@ -31,7 +31,8 @@ static int get_fpr(QEMUFile *f, void *pv, size_t size)
>      return 0;
>  }
>  
> -static void put_fpr(QEMUFile *f, void *pv, size_t size)
> +static void put_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                    QJSON *vmdesc)
>  {
>      int i;
>      fpr_t *v = pv;
> @@ -125,7 +126,7 @@ const VMStateDescription vmstate_mvp = {
>  
>  /* TLB state */
>  
> -static int get_tlb(QEMUFile *f, void *pv, size_t size)
> +static int get_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      r4k_tlb_t *v = pv;
>      uint16_t flags;
> @@ -152,7 +153,8 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size)
>      return 0;
>  }
>  
> -static void put_tlb(QEMUFile *f, void *pv, size_t size)
> +static void put_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                    QJSON *vmdesc)
>  {
>      r4k_tlb_t *v = pv;
>  
> diff --git a/target-ppc/machine.c b/target-ppc/machine.c
> index 4820f22..0e1822c 100644
> --- a/target-ppc/machine.c
> +++ b/target-ppc/machine.c
> @@ -106,7 +106,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
>      return 0;
>  }
>  
> -static int get_avr(QEMUFile *f, void *pv, size_t size)
> +static int get_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      ppc_avr_t *v = pv;
>  
> @@ -116,7 +116,8 @@ static int get_avr(QEMUFile *f, void *pv, size_t size)
>      return 0;
>  }
>  
> -static void put_avr(QEMUFile *f, void *pv, size_t size)
> +static void put_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                    QJSON *vmdesc)
>  {
>      ppc_avr_t *v = pv;
>  
> @@ -324,7 +325,7 @@ static const VMStateDescription vmstate_sr = {
>  };
>  
>  #ifdef TARGET_PPC64
> -static int get_slbe(QEMUFile *f, void *pv, size_t size)
> +static int get_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>  {
>      ppc_slb_t *v = pv;
>  
> @@ -334,7 +335,8 @@ static int get_slbe(QEMUFile *f, void *pv, size_t size)
>      return 0;
>  }
>  
> -static void put_slbe(QEMUFile *f, void *pv, size_t size)
> +static void put_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> +                     QJSON *vmdesc)
>  {
>      ppc_slb_t *v = pv;
>  
> diff --git a/target-sparc/machine.c b/target-sparc/machine.c
> index 59c92f7..3194e03 100644
> --- a/target-sparc/machine.c
> +++ b/target-sparc/machine.c
> @@ -59,7 +59,7 @@ static const VMStateDescription vmstate_tlb_entry = {
>  };
>  #endif
>  
> -static int get_psr(QEMUFile *f, void *opaque, size_t size)
> +static int get_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
>  {
>      SPARCCPU *cpu = opaque;
>      CPUSPARCState *env = &cpu->env;
> @@ -72,7 +72,8 @@ static int get_psr(QEMUFile *f, void *opaque, size_t size)
>      return 0;
>  }
>  
> -static void put_psr(QEMUFile *f, void *opaque, size_t size)
> +static void put_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field,
> +                QJSON *vmdesc)
>  {
>      SPARCCPU *cpu = opaque;
>      CPUSPARCState *env = &cpu->env;
> -- 
> 1.9.1
> 
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-06 19:01       ` Dr. David Alan Gilbert
  2016-10-06 19:49         ` Jianjun Duan
  2016-10-07  3:25         ` David Gibson
@ 2016-10-07 14:31         ` Paolo Bonzini
  2016-10-07 14:34           ` Dr. David Alan Gilbert
  2 siblings, 1 reply; 66+ messages in thread
From: Paolo Bonzini @ 2016-10-07 14:31 UTC (permalink / raw)
  To: Dr. David Alan Gilbert, Jianjun Duan
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst, david,
	veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth, aurelien,
	leon.alrae, blauwirbel, mark.cave-ayland, mdroth



On 06/10/2016 21:01, Dr. David Alan Gilbert wrote:
>> >> +                } else if (field->flags & VMS_LINKED) {
>> >> +                    ret = field->info->get(f, addr, size, field);
>> >>                  } else {
>> >>                      ret = field->info->get(f, addr, size, NULL);
>> >>  
>> >> @@ -193,6 +197,8 @@ static const char *vmfield_get_type_name(VMStateField *field)
>> >>  
>> >>      if (field->flags & VMS_STRUCT) {
>> >>          type = "struct";
>> >> +    } else if (field->flags & VMS_LINKED) {
>> >> +        type = "linked";
>> >>      } else if (field->info->name) {
>> >>          type = field->info->name;
>> >>      }
>> >> @@ -327,6 +333,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
>> >>                  }
>> >>                  if (field->flags & VMS_STRUCT) {
>> >>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
>> >> +                } else if  (field->flags & VMS_LINKED) {
>> >> +                    field->info->put(f, addr, size, field, vmdesc_loop);
>> >>                  } else {
>> >>                      field->info->put(f, addr, size, NULL, NULL);
>> >>                  }

Is VMS_LINKED needed at all, since the fields are unused for every
VMStateInfo except qtailq?

Paolo

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

* Re: [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-07 14:31         ` Paolo Bonzini
@ 2016-10-07 14:34           ` Dr. David Alan Gilbert
  2016-10-07 16:31             ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
  0 siblings, 1 reply; 66+ messages in thread
From: Dr. David Alan Gilbert @ 2016-10-07 14:34 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Jianjun Duan, qemu-devel, qemu-ppc, dmitry, peter.maydell,
	kraxel, mst, david, veroniabahaa, quintela, amit.shah, mreitz,
	kwolf, rth, aurelien, leon.alrae, blauwirbel, mark.cave-ayland,
	mdroth

* Paolo Bonzini (pbonzini@redhat.com) wrote:
> 
> 
> On 06/10/2016 21:01, Dr. David Alan Gilbert wrote:
> >> >> +                } else if (field->flags & VMS_LINKED) {
> >> >> +                    ret = field->info->get(f, addr, size, field);
> >> >>                  } else {
> >> >>                      ret = field->info->get(f, addr, size, NULL);
> >> >>  
> >> >> @@ -193,6 +197,8 @@ static const char *vmfield_get_type_name(VMStateField *field)
> >> >>  
> >> >>      if (field->flags & VMS_STRUCT) {
> >> >>          type = "struct";
> >> >> +    } else if (field->flags & VMS_LINKED) {
> >> >> +        type = "linked";
> >> >>      } else if (field->info->name) {
> >> >>          type = field->info->name;
> >> >>      }
> >> >> @@ -327,6 +333,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
> >> >>                  }
> >> >>                  if (field->flags & VMS_STRUCT) {
> >> >>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
> >> >> +                } else if  (field->flags & VMS_LINKED) {
> >> >> +                    field->info->put(f, addr, size, field, vmdesc_loop);
> >> >>                  } else {
> >> >>                      field->info->put(f, addr, size, NULL, NULL);
> >> >>                  }
> 
> Is VMS_LINKED needed at all, since the fields are unused for every
> VMStateInfo except qtailq?

No, I think you could easily drop the VMS_LINKED and just always pass them in.

Dave

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

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

* Re: [Qemu-devel] [QEMU PATCH v5 5/6] migration: spapr: migrate ccs_list in spapr state
  2016-10-07  3:36   ` David Gibson
@ 2016-10-07 14:52     ` Michael Roth
  2016-10-10  5:05       ` David Gibson
  0 siblings, 1 reply; 66+ messages in thread
From: Michael Roth @ 2016-10-07 14:52 UTC (permalink / raw)
  To: David Gibson, Jianjun Duan
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, dgilbert

Quoting David Gibson (2016-10-06 22:36:07)
> On Mon, Oct 03, 2016 at 11:24:56AM -0700, Jianjun Duan wrote:
> > ccs_list in spapr state maintains the device tree related
> > information on the rtas side for hotplugged devices. In racing
> > situations between hotplug events and migration operation, a rtas
> > hotplug event could be migrated from the source guest to target
> > guest, or the source guest could have not yet finished fetching
> > the device tree when migration is started, the target will try
> > to finish fetching the device tree. By migrating ccs_list, the
> > target can fetch the device tree properly.
> > 
> > ccs_list is put in a subsection in the spapr state VMSD to make
> > sure migration across different versions is not broken.
> > 
> > Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
> 
> I'm still not entirely convinced we need to migrate the ccs_list.
> What would happen if we did this:
> 
>    * Keep a flag which indicates whether the guest is in the middle of
>      the configure_connector process.
>        - I'm not sure if that would need to be a new bit of state, or
>          if we could deduce it from the value of the isolation and
>          allocation states
>        - If it's new state, we'd need to migrate it, obviously not if
>          we can derive it from other state flags
> 
>    * On the destination during post_load, if there was an in-progress
>      configure_connector on the source, we set another "stale
>      configure" flag
> 
>    * When a configure_connector call is attempted on the destination
>      with the stale configure flag set, return an error
> 
> The question is, if we choose the right error, can we get the guest to
> either restart the configure from scratch, or fail gracefully, so the
> operator can restart the hotplug

To get the configure to restart, the guest's configure_connector
implementation would need to changed. Current code in drmgr would just
bail on any error, and I'd imagine the in-kernel version does the same.

So at least for existing guests, the only option is failing the command
at the operator's interface, namely device_add. device_add is
asynchronous to the actual hotplug event handling however. So if we want
to convey failure to the user, it would have to be either in the form of
a new QMP event emitted to convey hotplug success or error, or through
device_add itself by implementing something like the async QMP rework
that Marc-Andre posted some time back (which still seems to be a topic
of debate). Which either approach, something like libvirt, with adequate
state-tracking for pending hotplug events, could handle an error event
on the target side post-migrate and convey that to the user somehow.

That's probably a much larger discussion if it comes to that, but doable
in theory.

But even that wouldn't get us totally out of the woods: DRC state can
still be modified outside of hotplug. For instance, a guest should be
able to do:

  drmgr -c pci -s <drc_index> -r
  drmgr -c pci -s <drc_index> -a

to return a device to firmware and then later take it back and
reconfigure it. I'm not aware of any common case where this would occur,
but it's not disallowed by the specification, and performing a migration
between these 2 operations would currently break this since the default
coldplug state on target assumes a configured state in source.

> 
> > ---
> >  hw/ppc/spapr.c | 34 ++++++++++++++++++++++++++++++++++
> >  1 file changed, 34 insertions(+)
> > 
> > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> > index 63b6a0d..1847d35 100644
> > --- a/hw/ppc/spapr.c
> > +++ b/hw/ppc/spapr.c
> > @@ -1255,6 +1255,36 @@ static bool version_before_3(void *opaque, int version_id)
> >      return version_id < 3;
> >  }
> >  
> > +static bool spapr_ccs_list_needed(void *opaque)
> > +{
> > +    sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
> > +    return !QTAILQ_EMPTY(&spapr->ccs_list);
> > +}
> > +
> > +static const VMStateDescription vmstate_spapr_ccs = {
> > +    .name = "spaprconfigureconnectorstate",
> > +    .version_id = 1,
> > +    .minimum_version_id = 1,
> > +    .fields = (VMStateField[]) {
> > +        VMSTATE_UINT32(drc_index, sPAPRConfigureConnectorState),
> > +        VMSTATE_INT32(fdt_offset, sPAPRConfigureConnectorState),
> > +        VMSTATE_INT32(fdt_depth, sPAPRConfigureConnectorState),
> > +        VMSTATE_END_OF_LIST()
> > +    },
> > +};
> > +
> > +static const VMStateDescription vmstate_spapr_ccs_list = {
> > +    .name = "spaprccslist",
> > +    .version_id = 1,
> > +    .minimum_version_id = 1,
> > +    .needed = spapr_ccs_list_needed,
> > +    .fields = (VMStateField[]) {
> > +        VMSTATE_QTAILQ_V(ccs_list, sPAPRMachineState, 1,
> > +                         vmstate_spapr_ccs, sPAPRConfigureConnectorState, next),
> > +        VMSTATE_END_OF_LIST()
> > +    },
> > +};
> > +
> >  static const VMStateDescription vmstate_spapr = {
> >      .name = "spapr",
> >      .version_id = 3,
> > @@ -1270,6 +1300,10 @@ static const VMStateDescription vmstate_spapr = {
> >          VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2),
> >          VMSTATE_END_OF_LIST()
> >      },
> > +    .subsections = (const VMStateDescription*[]) {
> > +        &vmstate_spapr_ccs_list,
> > +        NULL
> > +    }
> >  };
> >  
> >  static int htab_save_setup(QEMUFile *f, void *opaque)
> 
> -- 
> David Gibson                    | I'll have my music baroque, and my code
> david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
>                                 | _way_ _around_!
> http://www.ozlabs.org/~dgibson

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-07 14:34           ` Dr. David Alan Gilbert
@ 2016-10-07 16:31             ` Jianjun Duan
  2016-10-07 16:32               ` Paolo Bonzini
  0 siblings, 1 reply; 66+ messages in thread
From: Jianjun Duan @ 2016-10-07 16:31 UTC (permalink / raw)
  To: Dr. David Alan Gilbert, Paolo Bonzini
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst, david,
	veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth, aurelien,
	leon.alrae, blauwirbel, mark.cave-ayland, mdroth



On 10/07/2016 07:34 AM, Dr. David Alan Gilbert wrote:
> * Paolo Bonzini (pbonzini@redhat.com) wrote:
>>
>>
>> On 06/10/2016 21:01, Dr. David Alan Gilbert wrote:
>>>>>> +                } else if (field->flags & VMS_LINKED) {
>>>>>> +                    ret = field->info->get(f, addr, size, field);
>>>>>>                  } else {
>>>>>>                      ret = field->info->get(f, addr, size, NULL);
>>>>>>  
>>>>>> @@ -193,6 +197,8 @@ static const char *vmfield_get_type_name(VMStateField *field)
>>>>>>  
>>>>>>      if (field->flags & VMS_STRUCT) {
>>>>>>          type = "struct";
>>>>>> +    } else if (field->flags & VMS_LINKED) {
>>>>>> +        type = "linked";
>>>>>>      } else if (field->info->name) {
>>>>>>          type = field->info->name;
>>>>>>      }
>>>>>> @@ -327,6 +333,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
>>>>>>                  }
>>>>>>                  if (field->flags & VMS_STRUCT) {
>>>>>>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
>>>>>> +                } else if  (field->flags & VMS_LINKED) {
>>>>>> +                    field->info->put(f, addr, size, field, vmdesc_loop);
>>>>>>                  } else {
>>>>>>                      field->info->put(f, addr, size, NULL, NULL);
>>>>>>                  }
>>
>> Is VMS_LINKED needed at all, since the fields are unused for every
>> VMStateInfo except qtailq?
> 
> No, I think you could easily drop the VMS_LINKED and just always pass them in.

It is needed if we want to use vmdesc_loop.

Thanks,
Jianjun

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

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-07 16:31             ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
@ 2016-10-07 16:32               ` Paolo Bonzini
  2016-10-07 17:25                 ` Jianjun Duan
  0 siblings, 1 reply; 66+ messages in thread
From: Paolo Bonzini @ 2016-10-07 16:32 UTC (permalink / raw)
  To: Jianjun Duan, Dr. David Alan Gilbert
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst, david,
	veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth, aurelien,
	leon.alrae, blauwirbel, mark.cave-ayland, mdroth



On 07/10/2016 18:31, Jianjun Duan wrote:
> 
> 
> On 10/07/2016 07:34 AM, Dr. David Alan Gilbert wrote:
>> * Paolo Bonzini (pbonzini@redhat.com) wrote:
>>>
>>>
>>> On 06/10/2016 21:01, Dr. David Alan Gilbert wrote:
>>>>>>> +                } else if (field->flags & VMS_LINKED) {
>>>>>>> +                    ret = field->info->get(f, addr, size, field);
>>>>>>>                  } else {
>>>>>>>                      ret = field->info->get(f, addr, size, NULL);
>>>>>>>  
>>>>>>> @@ -193,6 +197,8 @@ static const char *vmfield_get_type_name(VMStateField *field)
>>>>>>>  
>>>>>>>      if (field->flags & VMS_STRUCT) {
>>>>>>>          type = "struct";
>>>>>>> +    } else if (field->flags & VMS_LINKED) {
>>>>>>> +        type = "linked";
>>>>>>>      } else if (field->info->name) {
>>>>>>>          type = field->info->name;
>>>>>>>      }
>>>>>>> @@ -327,6 +333,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
>>>>>>>                  }
>>>>>>>                  if (field->flags & VMS_STRUCT) {
>>>>>>>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
>>>>>>> +                } else if  (field->flags & VMS_LINKED) {
>>>>>>> +                    field->info->put(f, addr, size, field, vmdesc_loop);
>>>>>>>                  } else {
>>>>>>>                      field->info->put(f, addr, size, NULL, NULL);
>>>>>>>                  }
>>>
>>> Is VMS_LINKED needed at all, since the fields are unused for every
>>> VMStateInfo except qtailq?
>>
>> No, I think you could easily drop the VMS_LINKED and just always pass them in.
> 
> It is needed if we want to use vmdesc_loop.

Just always pass it in, can't you?

Paolo

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-07 12:08   ` Dr. David Alan Gilbert
@ 2016-10-07 16:35     ` Jianjun Duan
  2016-10-07 18:42       ` Dr. David Alan Gilbert
  0 siblings, 1 reply; 66+ messages in thread
From: Jianjun Duan @ 2016-10-07 16:35 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth



On 10/07/2016 05:08 AM, Dr. David Alan Gilbert wrote:
> * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
>> Current migration code cannot handle some data structures such as
>> QTAILQ in qemu/queue.h. Here we extend the signatures of put/get
>> in VMStateInfo so that customized handling is supported.
>>
>> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
>> ---
>>  hw/net/vmxnet3.c            | 18 ++++++---
>>  hw/nvram/eeprom93xx.c       |  6 ++-
>>  hw/nvram/fw_cfg.c           |  6 ++-
>>  hw/pci/msix.c               |  6 ++-
>>  hw/pci/pci.c                | 12 ++++--
>>  hw/pci/shpc.c               |  5 ++-
>>  hw/scsi/scsi-bus.c          |  6 ++-
>>  hw/timer/twl92230.c         |  6 ++-
>>  hw/usb/redirect.c           | 18 ++++++---
>>  hw/virtio/virtio-pci.c      |  6 ++-
>>  hw/virtio/virtio.c          |  6 ++-
>>  include/migration/vmstate.h | 10 +++--
>>  migration/savevm.c          |  5 ++-
>>  migration/vmstate.c         | 95 ++++++++++++++++++++++++++++-----------------
>>  target-alpha/machine.c      |  5 ++-
>>  target-arm/machine.c        | 12 ++++--
>>  target-i386/machine.c       | 21 ++++++----
>>  target-mips/machine.c       | 10 +++--
>>  target-ppc/machine.c        | 10 +++--
>>  target-sparc/machine.c      |  5 ++-
>>  20 files changed, 171 insertions(+), 97 deletions(-)
>>
> 
> <snip>
> 
>> diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
>> index 444672a..2ca4b46 100644
>> --- a/hw/usb/redirect.c
>> +++ b/hw/usb/redirect.c
>> @@ -2154,7 +2154,8 @@ static int usbredir_post_load(void *priv, int version_id)
>>  }
>>  
>>  /* For usbredirparser migration */
>> -static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
>> +static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused,
>> +                                void *opaque, QJSON *vmdesc)
>>  {
>>      USBRedirDevice *dev = priv;
>>      uint8_t *data;
>> @@ -2174,7 +2175,8 @@ static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
>>      free(data);
>>  }
>>  
>> -static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused)
>> +static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused,
>> +                               void *opaque)
> 
> Neither of these built for me; I had to change those to VMStateField rather than void *;
> 
> also is this series tested ontop of Halil's patches - because without them
> I'm finding I also had to fix up most of the other virtio devices.
> 
> Dave

I built it on top of ppc-for-2.8 without problems. Is Hail's patch in
ppc-for-2.8 yet?

Thanks,
Jianjun

> 
> 
>>      USBRedirDevice *dev = priv;
>>      uint8_t *data;
>> @@ -2217,7 +2219,8 @@ static const VMStateInfo usbredir_parser_vmstate_info = {
>>  
>>  
>>  /* For buffered packets (iso/irq) queue migration */
>> -static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
>> +static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused,
>> +                               VMStateField *field, QJSON *vmdesc)
>>  {
>>      struct endp_data *endp = priv;
>>      USBRedirDevice *dev = endp->dev;
>> @@ -2237,7 +2240,8 @@ static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
>>      assert(i == endp->bufpq_size);
>>  }
>>  
>> -static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused)
>> +static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused,
>> +                              VMStateField *field)
>>  {
>>      struct endp_data *endp = priv;
>>      USBRedirDevice *dev = endp->dev;
>> @@ -2340,7 +2344,8 @@ static const VMStateDescription usbredir_ep_vmstate = {
>>  
>>  
>>  /* For PacketIdQueue migration */
>> -static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused)
>> +static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused,
>> +                                     VMStateField *field, QJSON *vmdesc)
>>  {
>>      struct PacketIdQueue *q = priv;
>>      USBRedirDevice *dev = q->dev;
>> @@ -2356,7 +2361,8 @@ static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused)
>>      assert(remain == 0);
>>  }
>>  
>> -static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused)
>> +static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused,
>> +                                    VMStateField *field)
>>  {
>>      struct PacketIdQueue *q = priv;
>>      USBRedirDevice *dev = q->dev;
>> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
>> index 2d60a00..38a7abd 100644
>> --- a/hw/virtio/virtio-pci.c
>> +++ b/hw/virtio/virtio-pci.c
>> @@ -108,7 +108,8 @@ static bool virtio_pci_has_extra_state(DeviceState *d)
>>      return proxy->flags & VIRTIO_PCI_FLAG_MIGRATE_EXTRA;
>>  }
>>  
>> -static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size)
>> +static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size,
>> +                                       VMStateField *field)
>>  {
>>      VirtIOPCIProxy *proxy = pv;
>>      int i;
>> @@ -137,7 +138,8 @@ static void virtio_pci_save_modern_queue_state(VirtIOPCIQueue *vq,
>>      qemu_put_be32(f, vq->used[1]);
>>  }
>>  
>> -static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size)
>> +static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size,
>> +                                        VMStateField *field, QJSON *vmdesc)
>>  {
>>      VirtIOPCIProxy *proxy = pv;
>>      int i;
>> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
>> index 18ce333..ade2683 100644
>> --- a/hw/virtio/virtio.c
>> +++ b/hw/virtio/virtio.c
>> @@ -1467,7 +1467,8 @@ static const VMStateDescription vmstate_virtio_ringsize = {
>>      }
>>  };
>>  
>> -static int get_extra_state(QEMUFile *f, void *pv, size_t size)
>> +static int get_extra_state(QEMUFile *f, void *pv, size_t size,
>> +                           VMStateField *field)
>>  {
>>      VirtIODevice *vdev = pv;
>>      BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
>> @@ -1480,7 +1481,8 @@ static int get_extra_state(QEMUFile *f, void *pv, size_t size)
>>      }
>>  }
>>  
>> -static void put_extra_state(QEMUFile *f, void *pv, size_t size)
>> +static void put_extra_state(QEMUFile *f, void *pv, size_t size,
>> +                            VMStateField *field, QJSON *vmdesc)
>>  {
>>      VirtIODevice *vdev = pv;
>>      BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
>> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
>> index 1638ee5..459dd4a 100644
>> --- a/include/migration/vmstate.h
>> +++ b/include/migration/vmstate.h
>> @@ -81,11 +81,13 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque);
>>  
>>  typedef struct VMStateInfo VMStateInfo;
>>  typedef struct VMStateDescription VMStateDescription;
>> +typedef struct VMStateField VMStateField;
>>  
>>  struct VMStateInfo {
>>      const char *name;
>> -    int (*get)(QEMUFile *f, void *pv, size_t size);
>> -    void (*put)(QEMUFile *f, void *pv, size_t size);
>> +    int (*get)(QEMUFile *f, void *pv, size_t size, VMStateField *field);
>> +    void (*put)(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                QJSON *vmdesc);
>>  };
>>  
>>  enum VMStateFlags {
>> @@ -186,7 +188,7 @@ enum VMStateFlags {
>>      VMS_MULTIPLY_ELEMENTS = 0x4000,
>>  };
>>  
>> -typedef struct {
>> +struct VMStateField {
>>      const char *name;
>>      size_t offset;
>>      size_t size;
>> @@ -199,7 +201,7 @@ typedef struct {
>>      const VMStateDescription *vmsd;
>>      int version_id;
>>      bool (*field_exists)(void *opaque, int version_id);
>> -} VMStateField;
>> +};
>>  
>>  struct VMStateDescription {
>>      const char *name;
>> diff --git a/migration/savevm.c b/migration/savevm.c
>> index ef5c3d1..13b53ad 100644
>> --- a/migration/savevm.c
>> +++ b/migration/savevm.c
>> @@ -220,14 +220,15 @@ void timer_get(QEMUFile *f, QEMUTimer *ts)
>>   * Not in vmstate.c to not add qemu-timer.c as dependency to vmstate.c
>>   */
>>  
>> -static int get_timer(QEMUFile *f, void *pv, size_t size)
>> +static int get_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      QEMUTimer *v = pv;
>>      timer_get(f, v);
>>      return 0;
>>  }
>>  
>> -static void put_timer(QEMUFile *f, void *pv, size_t size)
>> +static void put_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                QJSON *vmdesc)
>>  {
>>      QEMUTimer *v = pv;
>>      timer_put(f, v);
>> diff --git a/migration/vmstate.c b/migration/vmstate.c
>> index fc29acf..66802cb 100644
>> --- a/migration/vmstate.c
>> +++ b/migration/vmstate.c
>> @@ -122,7 +122,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
>>                      ret = vmstate_load_state(f, field->vmsd, addr,
>>                                               field->vmsd->version_id);
>>                  } else {
>> -                    ret = field->info->get(f, addr, size);
>> +                    ret = field->info->get(f, addr, size, NULL);
>>  
>>                  }
>>                  if (ret >= 0) {
>> @@ -328,7 +328,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
>>                  if (field->flags & VMS_STRUCT) {
>>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
>>                  } else {
>> -                    field->info->put(f, addr, size);
>> +                    field->info->put(f, addr, size, NULL, NULL);
>>                  }
>>  
>>                  written_bytes = qemu_ftell_fast(f) - old_offset;
>> @@ -461,14 +461,15 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
>>  
>>  /* bool */
>>  
>> -static int get_bool(QEMUFile *f, void *pv, size_t size)
>> +static int get_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      bool *v = pv;
>>      *v = qemu_get_byte(f);
>>      return 0;
>>  }
>>  
>> -static void put_bool(QEMUFile *f, void *pv, size_t size)
>> +static void put_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                     QJSON *vmdesc)
>>  {
>>      bool *v = pv;
>>      qemu_put_byte(f, *v);
>> @@ -482,14 +483,15 @@ const VMStateInfo vmstate_info_bool = {
>>  
>>  /* 8 bit int */
>>  
>> -static int get_int8(QEMUFile *f, void *pv, size_t size)
>> +static int get_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      int8_t *v = pv;
>>      qemu_get_s8s(f, v);
>>      return 0;
>>  }
>>  
>> -static void put_int8(QEMUFile *f, void *pv, size_t size)
>> +static void put_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                     QJSON *vmdesc)
>>  {
>>      int8_t *v = pv;
>>      qemu_put_s8s(f, v);
>> @@ -503,14 +505,15 @@ const VMStateInfo vmstate_info_int8 = {
>>  
>>  /* 16 bit int */
>>  
>> -static int get_int16(QEMUFile *f, void *pv, size_t size)
>> +static int get_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      int16_t *v = pv;
>>      qemu_get_sbe16s(f, v);
>>      return 0;
>>  }
>>  
>> -static void put_int16(QEMUFile *f, void *pv, size_t size)
>> +static void put_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                      QJSON *vmdesc)
>>  {
>>      int16_t *v = pv;
>>      qemu_put_sbe16s(f, v);
>> @@ -524,14 +527,15 @@ const VMStateInfo vmstate_info_int16 = {
>>  
>>  /* 32 bit int */
>>  
>> -static int get_int32(QEMUFile *f, void *pv, size_t size)
>> +static int get_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      int32_t *v = pv;
>>      qemu_get_sbe32s(f, v);
>>      return 0;
>>  }
>>  
>> -static void put_int32(QEMUFile *f, void *pv, size_t size)
>> +static void put_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                      QJSON *vmdesc)
>>  {
>>      int32_t *v = pv;
>>      qemu_put_sbe32s(f, v);
>> @@ -546,7 +550,8 @@ const VMStateInfo vmstate_info_int32 = {
>>  /* 32 bit int. See that the received value is the same than the one
>>     in the field */
>>  
>> -static int get_int32_equal(QEMUFile *f, void *pv, size_t size)
>> +static int get_int32_equal(QEMUFile *f, void *pv, size_t size,
>> +                           VMStateField *field)
>>  {
>>      int32_t *v = pv;
>>      int32_t v2;
>> @@ -568,7 +573,7 @@ const VMStateInfo vmstate_info_int32_equal = {
>>   * and less than or equal to the one in the field.
>>   */
>>  
>> -static int get_int32_le(QEMUFile *f, void *pv, size_t size)
>> +static int get_int32_le(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      int32_t *cur = pv;
>>      int32_t loaded;
>> @@ -589,14 +594,15 @@ const VMStateInfo vmstate_info_int32_le = {
>>  
>>  /* 64 bit int */
>>  
>> -static int get_int64(QEMUFile *f, void *pv, size_t size)
>> +static int get_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      int64_t *v = pv;
>>      qemu_get_sbe64s(f, v);
>>      return 0;
>>  }
>>  
>> -static void put_int64(QEMUFile *f, void *pv, size_t size)
>> +static void put_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                      QJSON *vmdesc)
>>  {
>>      int64_t *v = pv;
>>      qemu_put_sbe64s(f, v);
>> @@ -610,14 +616,15 @@ const VMStateInfo vmstate_info_int64 = {
>>  
>>  /* 8 bit unsigned int */
>>  
>> -static int get_uint8(QEMUFile *f, void *pv, size_t size)
>> +static int get_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      uint8_t *v = pv;
>>      qemu_get_8s(f, v);
>>      return 0;
>>  }
>>  
>> -static void put_uint8(QEMUFile *f, void *pv, size_t size)
>> +static void put_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                      QJSON *vmdesc)
>>  {
>>      uint8_t *v = pv;
>>      qemu_put_8s(f, v);
>> @@ -631,14 +638,15 @@ const VMStateInfo vmstate_info_uint8 = {
>>  
>>  /* 16 bit unsigned int */
>>  
>> -static int get_uint16(QEMUFile *f, void *pv, size_t size)
>> +static int get_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      uint16_t *v = pv;
>>      qemu_get_be16s(f, v);
>>      return 0;
>>  }
>>  
>> -static void put_uint16(QEMUFile *f, void *pv, size_t size)
>> +static void put_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                       QJSON *vmdesc)
>>  {
>>      uint16_t *v = pv;
>>      qemu_put_be16s(f, v);
>> @@ -652,14 +660,15 @@ const VMStateInfo vmstate_info_uint16 = {
>>  
>>  /* 32 bit unsigned int */
>>  
>> -static int get_uint32(QEMUFile *f, void *pv, size_t size)
>> +static int get_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      uint32_t *v = pv;
>>      qemu_get_be32s(f, v);
>>      return 0;
>>  }
>>  
>> -static void put_uint32(QEMUFile *f, void *pv, size_t size)
>> +static void put_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                       QJSON *vmdesc)
>>  {
>>      uint32_t *v = pv;
>>      qemu_put_be32s(f, v);
>> @@ -674,7 +683,8 @@ const VMStateInfo vmstate_info_uint32 = {
>>  /* 32 bit uint. See that the received value is the same than the one
>>     in the field */
>>  
>> -static int get_uint32_equal(QEMUFile *f, void *pv, size_t size)
>> +static int get_uint32_equal(QEMUFile *f, void *pv, size_t size,
>> +                            VMStateField *field)
>>  {
>>      uint32_t *v = pv;
>>      uint32_t v2;
>> @@ -694,14 +704,15 @@ const VMStateInfo vmstate_info_uint32_equal = {
>>  
>>  /* 64 bit unsigned int */
>>  
>> -static int get_uint64(QEMUFile *f, void *pv, size_t size)
>> +static int get_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      uint64_t *v = pv;
>>      qemu_get_be64s(f, v);
>>      return 0;
>>  }
>>  
>> -static void put_uint64(QEMUFile *f, void *pv, size_t size)
>> +static void put_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                       QJSON *vmdesc)
>>  {
>>      uint64_t *v = pv;
>>      qemu_put_be64s(f, v);
>> @@ -716,7 +727,8 @@ const VMStateInfo vmstate_info_uint64 = {
>>  /* 64 bit unsigned int. See that the received value is the same than the one
>>     in the field */
>>  
>> -static int get_uint64_equal(QEMUFile *f, void *pv, size_t size)
>> +static int get_uint64_equal(QEMUFile *f, void *pv, size_t size,
>> +                            VMStateField *field)
>>  {
>>      uint64_t *v = pv;
>>      uint64_t v2;
>> @@ -737,7 +749,8 @@ const VMStateInfo vmstate_info_uint64_equal = {
>>  /* 8 bit int. See that the received value is the same than the one
>>     in the field */
>>  
>> -static int get_uint8_equal(QEMUFile *f, void *pv, size_t size)
>> +static int get_uint8_equal(QEMUFile *f, void *pv, size_t size,
>> +                           VMStateField *field)
>>  {
>>      uint8_t *v = pv;
>>      uint8_t v2;
>> @@ -758,7 +771,8 @@ const VMStateInfo vmstate_info_uint8_equal = {
>>  /* 16 bit unsigned int int. See that the received value is the same than the one
>>     in the field */
>>  
>> -static int get_uint16_equal(QEMUFile *f, void *pv, size_t size)
>> +static int get_uint16_equal(QEMUFile *f, void *pv, size_t size,
>> +                            VMStateField *field)
>>  {
>>      uint16_t *v = pv;
>>      uint16_t v2;
>> @@ -778,7 +792,8 @@ const VMStateInfo vmstate_info_uint16_equal = {
>>  
>>  /* floating point */
>>  
>> -static int get_float64(QEMUFile *f, void *pv, size_t size)
>> +static int get_float64(QEMUFile *f, void *pv, size_t size,
>> +                       VMStateField *field)
>>  {
>>      float64 *v = pv;
>>  
>> @@ -786,7 +801,8 @@ static int get_float64(QEMUFile *f, void *pv, size_t size)
>>      return 0;
>>  }
>>  
>> -static void put_float64(QEMUFile *f, void *pv, size_t size)
>> +static void put_float64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                        QJSON *vmdesc)
>>  {
>>      uint64_t *v = pv;
>>  
>> @@ -801,7 +817,8 @@ const VMStateInfo vmstate_info_float64 = {
>>  
>>  /* CPU_DoubleU type */
>>  
>> -static int get_cpudouble(QEMUFile *f, void *pv, size_t size)
>> +static int get_cpudouble(QEMUFile *f, void *pv, size_t size,
>> +                         VMStateField *field)
>>  {
>>      CPU_DoubleU *v = pv;
>>      qemu_get_be32s(f, &v->l.upper);
>> @@ -809,7 +826,8 @@ static int get_cpudouble(QEMUFile *f, void *pv, size_t size)
>>      return 0;
>>  }
>>  
>> -static void put_cpudouble(QEMUFile *f, void *pv, size_t size)
>> +static void put_cpudouble(QEMUFile *f, void *pv, size_t size,
>> +                          VMStateField *field, QJSON *vmdesc)
>>  {
>>      CPU_DoubleU *v = pv;
>>      qemu_put_be32s(f, &v->l.upper);
>> @@ -824,14 +842,16 @@ const VMStateInfo vmstate_info_cpudouble = {
>>  
>>  /* uint8_t buffers */
>>  
>> -static int get_buffer(QEMUFile *f, void *pv, size_t size)
>> +static int get_buffer(QEMUFile *f, void *pv, size_t size,
>> +                      VMStateField *field)
>>  {
>>      uint8_t *v = pv;
>>      qemu_get_buffer(f, v, size);
>>      return 0;
>>  }
>>  
>> -static void put_buffer(QEMUFile *f, void *pv, size_t size)
>> +static void put_buffer(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                       QJSON *vmdesc)
>>  {
>>      uint8_t *v = pv;
>>      qemu_put_buffer(f, v, size);
>> @@ -846,7 +866,8 @@ const VMStateInfo vmstate_info_buffer = {
>>  /* unused buffers: space that was used for some fields that are
>>     not useful anymore */
>>  
>> -static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
>> +static int get_unused_buffer(QEMUFile *f, void *pv, size_t size,
>> +                             VMStateField *field)
>>  {
>>      uint8_t buf[1024];
>>      int block_len;
>> @@ -859,7 +880,8 @@ static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
>>     return 0;
>>  }
>>  
>> -static void put_unused_buffer(QEMUFile *f, void *pv, size_t size)
>> +static void put_unused_buffer(QEMUFile *f, void *pv, size_t size,
>> +                              VMStateField *field, QJSON *vmdesc)
>>  {
>>      static const uint8_t buf[1024];
>>      int block_len;
>> @@ -884,7 +906,7 @@ const VMStateInfo vmstate_info_unused_buffer = {
>>   */
>>  /* This is the number of 64 bit words sent over the wire */
>>  #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
>> -static int get_bitmap(QEMUFile *f, void *pv, size_t size)
>> +static int get_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      unsigned long *bmp = pv;
>>      int i, idx = 0;
>> @@ -898,7 +920,8 @@ static int get_bitmap(QEMUFile *f, void *pv, size_t size)
>>      return 0;
>>  }
>>  
>> -static void put_bitmap(QEMUFile *f, void *pv, size_t size)
>> +static void put_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                QJSON *vmdesc)
>>  {
>>      unsigned long *bmp = pv;
>>      int i, idx = 0;
>> diff --git a/target-alpha/machine.c b/target-alpha/machine.c
>> index 710b783..48e3278 100644
>> --- a/target-alpha/machine.c
>> +++ b/target-alpha/machine.c
>> @@ -5,14 +5,15 @@
>>  #include "hw/boards.h"
>>  #include "migration/cpu.h"
>>  
>> -static int get_fpcr(QEMUFile *f, void *opaque, size_t size)
>> +static int get_fpcr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
>>  {
>>      CPUAlphaState *env = opaque;
>>      cpu_alpha_store_fpcr(env, qemu_get_be64(f));
>>      return 0;
>>  }
>>  
>> -static void put_fpcr(QEMUFile *f, void *opaque, size_t size)
>> +static void put_fpcr(QEMUFile *f, void *opaque, size_t size,
>> +                     VMStateField *field, QJSON *vmdesc)
>>  {
>>      CPUAlphaState *env = opaque;
>>      qemu_put_be64(f, cpu_alpha_load_fpcr(env));
>> diff --git a/target-arm/machine.c b/target-arm/machine.c
>> index 7a6ca31..41a0de9 100644
>> --- a/target-arm/machine.c
>> +++ b/target-arm/machine.c
>> @@ -17,7 +17,8 @@ static bool vfp_needed(void *opaque)
>>      return arm_feature(env, ARM_FEATURE_VFP);
>>  }
>>  
>> -static int get_fpscr(QEMUFile *f, void *opaque, size_t size)
>> +static int get_fpscr(QEMUFile *f, void *opaque, size_t size,
>> +                     VMStateField *field)
>>  {
>>      ARMCPU *cpu = opaque;
>>      CPUARMState *env = &cpu->env;
>> @@ -27,7 +28,8 @@ static int get_fpscr(QEMUFile *f, void *opaque, size_t size)
>>      return 0;
>>  }
>>  
>> -static void put_fpscr(QEMUFile *f, void *opaque, size_t size)
>> +static void put_fpscr(QEMUFile *f, void *opaque, size_t size,
>> +                      VMStateField *field, QJSON *vmdesc)
>>  {
>>      ARMCPU *cpu = opaque;
>>      CPUARMState *env = &cpu->env;
>> @@ -163,7 +165,8 @@ static const VMStateDescription vmstate_pmsav7 = {
>>      }
>>  };
>>  
>> -static int get_cpsr(QEMUFile *f, void *opaque, size_t size)
>> +static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
>> +                    VMStateField *field)
>>  {
>>      ARMCPU *cpu = opaque;
>>      CPUARMState *env = &cpu->env;
>> @@ -180,7 +183,8 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size)
>>      return 0;
>>  }
>>  
>> -static void put_cpsr(QEMUFile *f, void *opaque, size_t size)
>> +static void put_cpsr(QEMUFile *f, void *opaque, size_t size,
>> +                     VMStateField *field, QJSON *vmdesc)
>>  {
>>      ARMCPU *cpu = opaque;
>>      CPUARMState *env = &cpu->env;
>> diff --git a/target-i386/machine.c b/target-i386/machine.c
>> index 71c0e4d..1df19e2 100644
>> --- a/target-i386/machine.c
>> +++ b/target-i386/machine.c
>> @@ -139,7 +139,8 @@ static const VMStateDescription vmstate_mtrr_var = {
>>  #define VMSTATE_MTRR_VARS(_field, _state, _n, _v)                    \
>>      VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar)
>>  
>> -static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size)
>> +static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size,
>> +                            VMStateField *field, QJSON *vmdesc)
>>  {
>>      fprintf(stderr, "call put_fpreg() with invalid arguments\n");
>>      exit(0);
>> @@ -167,7 +168,8 @@ static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
>>      p->exp = e;
>>  }
>>  
>> -static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
>> +static int get_fpreg(QEMUFile *f, void *opaque, size_t size,
>> +                     VMStateField *field)
>>  {
>>      FPReg *fp_reg = opaque;
>>      uint64_t mant;
>> @@ -179,7 +181,8 @@ static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
>>      return 0;
>>  }
>>  
>> -static void put_fpreg(QEMUFile *f, void *opaque, size_t size)
>> +static void put_fpreg(QEMUFile *f, void *opaque, size_t size,
>> +                      VMStateField *field, QJSON *vmdesc)
>>  {
>>      FPReg *fp_reg = opaque;
>>      uint64_t mant;
>> @@ -197,7 +200,8 @@ static const VMStateInfo vmstate_fpreg = {
>>      .put  = put_fpreg,
>>  };
>>  
>> -static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size)
>> +static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size,
>> +                           VMStateField *field)
>>  {
>>      union x86_longdouble *p = opaque;
>>      uint64_t mant;
>> @@ -214,7 +218,8 @@ static const VMStateInfo vmstate_fpreg_1_mmx = {
>>      .put  = put_fpreg_error,
>>  };
>>  
>> -static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size)
>> +static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size,
>> +                              VMStateField *field)
>>  {
>>      union x86_longdouble *p = opaque;
>>      uint64_t mant;
>> @@ -276,14 +281,16 @@ static bool less_than_7(void *opaque, int version_id)
>>      return version_id < 7;
>>  }
>>  
>> -static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
>> +static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size,
>> +                                VMStateField *field)
>>  {
>>      uint64_t *v = pv;
>>      *v = qemu_get_be32(f);
>>      return 0;
>>  }
>>  
>> -static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
>> +static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size,
>> +                                 VMStateField *field, QJSON *vmdesc)
>>  {
>>      uint64_t *v = pv;
>>      qemu_put_be32(f, *v);
>> diff --git a/target-mips/machine.c b/target-mips/machine.c
>> index a27f2f1..179084c 100644
>> --- a/target-mips/machine.c
>> +++ b/target-mips/machine.c
>> @@ -20,7 +20,7 @@ static int cpu_post_load(void *opaque, int version_id)
>>  
>>  /* FPU state */
>>  
>> -static int get_fpr(QEMUFile *f, void *pv, size_t size)
>> +static int get_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      int i;
>>      fpr_t *v = pv;
>> @@ -31,7 +31,8 @@ static int get_fpr(QEMUFile *f, void *pv, size_t size)
>>      return 0;
>>  }
>>  
>> -static void put_fpr(QEMUFile *f, void *pv, size_t size)
>> +static void put_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                    QJSON *vmdesc)
>>  {
>>      int i;
>>      fpr_t *v = pv;
>> @@ -125,7 +126,7 @@ const VMStateDescription vmstate_mvp = {
>>  
>>  /* TLB state */
>>  
>> -static int get_tlb(QEMUFile *f, void *pv, size_t size)
>> +static int get_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      r4k_tlb_t *v = pv;
>>      uint16_t flags;
>> @@ -152,7 +153,8 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size)
>>      return 0;
>>  }
>>  
>> -static void put_tlb(QEMUFile *f, void *pv, size_t size)
>> +static void put_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                    QJSON *vmdesc)
>>  {
>>      r4k_tlb_t *v = pv;
>>  
>> diff --git a/target-ppc/machine.c b/target-ppc/machine.c
>> index 4820f22..0e1822c 100644
>> --- a/target-ppc/machine.c
>> +++ b/target-ppc/machine.c
>> @@ -106,7 +106,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
>>      return 0;
>>  }
>>  
>> -static int get_avr(QEMUFile *f, void *pv, size_t size)
>> +static int get_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      ppc_avr_t *v = pv;
>>  
>> @@ -116,7 +116,8 @@ static int get_avr(QEMUFile *f, void *pv, size_t size)
>>      return 0;
>>  }
>>  
>> -static void put_avr(QEMUFile *f, void *pv, size_t size)
>> +static void put_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                    QJSON *vmdesc)
>>  {
>>      ppc_avr_t *v = pv;
>>  
>> @@ -324,7 +325,7 @@ static const VMStateDescription vmstate_sr = {
>>  };
>>  
>>  #ifdef TARGET_PPC64
>> -static int get_slbe(QEMUFile *f, void *pv, size_t size)
>> +static int get_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field)
>>  {
>>      ppc_slb_t *v = pv;
>>  
>> @@ -334,7 +335,8 @@ static int get_slbe(QEMUFile *f, void *pv, size_t size)
>>      return 0;
>>  }
>>  
>> -static void put_slbe(QEMUFile *f, void *pv, size_t size)
>> +static void put_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field,
>> +                     QJSON *vmdesc)
>>  {
>>      ppc_slb_t *v = pv;
>>  
>> diff --git a/target-sparc/machine.c b/target-sparc/machine.c
>> index 59c92f7..3194e03 100644
>> --- a/target-sparc/machine.c
>> +++ b/target-sparc/machine.c
>> @@ -59,7 +59,7 @@ static const VMStateDescription vmstate_tlb_entry = {
>>  };
>>  #endif
>>  
>> -static int get_psr(QEMUFile *f, void *opaque, size_t size)
>> +static int get_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
>>  {
>>      SPARCCPU *cpu = opaque;
>>      CPUSPARCState *env = &cpu->env;
>> @@ -72,7 +72,8 @@ static int get_psr(QEMUFile *f, void *opaque, size_t size)
>>      return 0;
>>  }
>>  
>> -static void put_psr(QEMUFile *f, void *opaque, size_t size)
>> +static void put_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field,
>> +                QJSON *vmdesc)
>>  {
>>      SPARCCPU *cpu = opaque;
>>      CPUSPARCState *env = &cpu->env;
>> -- 
>> 1.9.1
>>
>>
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
> 

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

* Re: [Qemu-devel] [QEMU PATCH v5 2/6] migration: spapr_drc: defined VMStateDescription struct
  2016-10-07  3:12   ` David Gibson
@ 2016-10-07 17:17     ` Jianjun Duan
  2016-10-10  5:09       ` David Gibson
  0 siblings, 1 reply; 66+ messages in thread
From: Jianjun Duan @ 2016-10-07 17:17 UTC (permalink / raw)
  To: David Gibson
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth,
	dgilbert



On 10/06/2016 08:12 PM, David Gibson wrote:
> On Mon, Oct 03, 2016 at 11:24:53AM -0700, Jianjun Duan wrote:
>> To manage hotplug/unplug of dynamic resources such as PCI cards,
>> memory, and CPU on sPAPR guests, a firmware abstraction known as
>> a Dynamic Resource Connector (DRC) is used to assign a particular
>> dynamic resource to the guest, and provide an interface for the
>> guest to manage configuration/removal of the resource associated
>> with it.
>>
>> To migrate the hotplugged resources in migration, the
>> associated DRC state need be migrated. To migrate the DRC state,
>> we defined the VMStateDescription struct for spapr_drc to enable
>> the transmission of spapr_drc state in migration.
>>
>> Not all the elements in the DRC state are migrated. Only those
>> ones modifiable or needed by guest actions or device add/remove
>> operation are migrated. From the perspective of device
>> hotplugging, if we hotplug a device on the source, we need to
>> "coldplug" it on the target. The states across two hosts for the
>> same device are not the same. Ideally we want the states be same
>> after migration so that the device would function as hotplugged
>> on the target. For example we can unplug it. The minimum DRC
>> state we need to transfer should cover all the pieces changed by
>> hotplugging. Out of the elements of the DRC state, isolation_state,
>> allocation_sate, and configured are involved in the DR state
>> transition diagram from PAPR+ 2.7, 13.4. configured and signalled
>> are needed in attaching and detaching devices. indicator_state
>> provides users with hardware state information. These 6 elements
>> are migrated.
> 
> Hmm.. are you saying that the DRC state of a coldplugged device (after
> we've fully booted) is different from the DRC state of a hotplugged
> device (after all the hotplug operations have fully completed)?
> 
> If that's correct that sounds like a general bug in the DRC state
> management, not something only related to migration.
> 
> Looking at the code, though, that doesn't really seem to be what it's
> doing.
> 

After hotplugging a device, changes may be made to its DRC state on the
source. But on target the state is fresh. The possible changes are shown
in spapr_drc_needed function.
>> detach_cb in the DRC state is a function pointer that cannot be
>> migrated. We set it right after DRC state is migrated so that
>> a migrated hot-unplug event could finish its work.
>>
>> The instance_id is used to identify objects in migration. We set
>> instance_id of DRC using the unique index so that it is the same
>> across migration.
>>
>> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
>> ---
>>  hw/ppc/spapr_drc.c         | 69 ++++++++++++++++++++++++++++++++++++++++++++++
>>  hw/ppc/spapr_pci.c         | 22 +++++++++++++++
>>  include/hw/ppc/spapr_drc.h |  9 ++++++
>>  3 files changed, 100 insertions(+)
>>
>> diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
>> index 6e54fd4..369ec02 100644
>> --- a/hw/ppc/spapr_drc.c
>> +++ b/hw/ppc/spapr_drc.c
>> @@ -615,6 +615,71 @@ static void spapr_dr_connector_instance_init(Object *obj)
>>                          NULL, NULL, NULL, NULL);
>>  }
>>  
>> +static bool spapr_drc_needed(void *opaque)
>> +{
>> +    sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;
>> +    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
>> +    bool rc = false;
>> +    sPAPRDREntitySense value;
>> +
>> +    drck->entity_sense(drc, &value);
>> +    /* If no dev is plugged in there is no need to migrate the DRC state */
>> +    if (value != SPAPR_DR_ENTITY_SENSE_PRESENT) {
>> +        return false;
>> +    }
>> +    /*
>> +     * If there is dev plugged in, we need to migrate the DRC state when
>> +     * it is different from cold-plugged state
>> +     */
>> +    switch(drc->type) {
>> +    /* for PCI type */
>> +    case SPAPR_DR_CONNECTOR_TYPE_PCI:
>> +        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) &&
>> +               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) &&
>> +               drc->configured && drc->signalled && !drc->awaiting_release);
>> +        break;
>> +    /* for LMB type */
>> +    case SPAPR_DR_CONNECTOR_TYPE_LMB:
>> +        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) &&
>> +               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) &&
>> +               drc->configured && drc->signalled && !drc->awaiting_release);
>> +        break;
> 
> What about CPU type?z

For CPU Type, those states don't change from source to host.

>> +    default:
>> +        ;
>> +    }
>> +
>> +    return rc;
>> +}
>> +
>> +/* detach_cb needs be set since it is not migrated */
>> +static void postmigrate_set_detach_cb(sPAPRDRConnector *drc,
>> +                                      spapr_drc_detach_cb *detach_cb)
>> +{
>> +    drc->detach_cb = detach_cb;
>> +}
>> +
>> +/* return the unique drc index as instance_id for qom interfaces*/
>> +static int get_instance_id(DeviceState *dev)
>> +{
>> +    return (int)get_index(SPAPR_DR_CONNECTOR(OBJECT(dev)));
>> +}
>> +
>> +static const VMStateDescription vmstate_spapr_drc = {
>> +    .name = "spapr_drc",
>> +    .version_id = 1,
>> +    .minimum_version_id = 1,
>> +    .needed = spapr_drc_needed,
>> +    .fields  = (VMStateField []) {
>> +        VMSTATE_UINT32(isolation_state, sPAPRDRConnector),
>> +        VMSTATE_UINT32(allocation_state, sPAPRDRConnector),
>> +        VMSTATE_UINT32(indicator_state, sPAPRDRConnector),
>> +        VMSTATE_BOOL(configured, sPAPRDRConnector),
>> +        VMSTATE_BOOL(awaiting_release, sPAPRDRConnector),
>> +        VMSTATE_BOOL(signalled, sPAPRDRConnector),
>> +        VMSTATE_END_OF_LIST()
>> +    }
>> +};
>> +
>>  static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
>>  {
>>      DeviceClass *dk = DEVICE_CLASS(k);
>> @@ -623,6 +688,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
>>      dk->reset = reset;
>>      dk->realize = realize;
>>      dk->unrealize = unrealize;
>> +    dk->vmsd = &vmstate_spapr_drc;
>> +    dk->dev_get_instance_id = get_instance_id;
>>      drck->set_isolation_state = set_isolation_state;
>>      drck->set_indicator_state = set_indicator_state;
>>      drck->set_allocation_state = set_allocation_state;
>> @@ -636,6 +703,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
>>      drck->detach = detach;
>>      drck->release_pending = release_pending;
>>      drck->set_signalled = set_signalled;
>> +    drck->postmigrate_set_detach_cb = postmigrate_set_detach_cb;
>> +
>>      /*
>>       * Reason: it crashes FIXME find and document the real reason
>>       */
>> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
>> index 4f00865..080471c 100644
>> --- a/hw/ppc/spapr_pci.c
>> +++ b/hw/ppc/spapr_pci.c
>> @@ -1594,11 +1594,33 @@ static void spapr_pci_pre_save(void *opaque)
>>      }
>>  }
>>  
>> +/*
>> + * detach_cb in the DRC state is a function pointer that cannot be
>> + * migrated. We set it right after migration so that a migrated
>> + * hot-unplug event could finish its work.
>> + */
>> +static void spapr_pci_set_detach_cb(PCIBus *bus, PCIDevice *pdev,
>> +                                 void *opaque)
>> +{
>> +    sPAPRPHBState *sphb = opaque;
>> +    sPAPRDRConnector *drc = spapr_phb_get_pci_drc(sphb, pdev);
>> +    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
>> +    drck->postmigrate_set_detach_cb(drc, spapr_phb_remove_pci_device_cb);
> 
> Why is spapr_phb_remove_pci_device_cb the right callback rather than
> something else?  This doesn't seem sensible.
> 
> More to the point, you're not restoring detach_cb_opaque, which means
> the detach_cb callback won't work properly anyway.
> 
If set_isolation_state/set_allocation_state is called on target without
spapr_phb_remove_pci_device being called earlier, drc->detach_cb is
null. Its value is spapr_phb_remove_pci_device_cb and is set in
spapr_phb_remove_pci_device.

You are right about detach_cb. It needs be restored.

>> +}
>> +
>>  static int spapr_pci_post_load(void *opaque, int version_id)
>>  {
>>      sPAPRPHBState *sphb = opaque;
>>      gpointer key, value;
>>      int i;
>> +    PCIBus *bus = PCI_HOST_BRIDGE(sphb)->bus;
>> +    unsigned int bus_no = 0;
>> +
>> +    /* Set detach_cb for the drc unconditionally after migration */
>> +    if (bus) {
>> +        pci_for_each_device(bus, pci_bus_num(bus), spapr_pci_set_detach_cb,
>> +                            &bus_no);
>> +    }
>>  
>>      for (i = 0; i < sphb->msi_devs_num; ++i) {
>>          key = g_memdup(&sphb->msi_devs[i].key,
>> diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h
>> index fa531d5..17589c8 100644
>> --- a/include/hw/ppc/spapr_drc.h
>> +++ b/include/hw/ppc/spapr_drc.h
>> @@ -192,6 +192,15 @@ typedef struct sPAPRDRConnectorClass {
>>                     void *detach_cb_opaque, Error **errp);
>>      bool (*release_pending)(sPAPRDRConnector *drc);
>>      void (*set_signalled)(sPAPRDRConnector *drc);
>> +
>> +    /*
>> +     * QEMU interface for setting detach_cb after migration.
>> +     * detach_cb in the DRC state is a function pointer that cannot be
>> +     * migrated. We set it right after migration so that a migrated
>> +     * hot-unplug event could finish its work.
>> +     */
>> +    void (*postmigrate_set_detach_cb)(sPAPRDRConnector *drc,
>> +                                      spapr_drc_detach_cb *detach_cb);
>>  } sPAPRDRConnectorClass;
>>  
>>  sPAPRDRConnector *spapr_dr_connector_new(Object *owner,
> 

Thanks,
Jianjun

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-07 16:32               ` Paolo Bonzini
@ 2016-10-07 17:25                 ` Jianjun Duan
  2016-10-07 17:34                   ` Dr. David Alan Gilbert
  0 siblings, 1 reply; 66+ messages in thread
From: Jianjun Duan @ 2016-10-07 17:25 UTC (permalink / raw)
  To: Paolo Bonzini, Dr. David Alan Gilbert
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst, david,
	veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth, aurelien,
	leon.alrae, blauwirbel, mark.cave-ayland, mdroth



On 10/07/2016 09:32 AM, Paolo Bonzini wrote:
> 
> 
> On 07/10/2016 18:31, Jianjun Duan wrote:
>>
>>
>> On 10/07/2016 07:34 AM, Dr. David Alan Gilbert wrote:
>>> * Paolo Bonzini (pbonzini@redhat.com) wrote:
>>>>
>>>>
>>>> On 06/10/2016 21:01, Dr. David Alan Gilbert wrote:
>>>>>>>> +                } else if (field->flags & VMS_LINKED) {
>>>>>>>> +                    ret = field->info->get(f, addr, size, field);
>>>>>>>>                  } else {
>>>>>>>>                      ret = field->info->get(f, addr, size, NULL);
>>>>>>>>  
>>>>>>>> @@ -193,6 +197,8 @@ static const char *vmfield_get_type_name(VMStateField *field)
>>>>>>>>  
>>>>>>>>      if (field->flags & VMS_STRUCT) {
>>>>>>>>          type = "struct";
>>>>>>>> +    } else if (field->flags & VMS_LINKED) {
>>>>>>>> +        type = "linked";
>>>>>>>>      } else if (field->info->name) {
>>>>>>>>          type = field->info->name;
>>>>>>>>      }
>>>>>>>> @@ -327,6 +333,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
>>>>>>>>                  }
>>>>>>>>                  if (field->flags & VMS_STRUCT) {
>>>>>>>>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
>>>>>>>> +                } else if  (field->flags & VMS_LINKED) {
>>>>>>>> +                    field->info->put(f, addr, size, field, vmdesc_loop);
>>>>>>>>                  } else {
>>>>>>>>                      field->info->put(f, addr, size, NULL, NULL);
>>>>>>>>                  }
>>>>
>>>> Is VMS_LINKED needed at all, since the fields are unused for every
>>>> VMStateInfo except qtailq?
>>>
>>> No, I think you could easily drop the VMS_LINKED and just always pass them in.
>>
>> It is needed if we want to use vmdesc_loop.
> 
> Just always pass it in, can't you?
> 
Could that lead to repetition of array elements? I know it depends on
individual put details.

Thanks,
Jianjun
> Paolo
> 

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-07 17:25                 ` Jianjun Duan
@ 2016-10-07 17:34                   ` Dr. David Alan Gilbert
  2016-10-07 17:43                     ` Jianjun Duan
  0 siblings, 1 reply; 66+ messages in thread
From: Dr. David Alan Gilbert @ 2016-10-07 17:34 UTC (permalink / raw)
  To: Jianjun Duan
  Cc: Paolo Bonzini, qemu-devel, qemu-ppc, dmitry, peter.maydell,
	kraxel, mst, david, veroniabahaa, quintela, amit.shah, mreitz,
	kwolf, rth, aurelien, leon.alrae, blauwirbel, mark.cave-ayland,
	mdroth

* Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> 
> 
> On 10/07/2016 09:32 AM, Paolo Bonzini wrote:
> > 
> > 
> > On 07/10/2016 18:31, Jianjun Duan wrote:
> >>
> >>
> >> On 10/07/2016 07:34 AM, Dr. David Alan Gilbert wrote:
> >>> * Paolo Bonzini (pbonzini@redhat.com) wrote:
> >>>>
> >>>>
> >>>> On 06/10/2016 21:01, Dr. David Alan Gilbert wrote:
> >>>>>>>> +                } else if (field->flags & VMS_LINKED) {
> >>>>>>>> +                    ret = field->info->get(f, addr, size, field);
> >>>>>>>>                  } else {
> >>>>>>>>                      ret = field->info->get(f, addr, size, NULL);
> >>>>>>>>  
> >>>>>>>> @@ -193,6 +197,8 @@ static const char *vmfield_get_type_name(VMStateField *field)
> >>>>>>>>  
> >>>>>>>>      if (field->flags & VMS_STRUCT) {
> >>>>>>>>          type = "struct";
> >>>>>>>> +    } else if (field->flags & VMS_LINKED) {
> >>>>>>>> +        type = "linked";
> >>>>>>>>      } else if (field->info->name) {
> >>>>>>>>          type = field->info->name;
> >>>>>>>>      }
> >>>>>>>> @@ -327,6 +333,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
> >>>>>>>>                  }
> >>>>>>>>                  if (field->flags & VMS_STRUCT) {
> >>>>>>>>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
> >>>>>>>> +                } else if  (field->flags & VMS_LINKED) {
> >>>>>>>> +                    field->info->put(f, addr, size, field, vmdesc_loop);
> >>>>>>>>                  } else {
> >>>>>>>>                      field->info->put(f, addr, size, NULL, NULL);
> >>>>>>>>                  }
> >>>>
> >>>> Is VMS_LINKED needed at all, since the fields are unused for every
> >>>> VMStateInfo except qtailq?
> >>>
> >>> No, I think you could easily drop the VMS_LINKED and just always pass them in.
> >>
> >> It is needed if we want to use vmdesc_loop.
> > 
> > Just always pass it in, can't you?
> > 
> Could that lead to repetition of array elements? I know it depends on
> individual put details.

I don't think so; Paolo is just suggesting replacing:

 +                } else if  (field->flags & VMS_LINKED) {
 +                    field->info->put(f, addr, size, field, vmdesc_loop);
                  } else {
                      field->info->put(f, addr, size, NULL, NULL);
                  }

by:

                  } else {
 -                    field->info->put(f, addr, size, NULL, NULL);
 +                    field->info->put(f, addr, size, field, vmdesc_loop);
                  }

most get/put won't use the field/vmdesc_loop so it wont matter.

Dave

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

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-07 17:34                   ` Dr. David Alan Gilbert
@ 2016-10-07 17:43                     ` Jianjun Duan
  2016-10-08 11:37                       ` Paolo Bonzini
  0 siblings, 1 reply; 66+ messages in thread
From: Jianjun Duan @ 2016-10-07 17:43 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Paolo Bonzini, qemu-devel, qemu-ppc, dmitry, peter.maydell,
	kraxel, mst, david, veroniabahaa, quintela, amit.shah, mreitz,
	kwolf, rth, aurelien, leon.alrae, blauwirbel, mark.cave-ayland,
	mdroth



On 10/07/2016 10:34 AM, Dr. David Alan Gilbert wrote:
> * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
>>
>>
>> On 10/07/2016 09:32 AM, Paolo Bonzini wrote:
>>>
>>>
>>> On 07/10/2016 18:31, Jianjun Duan wrote:
>>>>
>>>>
>>>> On 10/07/2016 07:34 AM, Dr. David Alan Gilbert wrote:
>>>>> * Paolo Bonzini (pbonzini@redhat.com) wrote:
>>>>>>
>>>>>>
>>>>>> On 06/10/2016 21:01, Dr. David Alan Gilbert wrote:
>>>>>>>>>> +                } else if (field->flags & VMS_LINKED) {
>>>>>>>>>> +                    ret = field->info->get(f, addr, size, field);
>>>>>>>>>>                  } else {
>>>>>>>>>>                      ret = field->info->get(f, addr, size, NULL);
>>>>>>>>>>  
>>>>>>>>>> @@ -193,6 +197,8 @@ static const char *vmfield_get_type_name(VMStateField *field)
>>>>>>>>>>  
>>>>>>>>>>      if (field->flags & VMS_STRUCT) {
>>>>>>>>>>          type = "struct";
>>>>>>>>>> +    } else if (field->flags & VMS_LINKED) {
>>>>>>>>>> +        type = "linked";
>>>>>>>>>>      } else if (field->info->name) {
>>>>>>>>>>          type = field->info->name;
>>>>>>>>>>      }
>>>>>>>>>> @@ -327,6 +333,8 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
>>>>>>>>>>                  }
>>>>>>>>>>                  if (field->flags & VMS_STRUCT) {
>>>>>>>>>>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
>>>>>>>>>> +                } else if  (field->flags & VMS_LINKED) {
>>>>>>>>>> +                    field->info->put(f, addr, size, field, vmdesc_loop);
>>>>>>>>>>                  } else {
>>>>>>>>>>                      field->info->put(f, addr, size, NULL, NULL);
>>>>>>>>>>                  }
>>>>>>
>>>>>> Is VMS_LINKED needed at all, since the fields are unused for every
>>>>>> VMStateInfo except qtailq?
>>>>>
>>>>> No, I think you could easily drop the VMS_LINKED and just always pass them in.
>>>>
>>>> It is needed if we want to use vmdesc_loop.
>>>
>>> Just always pass it in, can't you?
>>>
>> Could that lead to repetition of array elements? I know it depends on
>> individual put details.
> 
> I don't think so; Paolo is just suggesting replacing:
> 
>  +                } else if  (field->flags & VMS_LINKED) {
>  +                    field->info->put(f, addr, size, field, vmdesc_loop);
>                   } else {
>                       field->info->put(f, addr, size, NULL, NULL);
>                   }
> 
> by:
> 
>                   } else {
>  -                    field->info->put(f, addr, size, NULL, NULL);
>  +                    field->info->put(f, addr, size, field, vmdesc_loop);
>                   }
> 
> most get/put won't use the field/vmdesc_loop so it wont matter.
> 
> Dave
> 

Even though most put/get have no issues now, when somebody writes a new
put, he or she could run into issues if only checking the type
signature. It makes the code more readable.

I am OK either way.

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

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-07 16:35     ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
@ 2016-10-07 18:42       ` Dr. David Alan Gilbert
  2016-10-10  5:02         ` David Gibson
  0 siblings, 1 reply; 66+ messages in thread
From: Dr. David Alan Gilbert @ 2016-10-07 18:42 UTC (permalink / raw)
  To: Jianjun Duan
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst, david,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth

* Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> 
> 
> On 10/07/2016 05:08 AM, Dr. David Alan Gilbert wrote:
> > * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> >> Current migration code cannot handle some data structures such as
> >> QTAILQ in qemu/queue.h. Here we extend the signatures of put/get
> >> in VMStateInfo so that customized handling is supported.
> >>
> >> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
> >> ---
> >>  hw/net/vmxnet3.c            | 18 ++++++---
> >>  hw/nvram/eeprom93xx.c       |  6 ++-
> >>  hw/nvram/fw_cfg.c           |  6 ++-
> >>  hw/pci/msix.c               |  6 ++-
> >>  hw/pci/pci.c                | 12 ++++--
> >>  hw/pci/shpc.c               |  5 ++-
> >>  hw/scsi/scsi-bus.c          |  6 ++-
> >>  hw/timer/twl92230.c         |  6 ++-
> >>  hw/usb/redirect.c           | 18 ++++++---
> >>  hw/virtio/virtio-pci.c      |  6 ++-
> >>  hw/virtio/virtio.c          |  6 ++-
> >>  include/migration/vmstate.h | 10 +++--
> >>  migration/savevm.c          |  5 ++-
> >>  migration/vmstate.c         | 95 ++++++++++++++++++++++++++++-----------------
> >>  target-alpha/machine.c      |  5 ++-
> >>  target-arm/machine.c        | 12 ++++--
> >>  target-i386/machine.c       | 21 ++++++----
> >>  target-mips/machine.c       | 10 +++--
> >>  target-ppc/machine.c        | 10 +++--
> >>  target-sparc/machine.c      |  5 ++-
> >>  20 files changed, 171 insertions(+), 97 deletions(-)
> >>
> > 
> > <snip>
> > 
> >> diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
> >> index 444672a..2ca4b46 100644
> >> --- a/hw/usb/redirect.c
> >> +++ b/hw/usb/redirect.c
> >> @@ -2154,7 +2154,8 @@ static int usbredir_post_load(void *priv, int version_id)
> >>  }
> >>  
> >>  /* For usbredirparser migration */
> >> -static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
> >> +static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused,
> >> +                                void *opaque, QJSON *vmdesc)
> >>  {
> >>      USBRedirDevice *dev = priv;
> >>      uint8_t *data;
> >> @@ -2174,7 +2175,8 @@ static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
> >>      free(data);
> >>  }
> >>  
> >> -static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused)
> >> +static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused,
> >> +                               void *opaque)
> > 
> > Neither of these built for me; I had to change those to VMStateField rather than void *;
> > 
> > also is this series tested ontop of Halil's patches - because without them
> > I'm finding I also had to fix up most of the other virtio devices.
> > 
> > Dave
> 
> I built it on top of ppc-for-2.8 without problems. Is Hail's patch in
> ppc-for-2.8 yet?

I don't know about ppc-for-2.8;  patches for inclusion should work on the current
head unless stated otherwise.
Also, make sure you have the usbredir libraries installed and as much else as possible
to make sure you cover all the .get/.put functions - they're all over!

Dave

> Thanks,
> Jianjun
> 
> > 
> > 
> >>      USBRedirDevice *dev = priv;
> >>      uint8_t *data;
> >> @@ -2217,7 +2219,8 @@ static const VMStateInfo usbredir_parser_vmstate_info = {
> >>  
> >>  
> >>  /* For buffered packets (iso/irq) queue migration */
> >> -static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
> >> +static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused,
> >> +                               VMStateField *field, QJSON *vmdesc)
> >>  {
> >>      struct endp_data *endp = priv;
> >>      USBRedirDevice *dev = endp->dev;
> >> @@ -2237,7 +2240,8 @@ static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
> >>      assert(i == endp->bufpq_size);
> >>  }
> >>  
> >> -static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused)
> >> +static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused,
> >> +                              VMStateField *field)
> >>  {
> >>      struct endp_data *endp = priv;
> >>      USBRedirDevice *dev = endp->dev;
> >> @@ -2340,7 +2344,8 @@ static const VMStateDescription usbredir_ep_vmstate = {
> >>  
> >>  
> >>  /* For PacketIdQueue migration */
> >> -static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused)
> >> +static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused,
> >> +                                     VMStateField *field, QJSON *vmdesc)
> >>  {
> >>      struct PacketIdQueue *q = priv;
> >>      USBRedirDevice *dev = q->dev;
> >> @@ -2356,7 +2361,8 @@ static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused)
> >>      assert(remain == 0);
> >>  }
> >>  
> >> -static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused)
> >> +static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused,
> >> +                                    VMStateField *field)
> >>  {
> >>      struct PacketIdQueue *q = priv;
> >>      USBRedirDevice *dev = q->dev;
> >> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> >> index 2d60a00..38a7abd 100644
> >> --- a/hw/virtio/virtio-pci.c
> >> +++ b/hw/virtio/virtio-pci.c
> >> @@ -108,7 +108,8 @@ static bool virtio_pci_has_extra_state(DeviceState *d)
> >>      return proxy->flags & VIRTIO_PCI_FLAG_MIGRATE_EXTRA;
> >>  }
> >>  
> >> -static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size)
> >> +static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size,
> >> +                                       VMStateField *field)
> >>  {
> >>      VirtIOPCIProxy *proxy = pv;
> >>      int i;
> >> @@ -137,7 +138,8 @@ static void virtio_pci_save_modern_queue_state(VirtIOPCIQueue *vq,
> >>      qemu_put_be32(f, vq->used[1]);
> >>  }
> >>  
> >> -static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size)
> >> +static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size,
> >> +                                        VMStateField *field, QJSON *vmdesc)
> >>  {
> >>      VirtIOPCIProxy *proxy = pv;
> >>      int i;
> >> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> >> index 18ce333..ade2683 100644
> >> --- a/hw/virtio/virtio.c
> >> +++ b/hw/virtio/virtio.c
> >> @@ -1467,7 +1467,8 @@ static const VMStateDescription vmstate_virtio_ringsize = {
> >>      }
> >>  };
> >>  
> >> -static int get_extra_state(QEMUFile *f, void *pv, size_t size)
> >> +static int get_extra_state(QEMUFile *f, void *pv, size_t size,
> >> +                           VMStateField *field)
> >>  {
> >>      VirtIODevice *vdev = pv;
> >>      BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
> >> @@ -1480,7 +1481,8 @@ static int get_extra_state(QEMUFile *f, void *pv, size_t size)
> >>      }
> >>  }
> >>  
> >> -static void put_extra_state(QEMUFile *f, void *pv, size_t size)
> >> +static void put_extra_state(QEMUFile *f, void *pv, size_t size,
> >> +                            VMStateField *field, QJSON *vmdesc)
> >>  {
> >>      VirtIODevice *vdev = pv;
> >>      BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
> >> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
> >> index 1638ee5..459dd4a 100644
> >> --- a/include/migration/vmstate.h
> >> +++ b/include/migration/vmstate.h
> >> @@ -81,11 +81,13 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque);
> >>  
> >>  typedef struct VMStateInfo VMStateInfo;
> >>  typedef struct VMStateDescription VMStateDescription;
> >> +typedef struct VMStateField VMStateField;
> >>  
> >>  struct VMStateInfo {
> >>      const char *name;
> >> -    int (*get)(QEMUFile *f, void *pv, size_t size);
> >> -    void (*put)(QEMUFile *f, void *pv, size_t size);
> >> +    int (*get)(QEMUFile *f, void *pv, size_t size, VMStateField *field);
> >> +    void (*put)(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                QJSON *vmdesc);
> >>  };
> >>  
> >>  enum VMStateFlags {
> >> @@ -186,7 +188,7 @@ enum VMStateFlags {
> >>      VMS_MULTIPLY_ELEMENTS = 0x4000,
> >>  };
> >>  
> >> -typedef struct {
> >> +struct VMStateField {
> >>      const char *name;
> >>      size_t offset;
> >>      size_t size;
> >> @@ -199,7 +201,7 @@ typedef struct {
> >>      const VMStateDescription *vmsd;
> >>      int version_id;
> >>      bool (*field_exists)(void *opaque, int version_id);
> >> -} VMStateField;
> >> +};
> >>  
> >>  struct VMStateDescription {
> >>      const char *name;
> >> diff --git a/migration/savevm.c b/migration/savevm.c
> >> index ef5c3d1..13b53ad 100644
> >> --- a/migration/savevm.c
> >> +++ b/migration/savevm.c
> >> @@ -220,14 +220,15 @@ void timer_get(QEMUFile *f, QEMUTimer *ts)
> >>   * Not in vmstate.c to not add qemu-timer.c as dependency to vmstate.c
> >>   */
> >>  
> >> -static int get_timer(QEMUFile *f, void *pv, size_t size)
> >> +static int get_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      QEMUTimer *v = pv;
> >>      timer_get(f, v);
> >>      return 0;
> >>  }
> >>  
> >> -static void put_timer(QEMUFile *f, void *pv, size_t size)
> >> +static void put_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                QJSON *vmdesc)
> >>  {
> >>      QEMUTimer *v = pv;
> >>      timer_put(f, v);
> >> diff --git a/migration/vmstate.c b/migration/vmstate.c
> >> index fc29acf..66802cb 100644
> >> --- a/migration/vmstate.c
> >> +++ b/migration/vmstate.c
> >> @@ -122,7 +122,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
> >>                      ret = vmstate_load_state(f, field->vmsd, addr,
> >>                                               field->vmsd->version_id);
> >>                  } else {
> >> -                    ret = field->info->get(f, addr, size);
> >> +                    ret = field->info->get(f, addr, size, NULL);
> >>  
> >>                  }
> >>                  if (ret >= 0) {
> >> @@ -328,7 +328,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
> >>                  if (field->flags & VMS_STRUCT) {
> >>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
> >>                  } else {
> >> -                    field->info->put(f, addr, size);
> >> +                    field->info->put(f, addr, size, NULL, NULL);
> >>                  }
> >>  
> >>                  written_bytes = qemu_ftell_fast(f) - old_offset;
> >> @@ -461,14 +461,15 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
> >>  
> >>  /* bool */
> >>  
> >> -static int get_bool(QEMUFile *f, void *pv, size_t size)
> >> +static int get_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      bool *v = pv;
> >>      *v = qemu_get_byte(f);
> >>      return 0;
> >>  }
> >>  
> >> -static void put_bool(QEMUFile *f, void *pv, size_t size)
> >> +static void put_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                     QJSON *vmdesc)
> >>  {
> >>      bool *v = pv;
> >>      qemu_put_byte(f, *v);
> >> @@ -482,14 +483,15 @@ const VMStateInfo vmstate_info_bool = {
> >>  
> >>  /* 8 bit int */
> >>  
> >> -static int get_int8(QEMUFile *f, void *pv, size_t size)
> >> +static int get_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      int8_t *v = pv;
> >>      qemu_get_s8s(f, v);
> >>      return 0;
> >>  }
> >>  
> >> -static void put_int8(QEMUFile *f, void *pv, size_t size)
> >> +static void put_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                     QJSON *vmdesc)
> >>  {
> >>      int8_t *v = pv;
> >>      qemu_put_s8s(f, v);
> >> @@ -503,14 +505,15 @@ const VMStateInfo vmstate_info_int8 = {
> >>  
> >>  /* 16 bit int */
> >>  
> >> -static int get_int16(QEMUFile *f, void *pv, size_t size)
> >> +static int get_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      int16_t *v = pv;
> >>      qemu_get_sbe16s(f, v);
> >>      return 0;
> >>  }
> >>  
> >> -static void put_int16(QEMUFile *f, void *pv, size_t size)
> >> +static void put_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                      QJSON *vmdesc)
> >>  {
> >>      int16_t *v = pv;
> >>      qemu_put_sbe16s(f, v);
> >> @@ -524,14 +527,15 @@ const VMStateInfo vmstate_info_int16 = {
> >>  
> >>  /* 32 bit int */
> >>  
> >> -static int get_int32(QEMUFile *f, void *pv, size_t size)
> >> +static int get_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      int32_t *v = pv;
> >>      qemu_get_sbe32s(f, v);
> >>      return 0;
> >>  }
> >>  
> >> -static void put_int32(QEMUFile *f, void *pv, size_t size)
> >> +static void put_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                      QJSON *vmdesc)
> >>  {
> >>      int32_t *v = pv;
> >>      qemu_put_sbe32s(f, v);
> >> @@ -546,7 +550,8 @@ const VMStateInfo vmstate_info_int32 = {
> >>  /* 32 bit int. See that the received value is the same than the one
> >>     in the field */
> >>  
> >> -static int get_int32_equal(QEMUFile *f, void *pv, size_t size)
> >> +static int get_int32_equal(QEMUFile *f, void *pv, size_t size,
> >> +                           VMStateField *field)
> >>  {
> >>      int32_t *v = pv;
> >>      int32_t v2;
> >> @@ -568,7 +573,7 @@ const VMStateInfo vmstate_info_int32_equal = {
> >>   * and less than or equal to the one in the field.
> >>   */
> >>  
> >> -static int get_int32_le(QEMUFile *f, void *pv, size_t size)
> >> +static int get_int32_le(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      int32_t *cur = pv;
> >>      int32_t loaded;
> >> @@ -589,14 +594,15 @@ const VMStateInfo vmstate_info_int32_le = {
> >>  
> >>  /* 64 bit int */
> >>  
> >> -static int get_int64(QEMUFile *f, void *pv, size_t size)
> >> +static int get_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      int64_t *v = pv;
> >>      qemu_get_sbe64s(f, v);
> >>      return 0;
> >>  }
> >>  
> >> -static void put_int64(QEMUFile *f, void *pv, size_t size)
> >> +static void put_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                      QJSON *vmdesc)
> >>  {
> >>      int64_t *v = pv;
> >>      qemu_put_sbe64s(f, v);
> >> @@ -610,14 +616,15 @@ const VMStateInfo vmstate_info_int64 = {
> >>  
> >>  /* 8 bit unsigned int */
> >>  
> >> -static int get_uint8(QEMUFile *f, void *pv, size_t size)
> >> +static int get_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      uint8_t *v = pv;
> >>      qemu_get_8s(f, v);
> >>      return 0;
> >>  }
> >>  
> >> -static void put_uint8(QEMUFile *f, void *pv, size_t size)
> >> +static void put_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                      QJSON *vmdesc)
> >>  {
> >>      uint8_t *v = pv;
> >>      qemu_put_8s(f, v);
> >> @@ -631,14 +638,15 @@ const VMStateInfo vmstate_info_uint8 = {
> >>  
> >>  /* 16 bit unsigned int */
> >>  
> >> -static int get_uint16(QEMUFile *f, void *pv, size_t size)
> >> +static int get_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      uint16_t *v = pv;
> >>      qemu_get_be16s(f, v);
> >>      return 0;
> >>  }
> >>  
> >> -static void put_uint16(QEMUFile *f, void *pv, size_t size)
> >> +static void put_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                       QJSON *vmdesc)
> >>  {
> >>      uint16_t *v = pv;
> >>      qemu_put_be16s(f, v);
> >> @@ -652,14 +660,15 @@ const VMStateInfo vmstate_info_uint16 = {
> >>  
> >>  /* 32 bit unsigned int */
> >>  
> >> -static int get_uint32(QEMUFile *f, void *pv, size_t size)
> >> +static int get_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      uint32_t *v = pv;
> >>      qemu_get_be32s(f, v);
> >>      return 0;
> >>  }
> >>  
> >> -static void put_uint32(QEMUFile *f, void *pv, size_t size)
> >> +static void put_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                       QJSON *vmdesc)
> >>  {
> >>      uint32_t *v = pv;
> >>      qemu_put_be32s(f, v);
> >> @@ -674,7 +683,8 @@ const VMStateInfo vmstate_info_uint32 = {
> >>  /* 32 bit uint. See that the received value is the same than the one
> >>     in the field */
> >>  
> >> -static int get_uint32_equal(QEMUFile *f, void *pv, size_t size)
> >> +static int get_uint32_equal(QEMUFile *f, void *pv, size_t size,
> >> +                            VMStateField *field)
> >>  {
> >>      uint32_t *v = pv;
> >>      uint32_t v2;
> >> @@ -694,14 +704,15 @@ const VMStateInfo vmstate_info_uint32_equal = {
> >>  
> >>  /* 64 bit unsigned int */
> >>  
> >> -static int get_uint64(QEMUFile *f, void *pv, size_t size)
> >> +static int get_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      uint64_t *v = pv;
> >>      qemu_get_be64s(f, v);
> >>      return 0;
> >>  }
> >>  
> >> -static void put_uint64(QEMUFile *f, void *pv, size_t size)
> >> +static void put_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                       QJSON *vmdesc)
> >>  {
> >>      uint64_t *v = pv;
> >>      qemu_put_be64s(f, v);
> >> @@ -716,7 +727,8 @@ const VMStateInfo vmstate_info_uint64 = {
> >>  /* 64 bit unsigned int. See that the received value is the same than the one
> >>     in the field */
> >>  
> >> -static int get_uint64_equal(QEMUFile *f, void *pv, size_t size)
> >> +static int get_uint64_equal(QEMUFile *f, void *pv, size_t size,
> >> +                            VMStateField *field)
> >>  {
> >>      uint64_t *v = pv;
> >>      uint64_t v2;
> >> @@ -737,7 +749,8 @@ const VMStateInfo vmstate_info_uint64_equal = {
> >>  /* 8 bit int. See that the received value is the same than the one
> >>     in the field */
> >>  
> >> -static int get_uint8_equal(QEMUFile *f, void *pv, size_t size)
> >> +static int get_uint8_equal(QEMUFile *f, void *pv, size_t size,
> >> +                           VMStateField *field)
> >>  {
> >>      uint8_t *v = pv;
> >>      uint8_t v2;
> >> @@ -758,7 +771,8 @@ const VMStateInfo vmstate_info_uint8_equal = {
> >>  /* 16 bit unsigned int int. See that the received value is the same than the one
> >>     in the field */
> >>  
> >> -static int get_uint16_equal(QEMUFile *f, void *pv, size_t size)
> >> +static int get_uint16_equal(QEMUFile *f, void *pv, size_t size,
> >> +                            VMStateField *field)
> >>  {
> >>      uint16_t *v = pv;
> >>      uint16_t v2;
> >> @@ -778,7 +792,8 @@ const VMStateInfo vmstate_info_uint16_equal = {
> >>  
> >>  /* floating point */
> >>  
> >> -static int get_float64(QEMUFile *f, void *pv, size_t size)
> >> +static int get_float64(QEMUFile *f, void *pv, size_t size,
> >> +                       VMStateField *field)
> >>  {
> >>      float64 *v = pv;
> >>  
> >> @@ -786,7 +801,8 @@ static int get_float64(QEMUFile *f, void *pv, size_t size)
> >>      return 0;
> >>  }
> >>  
> >> -static void put_float64(QEMUFile *f, void *pv, size_t size)
> >> +static void put_float64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                        QJSON *vmdesc)
> >>  {
> >>      uint64_t *v = pv;
> >>  
> >> @@ -801,7 +817,8 @@ const VMStateInfo vmstate_info_float64 = {
> >>  
> >>  /* CPU_DoubleU type */
> >>  
> >> -static int get_cpudouble(QEMUFile *f, void *pv, size_t size)
> >> +static int get_cpudouble(QEMUFile *f, void *pv, size_t size,
> >> +                         VMStateField *field)
> >>  {
> >>      CPU_DoubleU *v = pv;
> >>      qemu_get_be32s(f, &v->l.upper);
> >> @@ -809,7 +826,8 @@ static int get_cpudouble(QEMUFile *f, void *pv, size_t size)
> >>      return 0;
> >>  }
> >>  
> >> -static void put_cpudouble(QEMUFile *f, void *pv, size_t size)
> >> +static void put_cpudouble(QEMUFile *f, void *pv, size_t size,
> >> +                          VMStateField *field, QJSON *vmdesc)
> >>  {
> >>      CPU_DoubleU *v = pv;
> >>      qemu_put_be32s(f, &v->l.upper);
> >> @@ -824,14 +842,16 @@ const VMStateInfo vmstate_info_cpudouble = {
> >>  
> >>  /* uint8_t buffers */
> >>  
> >> -static int get_buffer(QEMUFile *f, void *pv, size_t size)
> >> +static int get_buffer(QEMUFile *f, void *pv, size_t size,
> >> +                      VMStateField *field)
> >>  {
> >>      uint8_t *v = pv;
> >>      qemu_get_buffer(f, v, size);
> >>      return 0;
> >>  }
> >>  
> >> -static void put_buffer(QEMUFile *f, void *pv, size_t size)
> >> +static void put_buffer(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                       QJSON *vmdesc)
> >>  {
> >>      uint8_t *v = pv;
> >>      qemu_put_buffer(f, v, size);
> >> @@ -846,7 +866,8 @@ const VMStateInfo vmstate_info_buffer = {
> >>  /* unused buffers: space that was used for some fields that are
> >>     not useful anymore */
> >>  
> >> -static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
> >> +static int get_unused_buffer(QEMUFile *f, void *pv, size_t size,
> >> +                             VMStateField *field)
> >>  {
> >>      uint8_t buf[1024];
> >>      int block_len;
> >> @@ -859,7 +880,8 @@ static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
> >>     return 0;
> >>  }
> >>  
> >> -static void put_unused_buffer(QEMUFile *f, void *pv, size_t size)
> >> +static void put_unused_buffer(QEMUFile *f, void *pv, size_t size,
> >> +                              VMStateField *field, QJSON *vmdesc)
> >>  {
> >>      static const uint8_t buf[1024];
> >>      int block_len;
> >> @@ -884,7 +906,7 @@ const VMStateInfo vmstate_info_unused_buffer = {
> >>   */
> >>  /* This is the number of 64 bit words sent over the wire */
> >>  #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
> >> -static int get_bitmap(QEMUFile *f, void *pv, size_t size)
> >> +static int get_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      unsigned long *bmp = pv;
> >>      int i, idx = 0;
> >> @@ -898,7 +920,8 @@ static int get_bitmap(QEMUFile *f, void *pv, size_t size)
> >>      return 0;
> >>  }
> >>  
> >> -static void put_bitmap(QEMUFile *f, void *pv, size_t size)
> >> +static void put_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                QJSON *vmdesc)
> >>  {
> >>      unsigned long *bmp = pv;
> >>      int i, idx = 0;
> >> diff --git a/target-alpha/machine.c b/target-alpha/machine.c
> >> index 710b783..48e3278 100644
> >> --- a/target-alpha/machine.c
> >> +++ b/target-alpha/machine.c
> >> @@ -5,14 +5,15 @@
> >>  #include "hw/boards.h"
> >>  #include "migration/cpu.h"
> >>  
> >> -static int get_fpcr(QEMUFile *f, void *opaque, size_t size)
> >> +static int get_fpcr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
> >>  {
> >>      CPUAlphaState *env = opaque;
> >>      cpu_alpha_store_fpcr(env, qemu_get_be64(f));
> >>      return 0;
> >>  }
> >>  
> >> -static void put_fpcr(QEMUFile *f, void *opaque, size_t size)
> >> +static void put_fpcr(QEMUFile *f, void *opaque, size_t size,
> >> +                     VMStateField *field, QJSON *vmdesc)
> >>  {
> >>      CPUAlphaState *env = opaque;
> >>      qemu_put_be64(f, cpu_alpha_load_fpcr(env));
> >> diff --git a/target-arm/machine.c b/target-arm/machine.c
> >> index 7a6ca31..41a0de9 100644
> >> --- a/target-arm/machine.c
> >> +++ b/target-arm/machine.c
> >> @@ -17,7 +17,8 @@ static bool vfp_needed(void *opaque)
> >>      return arm_feature(env, ARM_FEATURE_VFP);
> >>  }
> >>  
> >> -static int get_fpscr(QEMUFile *f, void *opaque, size_t size)
> >> +static int get_fpscr(QEMUFile *f, void *opaque, size_t size,
> >> +                     VMStateField *field)
> >>  {
> >>      ARMCPU *cpu = opaque;
> >>      CPUARMState *env = &cpu->env;
> >> @@ -27,7 +28,8 @@ static int get_fpscr(QEMUFile *f, void *opaque, size_t size)
> >>      return 0;
> >>  }
> >>  
> >> -static void put_fpscr(QEMUFile *f, void *opaque, size_t size)
> >> +static void put_fpscr(QEMUFile *f, void *opaque, size_t size,
> >> +                      VMStateField *field, QJSON *vmdesc)
> >>  {
> >>      ARMCPU *cpu = opaque;
> >>      CPUARMState *env = &cpu->env;
> >> @@ -163,7 +165,8 @@ static const VMStateDescription vmstate_pmsav7 = {
> >>      }
> >>  };
> >>  
> >> -static int get_cpsr(QEMUFile *f, void *opaque, size_t size)
> >> +static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
> >> +                    VMStateField *field)
> >>  {
> >>      ARMCPU *cpu = opaque;
> >>      CPUARMState *env = &cpu->env;
> >> @@ -180,7 +183,8 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size)
> >>      return 0;
> >>  }
> >>  
> >> -static void put_cpsr(QEMUFile *f, void *opaque, size_t size)
> >> +static void put_cpsr(QEMUFile *f, void *opaque, size_t size,
> >> +                     VMStateField *field, QJSON *vmdesc)
> >>  {
> >>      ARMCPU *cpu = opaque;
> >>      CPUARMState *env = &cpu->env;
> >> diff --git a/target-i386/machine.c b/target-i386/machine.c
> >> index 71c0e4d..1df19e2 100644
> >> --- a/target-i386/machine.c
> >> +++ b/target-i386/machine.c
> >> @@ -139,7 +139,8 @@ static const VMStateDescription vmstate_mtrr_var = {
> >>  #define VMSTATE_MTRR_VARS(_field, _state, _n, _v)                    \
> >>      VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar)
> >>  
> >> -static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size)
> >> +static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size,
> >> +                            VMStateField *field, QJSON *vmdesc)
> >>  {
> >>      fprintf(stderr, "call put_fpreg() with invalid arguments\n");
> >>      exit(0);
> >> @@ -167,7 +168,8 @@ static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
> >>      p->exp = e;
> >>  }
> >>  
> >> -static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
> >> +static int get_fpreg(QEMUFile *f, void *opaque, size_t size,
> >> +                     VMStateField *field)
> >>  {
> >>      FPReg *fp_reg = opaque;
> >>      uint64_t mant;
> >> @@ -179,7 +181,8 @@ static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
> >>      return 0;
> >>  }
> >>  
> >> -static void put_fpreg(QEMUFile *f, void *opaque, size_t size)
> >> +static void put_fpreg(QEMUFile *f, void *opaque, size_t size,
> >> +                      VMStateField *field, QJSON *vmdesc)
> >>  {
> >>      FPReg *fp_reg = opaque;
> >>      uint64_t mant;
> >> @@ -197,7 +200,8 @@ static const VMStateInfo vmstate_fpreg = {
> >>      .put  = put_fpreg,
> >>  };
> >>  
> >> -static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size)
> >> +static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size,
> >> +                           VMStateField *field)
> >>  {
> >>      union x86_longdouble *p = opaque;
> >>      uint64_t mant;
> >> @@ -214,7 +218,8 @@ static const VMStateInfo vmstate_fpreg_1_mmx = {
> >>      .put  = put_fpreg_error,
> >>  };
> >>  
> >> -static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size)
> >> +static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size,
> >> +                              VMStateField *field)
> >>  {
> >>      union x86_longdouble *p = opaque;
> >>      uint64_t mant;
> >> @@ -276,14 +281,16 @@ static bool less_than_7(void *opaque, int version_id)
> >>      return version_id < 7;
> >>  }
> >>  
> >> -static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
> >> +static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size,
> >> +                                VMStateField *field)
> >>  {
> >>      uint64_t *v = pv;
> >>      *v = qemu_get_be32(f);
> >>      return 0;
> >>  }
> >>  
> >> -static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
> >> +static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size,
> >> +                                 VMStateField *field, QJSON *vmdesc)
> >>  {
> >>      uint64_t *v = pv;
> >>      qemu_put_be32(f, *v);
> >> diff --git a/target-mips/machine.c b/target-mips/machine.c
> >> index a27f2f1..179084c 100644
> >> --- a/target-mips/machine.c
> >> +++ b/target-mips/machine.c
> >> @@ -20,7 +20,7 @@ static int cpu_post_load(void *opaque, int version_id)
> >>  
> >>  /* FPU state */
> >>  
> >> -static int get_fpr(QEMUFile *f, void *pv, size_t size)
> >> +static int get_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      int i;
> >>      fpr_t *v = pv;
> >> @@ -31,7 +31,8 @@ static int get_fpr(QEMUFile *f, void *pv, size_t size)
> >>      return 0;
> >>  }
> >>  
> >> -static void put_fpr(QEMUFile *f, void *pv, size_t size)
> >> +static void put_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                    QJSON *vmdesc)
> >>  {
> >>      int i;
> >>      fpr_t *v = pv;
> >> @@ -125,7 +126,7 @@ const VMStateDescription vmstate_mvp = {
> >>  
> >>  /* TLB state */
> >>  
> >> -static int get_tlb(QEMUFile *f, void *pv, size_t size)
> >> +static int get_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      r4k_tlb_t *v = pv;
> >>      uint16_t flags;
> >> @@ -152,7 +153,8 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size)
> >>      return 0;
> >>  }
> >>  
> >> -static void put_tlb(QEMUFile *f, void *pv, size_t size)
> >> +static void put_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                    QJSON *vmdesc)
> >>  {
> >>      r4k_tlb_t *v = pv;
> >>  
> >> diff --git a/target-ppc/machine.c b/target-ppc/machine.c
> >> index 4820f22..0e1822c 100644
> >> --- a/target-ppc/machine.c
> >> +++ b/target-ppc/machine.c
> >> @@ -106,7 +106,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
> >>      return 0;
> >>  }
> >>  
> >> -static int get_avr(QEMUFile *f, void *pv, size_t size)
> >> +static int get_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      ppc_avr_t *v = pv;
> >>  
> >> @@ -116,7 +116,8 @@ static int get_avr(QEMUFile *f, void *pv, size_t size)
> >>      return 0;
> >>  }
> >>  
> >> -static void put_avr(QEMUFile *f, void *pv, size_t size)
> >> +static void put_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                    QJSON *vmdesc)
> >>  {
> >>      ppc_avr_t *v = pv;
> >>  
> >> @@ -324,7 +325,7 @@ static const VMStateDescription vmstate_sr = {
> >>  };
> >>  
> >>  #ifdef TARGET_PPC64
> >> -static int get_slbe(QEMUFile *f, void *pv, size_t size)
> >> +static int get_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> >>  {
> >>      ppc_slb_t *v = pv;
> >>  
> >> @@ -334,7 +335,8 @@ static int get_slbe(QEMUFile *f, void *pv, size_t size)
> >>      return 0;
> >>  }
> >>  
> >> -static void put_slbe(QEMUFile *f, void *pv, size_t size)
> >> +static void put_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> >> +                     QJSON *vmdesc)
> >>  {
> >>      ppc_slb_t *v = pv;
> >>  
> >> diff --git a/target-sparc/machine.c b/target-sparc/machine.c
> >> index 59c92f7..3194e03 100644
> >> --- a/target-sparc/machine.c
> >> +++ b/target-sparc/machine.c
> >> @@ -59,7 +59,7 @@ static const VMStateDescription vmstate_tlb_entry = {
> >>  };
> >>  #endif
> >>  
> >> -static int get_psr(QEMUFile *f, void *opaque, size_t size)
> >> +static int get_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
> >>  {
> >>      SPARCCPU *cpu = opaque;
> >>      CPUSPARCState *env = &cpu->env;
> >> @@ -72,7 +72,8 @@ static int get_psr(QEMUFile *f, void *opaque, size_t size)
> >>      return 0;
> >>  }
> >>  
> >> -static void put_psr(QEMUFile *f, void *opaque, size_t size)
> >> +static void put_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field,
> >> +                QJSON *vmdesc)
> >>  {
> >>      SPARCCPU *cpu = opaque;
> >>      CPUSPARCState *env = &cpu->env;
> >> -- 
> >> 1.9.1
> >>
> >>
> > --
> > Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
> > 
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-07 17:43                     ` Jianjun Duan
@ 2016-10-08 11:37                       ` Paolo Bonzini
  2016-10-08 19:28                         ` Halil Pasic
  0 siblings, 1 reply; 66+ messages in thread
From: Paolo Bonzini @ 2016-10-08 11:37 UTC (permalink / raw)
  To: Jianjun Duan, Dr. David Alan Gilbert
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst, david,
	veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth, aurelien,
	leon.alrae, blauwirbel, mark.cave-ayland, mdroth



On 07/10/2016 19:43, Jianjun Duan wrote:
> Even though most put/get have no issues now, when somebody writes a new
> put, he or she could run into issues if only checking the type
> signature. It makes the code more readable.

No, it doesn't because one is left wondering what is VMS_LINKED about.
What is the relation between linked datastructures and passing some
arguments as NULL/noon-NULL?

When somebody writes a new get/put, they'll make an informed choice on
what arguments they need. :)

Paolo

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-08 11:37                       ` Paolo Bonzini
@ 2016-10-08 19:28                         ` Halil Pasic
  2016-10-10 21:29                           ` Jianjun Duan
  2016-10-10 21:40                           ` Jianjun Duan
  0 siblings, 2 replies; 66+ messages in thread
From: Halil Pasic @ 2016-10-08 19:28 UTC (permalink / raw)
  To: Paolo Bonzini, Jianjun Duan, Dr. David Alan Gilbert
  Cc: veroniabahaa, peter.maydell, mdroth, mst, quintela,
	mark.cave-ayland, qemu-devel, mreitz, blauwirbel, amit.shah,
	qemu-ppc, kraxel, dmitry, kwolf, rth, leon.alrae, aurelien,
	david

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



On 10/08/2016 01:37 PM, Paolo Bonzini wrote:
>> Even though most put/get have no issues now, when somebody writes a new
>> > put, he or she could run into issues if only checking the type
>> > signature. It makes the code more readable.

> No, it doesn't because one is left wondering what is VMS_LINKED about.

I agree with Paolo. IMHO VMS_LINKED is conceptually difficult in  a sense
that it's quite different that what we have currently. I have the feeling,
conceptually, we are trying to fit in something like data structures with a
type parameter (the element type) here. AFAIU what vmstate currently can is
directed acyclic graphs of certain stuff (and also completely custom
handling based on custom put/get).

> What is the relation between linked datastructures and passing some
> arguments as NULL/noon-NULL?

IFAIU we need those for the datastructure because it's linked and has
a type parameter (element type). The two last arguments are for
the element type. These were added by the previous patch because
the old VMStateInfo did not need these. So we drastically changed
the scope of VMStateInfo with the previous patch and I'm not
sure I like this.

I will have to stare at this a bit longer to bring something more
constructive than these (largely feeling-based) remarks.

Cheers,
Halil


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

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-07 18:42       ` Dr. David Alan Gilbert
@ 2016-10-10  5:02         ` David Gibson
  0 siblings, 0 replies; 66+ messages in thread
From: David Gibson @ 2016-10-10  5:02 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Jianjun Duan, qemu-devel, qemu-ppc, dmitry, peter.maydell,
	kraxel, mst, pbonzini, veroniabahaa, quintela, amit.shah, mreitz,
	kwolf, rth, aurelien, leon.alrae, blauwirbel, mark.cave-ayland,
	mdroth

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

On Fri, Oct 07, 2016 at 07:42:12PM +0100, Dr. David Alan Gilbert wrote:
> * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> > 
> > 
> > On 10/07/2016 05:08 AM, Dr. David Alan Gilbert wrote:
> > > * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> > >> Current migration code cannot handle some data structures such as
> > >> QTAILQ in qemu/queue.h. Here we extend the signatures of put/get
> > >> in VMStateInfo so that customized handling is supported.
> > >>
> > >> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
> > >> ---
> > >>  hw/net/vmxnet3.c            | 18 ++++++---
> > >>  hw/nvram/eeprom93xx.c       |  6 ++-
> > >>  hw/nvram/fw_cfg.c           |  6 ++-
> > >>  hw/pci/msix.c               |  6 ++-
> > >>  hw/pci/pci.c                | 12 ++++--
> > >>  hw/pci/shpc.c               |  5 ++-
> > >>  hw/scsi/scsi-bus.c          |  6 ++-
> > >>  hw/timer/twl92230.c         |  6 ++-
> > >>  hw/usb/redirect.c           | 18 ++++++---
> > >>  hw/virtio/virtio-pci.c      |  6 ++-
> > >>  hw/virtio/virtio.c          |  6 ++-
> > >>  include/migration/vmstate.h | 10 +++--
> > >>  migration/savevm.c          |  5 ++-
> > >>  migration/vmstate.c         | 95 ++++++++++++++++++++++++++++-----------------
> > >>  target-alpha/machine.c      |  5 ++-
> > >>  target-arm/machine.c        | 12 ++++--
> > >>  target-i386/machine.c       | 21 ++++++----
> > >>  target-mips/machine.c       | 10 +++--
> > >>  target-ppc/machine.c        | 10 +++--
> > >>  target-sparc/machine.c      |  5 ++-
> > >>  20 files changed, 171 insertions(+), 97 deletions(-)
> > >>
> > > 
> > > <snip>
> > > 
> > >> diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
> > >> index 444672a..2ca4b46 100644
> > >> --- a/hw/usb/redirect.c
> > >> +++ b/hw/usb/redirect.c
> > >> @@ -2154,7 +2154,8 @@ static int usbredir_post_load(void *priv, int version_id)
> > >>  }
> > >>  
> > >>  /* For usbredirparser migration */
> > >> -static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
> > >> +static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused,
> > >> +                                void *opaque, QJSON *vmdesc)
> > >>  {
> > >>      USBRedirDevice *dev = priv;
> > >>      uint8_t *data;
> > >> @@ -2174,7 +2175,8 @@ static void usbredir_put_parser(QEMUFile *f, void *priv, size_t unused)
> > >>      free(data);
> > >>  }
> > >>  
> > >> -static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused)
> > >> +static int usbredir_get_parser(QEMUFile *f, void *priv, size_t unused,
> > >> +                               void *opaque)
> > > 
> > > Neither of these built for me; I had to change those to VMStateField rather than void *;
> > > 
> > > also is this series tested ontop of Halil's patches - because without them
> > > I'm finding I also had to fix up most of the other virtio devices.
> > > 
> > > Dave
> > 
> > I built it on top of ppc-for-2.8 without problems. Is Hail's patch in
> > ppc-for-2.8 yet?

If it's not in master, and not ppc specific, it won't be in ppc-for-2.8.

> I don't know about ppc-for-2.8;  patches for inclusion should work on the current
> head unless stated otherwise.

Right.  These started as ppc specific patches, for which being on top
of ppc-for-2.8 would be the right choice (ppc-for-2.8 regularly
rebases on master).  However, they now include a bunch of generic
migration changes, it should be done directly against master.  This
may require splitting the series into generic and ppc specific
portions.

> Also, make sure you have the usbredir libraries installed and as much else as possible
> to make sure you cover all the .get/.put functions - they're all over!
> 
> Dave
> 
> > Thanks,
> > Jianjun
> > 
> > > 
> > > 
> > >>      USBRedirDevice *dev = priv;
> > >>      uint8_t *data;
> > >> @@ -2217,7 +2219,8 @@ static const VMStateInfo usbredir_parser_vmstate_info = {
> > >>  
> > >>  
> > >>  /* For buffered packets (iso/irq) queue migration */
> > >> -static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
> > >> +static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused,
> > >> +                               VMStateField *field, QJSON *vmdesc)
> > >>  {
> > >>      struct endp_data *endp = priv;
> > >>      USBRedirDevice *dev = endp->dev;
> > >> @@ -2237,7 +2240,8 @@ static void usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused)
> > >>      assert(i == endp->bufpq_size);
> > >>  }
> > >>  
> > >> -static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused)
> > >> +static int usbredir_get_bufpq(QEMUFile *f, void *priv, size_t unused,
> > >> +                              VMStateField *field)
> > >>  {
> > >>      struct endp_data *endp = priv;
> > >>      USBRedirDevice *dev = endp->dev;
> > >> @@ -2340,7 +2344,8 @@ static const VMStateDescription usbredir_ep_vmstate = {
> > >>  
> > >>  
> > >>  /* For PacketIdQueue migration */
> > >> -static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused)
> > >> +static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused,
> > >> +                                     VMStateField *field, QJSON *vmdesc)
> > >>  {
> > >>      struct PacketIdQueue *q = priv;
> > >>      USBRedirDevice *dev = q->dev;
> > >> @@ -2356,7 +2361,8 @@ static void usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused)
> > >>      assert(remain == 0);
> > >>  }
> > >>  
> > >> -static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused)
> > >> +static int usbredir_get_packet_id_q(QEMUFile *f, void *priv, size_t unused,
> > >> +                                    VMStateField *field)
> > >>  {
> > >>      struct PacketIdQueue *q = priv;
> > >>      USBRedirDevice *dev = q->dev;
> > >> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> > >> index 2d60a00..38a7abd 100644
> > >> --- a/hw/virtio/virtio-pci.c
> > >> +++ b/hw/virtio/virtio-pci.c
> > >> @@ -108,7 +108,8 @@ static bool virtio_pci_has_extra_state(DeviceState *d)
> > >>      return proxy->flags & VIRTIO_PCI_FLAG_MIGRATE_EXTRA;
> > >>  }
> > >>  
> > >> -static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size,
> > >> +                                       VMStateField *field)
> > >>  {
> > >>      VirtIOPCIProxy *proxy = pv;
> > >>      int i;
> > >> @@ -137,7 +138,8 @@ static void virtio_pci_save_modern_queue_state(VirtIOPCIQueue *vq,
> > >>      qemu_put_be32(f, vq->used[1]);
> > >>  }
> > >>  
> > >> -static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_virtio_pci_modern_state(QEMUFile *f, void *pv, size_t size,
> > >> +                                        VMStateField *field, QJSON *vmdesc)
> > >>  {
> > >>      VirtIOPCIProxy *proxy = pv;
> > >>      int i;
> > >> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> > >> index 18ce333..ade2683 100644
> > >> --- a/hw/virtio/virtio.c
> > >> +++ b/hw/virtio/virtio.c
> > >> @@ -1467,7 +1467,8 @@ static const VMStateDescription vmstate_virtio_ringsize = {
> > >>      }
> > >>  };
> > >>  
> > >> -static int get_extra_state(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_extra_state(QEMUFile *f, void *pv, size_t size,
> > >> +                           VMStateField *field)
> > >>  {
> > >>      VirtIODevice *vdev = pv;
> > >>      BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
> > >> @@ -1480,7 +1481,8 @@ static int get_extra_state(QEMUFile *f, void *pv, size_t size)
> > >>      }
> > >>  }
> > >>  
> > >> -static void put_extra_state(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_extra_state(QEMUFile *f, void *pv, size_t size,
> > >> +                            VMStateField *field, QJSON *vmdesc)
> > >>  {
> > >>      VirtIODevice *vdev = pv;
> > >>      BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
> > >> diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
> > >> index 1638ee5..459dd4a 100644
> > >> --- a/include/migration/vmstate.h
> > >> +++ b/include/migration/vmstate.h
> > >> @@ -81,11 +81,13 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque);
> > >>  
> > >>  typedef struct VMStateInfo VMStateInfo;
> > >>  typedef struct VMStateDescription VMStateDescription;
> > >> +typedef struct VMStateField VMStateField;
> > >>  
> > >>  struct VMStateInfo {
> > >>      const char *name;
> > >> -    int (*get)(QEMUFile *f, void *pv, size_t size);
> > >> -    void (*put)(QEMUFile *f, void *pv, size_t size);
> > >> +    int (*get)(QEMUFile *f, void *pv, size_t size, VMStateField *field);
> > >> +    void (*put)(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                QJSON *vmdesc);
> > >>  };
> > >>  
> > >>  enum VMStateFlags {
> > >> @@ -186,7 +188,7 @@ enum VMStateFlags {
> > >>      VMS_MULTIPLY_ELEMENTS = 0x4000,
> > >>  };
> > >>  
> > >> -typedef struct {
> > >> +struct VMStateField {
> > >>      const char *name;
> > >>      size_t offset;
> > >>      size_t size;
> > >> @@ -199,7 +201,7 @@ typedef struct {
> > >>      const VMStateDescription *vmsd;
> > >>      int version_id;
> > >>      bool (*field_exists)(void *opaque, int version_id);
> > >> -} VMStateField;
> > >> +};
> > >>  
> > >>  struct VMStateDescription {
> > >>      const char *name;
> > >> diff --git a/migration/savevm.c b/migration/savevm.c
> > >> index ef5c3d1..13b53ad 100644
> > >> --- a/migration/savevm.c
> > >> +++ b/migration/savevm.c
> > >> @@ -220,14 +220,15 @@ void timer_get(QEMUFile *f, QEMUTimer *ts)
> > >>   * Not in vmstate.c to not add qemu-timer.c as dependency to vmstate.c
> > >>   */
> > >>  
> > >> -static int get_timer(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      QEMUTimer *v = pv;
> > >>      timer_get(f, v);
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_timer(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_timer(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                QJSON *vmdesc)
> > >>  {
> > >>      QEMUTimer *v = pv;
> > >>      timer_put(f, v);
> > >> diff --git a/migration/vmstate.c b/migration/vmstate.c
> > >> index fc29acf..66802cb 100644
> > >> --- a/migration/vmstate.c
> > >> +++ b/migration/vmstate.c
> > >> @@ -122,7 +122,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
> > >>                      ret = vmstate_load_state(f, field->vmsd, addr,
> > >>                                               field->vmsd->version_id);
> > >>                  } else {
> > >> -                    ret = field->info->get(f, addr, size);
> > >> +                    ret = field->info->get(f, addr, size, NULL);
> > >>  
> > >>                  }
> > >>                  if (ret >= 0) {
> > >> @@ -328,7 +328,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
> > >>                  if (field->flags & VMS_STRUCT) {
> > >>                      vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
> > >>                  } else {
> > >> -                    field->info->put(f, addr, size);
> > >> +                    field->info->put(f, addr, size, NULL, NULL);
> > >>                  }
> > >>  
> > >>                  written_bytes = qemu_ftell_fast(f) - old_offset;
> > >> @@ -461,14 +461,15 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
> > >>  
> > >>  /* bool */
> > >>  
> > >> -static int get_bool(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      bool *v = pv;
> > >>      *v = qemu_get_byte(f);
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_bool(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                     QJSON *vmdesc)
> > >>  {
> > >>      bool *v = pv;
> > >>      qemu_put_byte(f, *v);
> > >> @@ -482,14 +483,15 @@ const VMStateInfo vmstate_info_bool = {
> > >>  
> > >>  /* 8 bit int */
> > >>  
> > >> -static int get_int8(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      int8_t *v = pv;
> > >>      qemu_get_s8s(f, v);
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_int8(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                     QJSON *vmdesc)
> > >>  {
> > >>      int8_t *v = pv;
> > >>      qemu_put_s8s(f, v);
> > >> @@ -503,14 +505,15 @@ const VMStateInfo vmstate_info_int8 = {
> > >>  
> > >>  /* 16 bit int */
> > >>  
> > >> -static int get_int16(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      int16_t *v = pv;
> > >>      qemu_get_sbe16s(f, v);
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_int16(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                      QJSON *vmdesc)
> > >>  {
> > >>      int16_t *v = pv;
> > >>      qemu_put_sbe16s(f, v);
> > >> @@ -524,14 +527,15 @@ const VMStateInfo vmstate_info_int16 = {
> > >>  
> > >>  /* 32 bit int */
> > >>  
> > >> -static int get_int32(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      int32_t *v = pv;
> > >>      qemu_get_sbe32s(f, v);
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_int32(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                      QJSON *vmdesc)
> > >>  {
> > >>      int32_t *v = pv;
> > >>      qemu_put_sbe32s(f, v);
> > >> @@ -546,7 +550,8 @@ const VMStateInfo vmstate_info_int32 = {
> > >>  /* 32 bit int. See that the received value is the same than the one
> > >>     in the field */
> > >>  
> > >> -static int get_int32_equal(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_int32_equal(QEMUFile *f, void *pv, size_t size,
> > >> +                           VMStateField *field)
> > >>  {
> > >>      int32_t *v = pv;
> > >>      int32_t v2;
> > >> @@ -568,7 +573,7 @@ const VMStateInfo vmstate_info_int32_equal = {
> > >>   * and less than or equal to the one in the field.
> > >>   */
> > >>  
> > >> -static int get_int32_le(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_int32_le(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      int32_t *cur = pv;
> > >>      int32_t loaded;
> > >> @@ -589,14 +594,15 @@ const VMStateInfo vmstate_info_int32_le = {
> > >>  
> > >>  /* 64 bit int */
> > >>  
> > >> -static int get_int64(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      int64_t *v = pv;
> > >>      qemu_get_sbe64s(f, v);
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_int64(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                      QJSON *vmdesc)
> > >>  {
> > >>      int64_t *v = pv;
> > >>      qemu_put_sbe64s(f, v);
> > >> @@ -610,14 +616,15 @@ const VMStateInfo vmstate_info_int64 = {
> > >>  
> > >>  /* 8 bit unsigned int */
> > >>  
> > >> -static int get_uint8(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      uint8_t *v = pv;
> > >>      qemu_get_8s(f, v);
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_uint8(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                      QJSON *vmdesc)
> > >>  {
> > >>      uint8_t *v = pv;
> > >>      qemu_put_8s(f, v);
> > >> @@ -631,14 +638,15 @@ const VMStateInfo vmstate_info_uint8 = {
> > >>  
> > >>  /* 16 bit unsigned int */
> > >>  
> > >> -static int get_uint16(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      uint16_t *v = pv;
> > >>      qemu_get_be16s(f, v);
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_uint16(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                       QJSON *vmdesc)
> > >>  {
> > >>      uint16_t *v = pv;
> > >>      qemu_put_be16s(f, v);
> > >> @@ -652,14 +660,15 @@ const VMStateInfo vmstate_info_uint16 = {
> > >>  
> > >>  /* 32 bit unsigned int */
> > >>  
> > >> -static int get_uint32(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      uint32_t *v = pv;
> > >>      qemu_get_be32s(f, v);
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_uint32(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                       QJSON *vmdesc)
> > >>  {
> > >>      uint32_t *v = pv;
> > >>      qemu_put_be32s(f, v);
> > >> @@ -674,7 +683,8 @@ const VMStateInfo vmstate_info_uint32 = {
> > >>  /* 32 bit uint. See that the received value is the same than the one
> > >>     in the field */
> > >>  
> > >> -static int get_uint32_equal(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_uint32_equal(QEMUFile *f, void *pv, size_t size,
> > >> +                            VMStateField *field)
> > >>  {
> > >>      uint32_t *v = pv;
> > >>      uint32_t v2;
> > >> @@ -694,14 +704,15 @@ const VMStateInfo vmstate_info_uint32_equal = {
> > >>  
> > >>  /* 64 bit unsigned int */
> > >>  
> > >> -static int get_uint64(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      uint64_t *v = pv;
> > >>      qemu_get_be64s(f, v);
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_uint64(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                       QJSON *vmdesc)
> > >>  {
> > >>      uint64_t *v = pv;
> > >>      qemu_put_be64s(f, v);
> > >> @@ -716,7 +727,8 @@ const VMStateInfo vmstate_info_uint64 = {
> > >>  /* 64 bit unsigned int. See that the received value is the same than the one
> > >>     in the field */
> > >>  
> > >> -static int get_uint64_equal(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_uint64_equal(QEMUFile *f, void *pv, size_t size,
> > >> +                            VMStateField *field)
> > >>  {
> > >>      uint64_t *v = pv;
> > >>      uint64_t v2;
> > >> @@ -737,7 +749,8 @@ const VMStateInfo vmstate_info_uint64_equal = {
> > >>  /* 8 bit int. See that the received value is the same than the one
> > >>     in the field */
> > >>  
> > >> -static int get_uint8_equal(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_uint8_equal(QEMUFile *f, void *pv, size_t size,
> > >> +                           VMStateField *field)
> > >>  {
> > >>      uint8_t *v = pv;
> > >>      uint8_t v2;
> > >> @@ -758,7 +771,8 @@ const VMStateInfo vmstate_info_uint8_equal = {
> > >>  /* 16 bit unsigned int int. See that the received value is the same than the one
> > >>     in the field */
> > >>  
> > >> -static int get_uint16_equal(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_uint16_equal(QEMUFile *f, void *pv, size_t size,
> > >> +                            VMStateField *field)
> > >>  {
> > >>      uint16_t *v = pv;
> > >>      uint16_t v2;
> > >> @@ -778,7 +792,8 @@ const VMStateInfo vmstate_info_uint16_equal = {
> > >>  
> > >>  /* floating point */
> > >>  
> > >> -static int get_float64(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_float64(QEMUFile *f, void *pv, size_t size,
> > >> +                       VMStateField *field)
> > >>  {
> > >>      float64 *v = pv;
> > >>  
> > >> @@ -786,7 +801,8 @@ static int get_float64(QEMUFile *f, void *pv, size_t size)
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_float64(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_float64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                        QJSON *vmdesc)
> > >>  {
> > >>      uint64_t *v = pv;
> > >>  
> > >> @@ -801,7 +817,8 @@ const VMStateInfo vmstate_info_float64 = {
> > >>  
> > >>  /* CPU_DoubleU type */
> > >>  
> > >> -static int get_cpudouble(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_cpudouble(QEMUFile *f, void *pv, size_t size,
> > >> +                         VMStateField *field)
> > >>  {
> > >>      CPU_DoubleU *v = pv;
> > >>      qemu_get_be32s(f, &v->l.upper);
> > >> @@ -809,7 +826,8 @@ static int get_cpudouble(QEMUFile *f, void *pv, size_t size)
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_cpudouble(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_cpudouble(QEMUFile *f, void *pv, size_t size,
> > >> +                          VMStateField *field, QJSON *vmdesc)
> > >>  {
> > >>      CPU_DoubleU *v = pv;
> > >>      qemu_put_be32s(f, &v->l.upper);
> > >> @@ -824,14 +842,16 @@ const VMStateInfo vmstate_info_cpudouble = {
> > >>  
> > >>  /* uint8_t buffers */
> > >>  
> > >> -static int get_buffer(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_buffer(QEMUFile *f, void *pv, size_t size,
> > >> +                      VMStateField *field)
> > >>  {
> > >>      uint8_t *v = pv;
> > >>      qemu_get_buffer(f, v, size);
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_buffer(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_buffer(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                       QJSON *vmdesc)
> > >>  {
> > >>      uint8_t *v = pv;
> > >>      qemu_put_buffer(f, v, size);
> > >> @@ -846,7 +866,8 @@ const VMStateInfo vmstate_info_buffer = {
> > >>  /* unused buffers: space that was used for some fields that are
> > >>     not useful anymore */
> > >>  
> > >> -static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_unused_buffer(QEMUFile *f, void *pv, size_t size,
> > >> +                             VMStateField *field)
> > >>  {
> > >>      uint8_t buf[1024];
> > >>      int block_len;
> > >> @@ -859,7 +880,8 @@ static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
> > >>     return 0;
> > >>  }
> > >>  
> > >> -static void put_unused_buffer(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_unused_buffer(QEMUFile *f, void *pv, size_t size,
> > >> +                              VMStateField *field, QJSON *vmdesc)
> > >>  {
> > >>      static const uint8_t buf[1024];
> > >>      int block_len;
> > >> @@ -884,7 +906,7 @@ const VMStateInfo vmstate_info_unused_buffer = {
> > >>   */
> > >>  /* This is the number of 64 bit words sent over the wire */
> > >>  #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
> > >> -static int get_bitmap(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      unsigned long *bmp = pv;
> > >>      int i, idx = 0;
> > >> @@ -898,7 +920,8 @@ static int get_bitmap(QEMUFile *f, void *pv, size_t size)
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_bitmap(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                QJSON *vmdesc)
> > >>  {
> > >>      unsigned long *bmp = pv;
> > >>      int i, idx = 0;
> > >> diff --git a/target-alpha/machine.c b/target-alpha/machine.c
> > >> index 710b783..48e3278 100644
> > >> --- a/target-alpha/machine.c
> > >> +++ b/target-alpha/machine.c
> > >> @@ -5,14 +5,15 @@
> > >>  #include "hw/boards.h"
> > >>  #include "migration/cpu.h"
> > >>  
> > >> -static int get_fpcr(QEMUFile *f, void *opaque, size_t size)
> > >> +static int get_fpcr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
> > >>  {
> > >>      CPUAlphaState *env = opaque;
> > >>      cpu_alpha_store_fpcr(env, qemu_get_be64(f));
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_fpcr(QEMUFile *f, void *opaque, size_t size)
> > >> +static void put_fpcr(QEMUFile *f, void *opaque, size_t size,
> > >> +                     VMStateField *field, QJSON *vmdesc)
> > >>  {
> > >>      CPUAlphaState *env = opaque;
> > >>      qemu_put_be64(f, cpu_alpha_load_fpcr(env));
> > >> diff --git a/target-arm/machine.c b/target-arm/machine.c
> > >> index 7a6ca31..41a0de9 100644
> > >> --- a/target-arm/machine.c
> > >> +++ b/target-arm/machine.c
> > >> @@ -17,7 +17,8 @@ static bool vfp_needed(void *opaque)
> > >>      return arm_feature(env, ARM_FEATURE_VFP);
> > >>  }
> > >>  
> > >> -static int get_fpscr(QEMUFile *f, void *opaque, size_t size)
> > >> +static int get_fpscr(QEMUFile *f, void *opaque, size_t size,
> > >> +                     VMStateField *field)
> > >>  {
> > >>      ARMCPU *cpu = opaque;
> > >>      CPUARMState *env = &cpu->env;
> > >> @@ -27,7 +28,8 @@ static int get_fpscr(QEMUFile *f, void *opaque, size_t size)
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_fpscr(QEMUFile *f, void *opaque, size_t size)
> > >> +static void put_fpscr(QEMUFile *f, void *opaque, size_t size,
> > >> +                      VMStateField *field, QJSON *vmdesc)
> > >>  {
> > >>      ARMCPU *cpu = opaque;
> > >>      CPUARMState *env = &cpu->env;
> > >> @@ -163,7 +165,8 @@ static const VMStateDescription vmstate_pmsav7 = {
> > >>      }
> > >>  };
> > >>  
> > >> -static int get_cpsr(QEMUFile *f, void *opaque, size_t size)
> > >> +static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
> > >> +                    VMStateField *field)
> > >>  {
> > >>      ARMCPU *cpu = opaque;
> > >>      CPUARMState *env = &cpu->env;
> > >> @@ -180,7 +183,8 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size)
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_cpsr(QEMUFile *f, void *opaque, size_t size)
> > >> +static void put_cpsr(QEMUFile *f, void *opaque, size_t size,
> > >> +                     VMStateField *field, QJSON *vmdesc)
> > >>  {
> > >>      ARMCPU *cpu = opaque;
> > >>      CPUARMState *env = &cpu->env;
> > >> diff --git a/target-i386/machine.c b/target-i386/machine.c
> > >> index 71c0e4d..1df19e2 100644
> > >> --- a/target-i386/machine.c
> > >> +++ b/target-i386/machine.c
> > >> @@ -139,7 +139,8 @@ static const VMStateDescription vmstate_mtrr_var = {
> > >>  #define VMSTATE_MTRR_VARS(_field, _state, _n, _v)                    \
> > >>      VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar)
> > >>  
> > >> -static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size)
> > >> +static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size,
> > >> +                            VMStateField *field, QJSON *vmdesc)
> > >>  {
> > >>      fprintf(stderr, "call put_fpreg() with invalid arguments\n");
> > >>      exit(0);
> > >> @@ -167,7 +168,8 @@ static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
> > >>      p->exp = e;
> > >>  }
> > >>  
> > >> -static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
> > >> +static int get_fpreg(QEMUFile *f, void *opaque, size_t size,
> > >> +                     VMStateField *field)
> > >>  {
> > >>      FPReg *fp_reg = opaque;
> > >>      uint64_t mant;
> > >> @@ -179,7 +181,8 @@ static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_fpreg(QEMUFile *f, void *opaque, size_t size)
> > >> +static void put_fpreg(QEMUFile *f, void *opaque, size_t size,
> > >> +                      VMStateField *field, QJSON *vmdesc)
> > >>  {
> > >>      FPReg *fp_reg = opaque;
> > >>      uint64_t mant;
> > >> @@ -197,7 +200,8 @@ static const VMStateInfo vmstate_fpreg = {
> > >>      .put  = put_fpreg,
> > >>  };
> > >>  
> > >> -static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size)
> > >> +static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size,
> > >> +                           VMStateField *field)
> > >>  {
> > >>      union x86_longdouble *p = opaque;
> > >>      uint64_t mant;
> > >> @@ -214,7 +218,8 @@ static const VMStateInfo vmstate_fpreg_1_mmx = {
> > >>      .put  = put_fpreg_error,
> > >>  };
> > >>  
> > >> -static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size)
> > >> +static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size,
> > >> +                              VMStateField *field)
> > >>  {
> > >>      union x86_longdouble *p = opaque;
> > >>      uint64_t mant;
> > >> @@ -276,14 +281,16 @@ static bool less_than_7(void *opaque, int version_id)
> > >>      return version_id < 7;
> > >>  }
> > >>  
> > >> -static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size,
> > >> +                                VMStateField *field)
> > >>  {
> > >>      uint64_t *v = pv;
> > >>      *v = qemu_get_be32(f);
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size,
> > >> +                                 VMStateField *field, QJSON *vmdesc)
> > >>  {
> > >>      uint64_t *v = pv;
> > >>      qemu_put_be32(f, *v);
> > >> diff --git a/target-mips/machine.c b/target-mips/machine.c
> > >> index a27f2f1..179084c 100644
> > >> --- a/target-mips/machine.c
> > >> +++ b/target-mips/machine.c
> > >> @@ -20,7 +20,7 @@ static int cpu_post_load(void *opaque, int version_id)
> > >>  
> > >>  /* FPU state */
> > >>  
> > >> -static int get_fpr(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      int i;
> > >>      fpr_t *v = pv;
> > >> @@ -31,7 +31,8 @@ static int get_fpr(QEMUFile *f, void *pv, size_t size)
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_fpr(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_fpr(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                    QJSON *vmdesc)
> > >>  {
> > >>      int i;
> > >>      fpr_t *v = pv;
> > >> @@ -125,7 +126,7 @@ const VMStateDescription vmstate_mvp = {
> > >>  
> > >>  /* TLB state */
> > >>  
> > >> -static int get_tlb(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      r4k_tlb_t *v = pv;
> > >>      uint16_t flags;
> > >> @@ -152,7 +153,8 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size)
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_tlb(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_tlb(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                    QJSON *vmdesc)
> > >>  {
> > >>      r4k_tlb_t *v = pv;
> > >>  
> > >> diff --git a/target-ppc/machine.c b/target-ppc/machine.c
> > >> index 4820f22..0e1822c 100644
> > >> --- a/target-ppc/machine.c
> > >> +++ b/target-ppc/machine.c
> > >> @@ -106,7 +106,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static int get_avr(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      ppc_avr_t *v = pv;
> > >>  
> > >> @@ -116,7 +116,8 @@ static int get_avr(QEMUFile *f, void *pv, size_t size)
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_avr(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_avr(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                    QJSON *vmdesc)
> > >>  {
> > >>      ppc_avr_t *v = pv;
> > >>  
> > >> @@ -324,7 +325,7 @@ static const VMStateDescription vmstate_sr = {
> > >>  };
> > >>  
> > >>  #ifdef TARGET_PPC64
> > >> -static int get_slbe(QEMUFile *f, void *pv, size_t size)
> > >> +static int get_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field)
> > >>  {
> > >>      ppc_slb_t *v = pv;
> > >>  
> > >> @@ -334,7 +335,8 @@ static int get_slbe(QEMUFile *f, void *pv, size_t size)
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_slbe(QEMUFile *f, void *pv, size_t size)
> > >> +static void put_slbe(QEMUFile *f, void *pv, size_t size, VMStateField *field,
> > >> +                     QJSON *vmdesc)
> > >>  {
> > >>      ppc_slb_t *v = pv;
> > >>  
> > >> diff --git a/target-sparc/machine.c b/target-sparc/machine.c
> > >> index 59c92f7..3194e03 100644
> > >> --- a/target-sparc/machine.c
> > >> +++ b/target-sparc/machine.c
> > >> @@ -59,7 +59,7 @@ static const VMStateDescription vmstate_tlb_entry = {
> > >>  };
> > >>  #endif
> > >>  
> > >> -static int get_psr(QEMUFile *f, void *opaque, size_t size)
> > >> +static int get_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field)
> > >>  {
> > >>      SPARCCPU *cpu = opaque;
> > >>      CPUSPARCState *env = &cpu->env;
> > >> @@ -72,7 +72,8 @@ static int get_psr(QEMUFile *f, void *opaque, size_t size)
> > >>      return 0;
> > >>  }
> > >>  
> > >> -static void put_psr(QEMUFile *f, void *opaque, size_t size)
> > >> +static void put_psr(QEMUFile *f, void *opaque, size_t size, VMStateField *field,
> > >> +                QJSON *vmdesc)
> > >>  {
> > >>      SPARCCPU *cpu = opaque;
> > >>      CPUSPARCState *env = &cpu->env;
> > >>
> > >>
> > 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [Qemu-devel] [QEMU PATCH v5 5/6] migration: spapr: migrate ccs_list in spapr state
  2016-10-07 14:52     ` Michael Roth
@ 2016-10-10  5:05       ` David Gibson
  0 siblings, 0 replies; 66+ messages in thread
From: David Gibson @ 2016-10-10  5:05 UTC (permalink / raw)
  To: Michael Roth
  Cc: Jianjun Duan, qemu-devel, qemu-ppc, dmitry, peter.maydell,
	kraxel, mst, pbonzini, veroniabahaa, quintela, amit.shah, mreitz,
	kwolf, rth, aurelien, leon.alrae, blauwirbel, mark.cave-ayland,
	dgilbert

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

On Fri, Oct 07, 2016 at 09:52:51AM -0500, Michael Roth wrote:
> Quoting David Gibson (2016-10-06 22:36:07)
> > On Mon, Oct 03, 2016 at 11:24:56AM -0700, Jianjun Duan wrote:
> > > ccs_list in spapr state maintains the device tree related
> > > information on the rtas side for hotplugged devices. In racing
> > > situations between hotplug events and migration operation, a rtas
> > > hotplug event could be migrated from the source guest to target
> > > guest, or the source guest could have not yet finished fetching
> > > the device tree when migration is started, the target will try
> > > to finish fetching the device tree. By migrating ccs_list, the
> > > target can fetch the device tree properly.
> > > 
> > > ccs_list is put in a subsection in the spapr state VMSD to make
> > > sure migration across different versions is not broken.
> > > 
> > > Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
> > 
> > I'm still not entirely convinced we need to migrate the ccs_list.
> > What would happen if we did this:
> > 
> >    * Keep a flag which indicates whether the guest is in the middle of
> >      the configure_connector process.
> >        - I'm not sure if that would need to be a new bit of state, or
> >          if we could deduce it from the value of the isolation and
> >          allocation states
> >        - If it's new state, we'd need to migrate it, obviously not if
> >          we can derive it from other state flags
> > 
> >    * On the destination during post_load, if there was an in-progress
> >      configure_connector on the source, we set another "stale
> >      configure" flag
> > 
> >    * When a configure_connector call is attempted on the destination
> >      with the stale configure flag set, return an error
> > 
> > The question is, if we choose the right error, can we get the guest to
> > either restart the configure from scratch, or fail gracefully, so the
> > operator can restart the hotplug
> 
> To get the configure to restart, the guest's configure_connector
> implementation would need to changed. Current code in drmgr would just
> bail on any error, and I'd imagine the in-kernel version does the same.
> 
> So at least for existing guests, the only option is failing the command
> at the operator's interface, namely device_add. device_add is
> asynchronous to the actual hotplug event handling however. So if we want
> to convey failure to the user, it would have to be either in the form of
> a new QMP event emitted to convey hotplug success or error, or through
> device_add itself by implementing something like the async QMP rework
> that Marc-Andre posted some time back (which still seems to be a topic
> of debate). Which either approach, something like libvirt, with adequate
> state-tracking for pending hotplug events, could handle an error event
> on the target side post-migrate and convey that to the user somehow.
> 
> That's probably a much larger discussion if it comes to that, but doable
> in theory.
> 
> But even that wouldn't get us totally out of the woods: DRC state can
> still be modified outside of hotplug. For instance, a guest should be
> able to do:
> 
>   drmgr -c pci -s <drc_index> -r
>   drmgr -c pci -s <drc_index> -a
> 
> to return a device to firmware and then later take it back and
> reconfigure it. I'm not aware of any common case where this would occur,
> but it's not disallowed by the specification, and performing a migration
> between these 2 operations would currently break this since the default
> coldplug state on target assumes a configured state in source.

Thanks, that's a good case for why we need this.  Can you please fold
this description into your commit messages so it's there for posterity.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [Qemu-devel] [QEMU PATCH v5 2/6] migration: spapr_drc: defined VMStateDescription struct
  2016-10-07 17:17     ` Jianjun Duan
@ 2016-10-10  5:09       ` David Gibson
  2016-10-10 16:48         ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
  0 siblings, 1 reply; 66+ messages in thread
From: David Gibson @ 2016-10-10  5:09 UTC (permalink / raw)
  To: Jianjun Duan
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth,
	dgilbert

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

On Fri, Oct 07, 2016 at 10:17:45AM -0700, Jianjun Duan wrote:
> 
> 
> On 10/06/2016 08:12 PM, David Gibson wrote:
> > On Mon, Oct 03, 2016 at 11:24:53AM -0700, Jianjun Duan wrote:
> >> To manage hotplug/unplug of dynamic resources such as PCI cards,
> >> memory, and CPU on sPAPR guests, a firmware abstraction known as
> >> a Dynamic Resource Connector (DRC) is used to assign a particular
> >> dynamic resource to the guest, and provide an interface for the
> >> guest to manage configuration/removal of the resource associated
> >> with it.
> >>
> >> To migrate the hotplugged resources in migration, the
> >> associated DRC state need be migrated. To migrate the DRC state,
> >> we defined the VMStateDescription struct for spapr_drc to enable
> >> the transmission of spapr_drc state in migration.
> >>
> >> Not all the elements in the DRC state are migrated. Only those
> >> ones modifiable or needed by guest actions or device add/remove
> >> operation are migrated. From the perspective of device
> >> hotplugging, if we hotplug a device on the source, we need to
> >> "coldplug" it on the target. The states across two hosts for the
> >> same device are not the same. Ideally we want the states be same
> >> after migration so that the device would function as hotplugged
> >> on the target. For example we can unplug it. The minimum DRC
> >> state we need to transfer should cover all the pieces changed by
> >> hotplugging. Out of the elements of the DRC state, isolation_state,
> >> allocation_sate, and configured are involved in the DR state
> >> transition diagram from PAPR+ 2.7, 13.4. configured and signalled
> >> are needed in attaching and detaching devices. indicator_state
> >> provides users with hardware state information. These 6 elements
> >> are migrated.
> > 
> > Hmm.. are you saying that the DRC state of a coldplugged device (after
> > we've fully booted) is different from the DRC state of a hotplugged
> > device (after all the hotplug operations have fully completed)?
> > 
> > If that's correct that sounds like a general bug in the DRC state
> > management, not something only related to migration.
> > 
> > Looking at the code, though, that doesn't really seem to be what it's
> > doing.
> > 
> 
> After hotplugging a device, changes may be made to its DRC state on the
> source. But on target the state is fresh. The possible changes are shown
> in spapr_drc_needed function.

Ok.  If you can somehow include the content of the paragraph above in
your commit messages that would make the rationale clearer.

> >> detach_cb in the DRC state is a function pointer that cannot be
> >> migrated. We set it right after DRC state is migrated so that
> >> a migrated hot-unplug event could finish its work.
> >>
> >> The instance_id is used to identify objects in migration. We set
> >> instance_id of DRC using the unique index so that it is the same
> >> across migration.
> >>
> >> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
> >> ---
> >>  hw/ppc/spapr_drc.c         | 69 ++++++++++++++++++++++++++++++++++++++++++++++
> >>  hw/ppc/spapr_pci.c         | 22 +++++++++++++++
> >>  include/hw/ppc/spapr_drc.h |  9 ++++++
> >>  3 files changed, 100 insertions(+)
> >>
> >> diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
> >> index 6e54fd4..369ec02 100644
> >> --- a/hw/ppc/spapr_drc.c
> >> +++ b/hw/ppc/spapr_drc.c
> >> @@ -615,6 +615,71 @@ static void spapr_dr_connector_instance_init(Object *obj)
> >>                          NULL, NULL, NULL, NULL);
> >>  }
> >>  
> >> +static bool spapr_drc_needed(void *opaque)
> >> +{
> >> +    sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;
> >> +    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
> >> +    bool rc = false;
> >> +    sPAPRDREntitySense value;
> >> +
> >> +    drck->entity_sense(drc, &value);
> >> +    /* If no dev is plugged in there is no need to migrate the DRC state */
> >> +    if (value != SPAPR_DR_ENTITY_SENSE_PRESENT) {
> >> +        return false;
> >> +    }
> >> +    /*
> >> +     * If there is dev plugged in, we need to migrate the DRC state when
> >> +     * it is different from cold-plugged state
> >> +     */
> >> +    switch(drc->type) {
> >> +    /* for PCI type */
> >> +    case SPAPR_DR_CONNECTOR_TYPE_PCI:
> >> +        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) &&
> >> +               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) &&
> >> +               drc->configured && drc->signalled && !drc->awaiting_release);
> >> +        break;
> >> +    /* for LMB type */
> >> +    case SPAPR_DR_CONNECTOR_TYPE_LMB:
> >> +        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) &&
> >> +               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) &&
> >> +               drc->configured && drc->signalled && !drc->awaiting_release);
> >> +        break;
> > 
> > What about CPU type?z
> 
> For CPU Type, those states don't change from source to host.

Is that a property of the CPU type specifically, or is that just
because current guests don't mess with the CPU DRC states the way they
do with other devices?

> >> +    default:
> >> +        ;
> >> +    }
> >> +
> >> +    return rc;
> >> +}
> >> +
> >> +/* detach_cb needs be set since it is not migrated */
> >> +static void postmigrate_set_detach_cb(sPAPRDRConnector *drc,
> >> +                                      spapr_drc_detach_cb *detach_cb)
> >> +{
> >> +    drc->detach_cb = detach_cb;
> >> +}
> >> +
> >> +/* return the unique drc index as instance_id for qom interfaces*/
> >> +static int get_instance_id(DeviceState *dev)
> >> +{
> >> +    return (int)get_index(SPAPR_DR_CONNECTOR(OBJECT(dev)));
> >> +}
> >> +
> >> +static const VMStateDescription vmstate_spapr_drc = {
> >> +    .name = "spapr_drc",
> >> +    .version_id = 1,
> >> +    .minimum_version_id = 1,
> >> +    .needed = spapr_drc_needed,
> >> +    .fields  = (VMStateField []) {
> >> +        VMSTATE_UINT32(isolation_state, sPAPRDRConnector),
> >> +        VMSTATE_UINT32(allocation_state, sPAPRDRConnector),
> >> +        VMSTATE_UINT32(indicator_state, sPAPRDRConnector),
> >> +        VMSTATE_BOOL(configured, sPAPRDRConnector),
> >> +        VMSTATE_BOOL(awaiting_release, sPAPRDRConnector),
> >> +        VMSTATE_BOOL(signalled, sPAPRDRConnector),
> >> +        VMSTATE_END_OF_LIST()
> >> +    }
> >> +};
> >> +
> >>  static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
> >>  {
> >>      DeviceClass *dk = DEVICE_CLASS(k);
> >> @@ -623,6 +688,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
> >>      dk->reset = reset;
> >>      dk->realize = realize;
> >>      dk->unrealize = unrealize;
> >> +    dk->vmsd = &vmstate_spapr_drc;
> >> +    dk->dev_get_instance_id = get_instance_id;
> >>      drck->set_isolation_state = set_isolation_state;
> >>      drck->set_indicator_state = set_indicator_state;
> >>      drck->set_allocation_state = set_allocation_state;
> >> @@ -636,6 +703,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
> >>      drck->detach = detach;
> >>      drck->release_pending = release_pending;
> >>      drck->set_signalled = set_signalled;
> >> +    drck->postmigrate_set_detach_cb = postmigrate_set_detach_cb;
> >> +
> >>      /*
> >>       * Reason: it crashes FIXME find and document the real reason
> >>       */
> >> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
> >> index 4f00865..080471c 100644
> >> --- a/hw/ppc/spapr_pci.c
> >> +++ b/hw/ppc/spapr_pci.c
> >> @@ -1594,11 +1594,33 @@ static void spapr_pci_pre_save(void *opaque)
> >>      }
> >>  }
> >>  
> >> +/*
> >> + * detach_cb in the DRC state is a function pointer that cannot be
> >> + * migrated. We set it right after migration so that a migrated
> >> + * hot-unplug event could finish its work.
> >> + */
> >> +static void spapr_pci_set_detach_cb(PCIBus *bus, PCIDevice *pdev,
> >> +                                 void *opaque)
> >> +{
> >> +    sPAPRPHBState *sphb = opaque;
> >> +    sPAPRDRConnector *drc = spapr_phb_get_pci_drc(sphb, pdev);
> >> +    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
> >> +    drck->postmigrate_set_detach_cb(drc, spapr_phb_remove_pci_device_cb);
> > 
> > Why is spapr_phb_remove_pci_device_cb the right callback rather than
> > something else?  This doesn't seem sensible.
> > 
> > More to the point, you're not restoring detach_cb_opaque, which means
> > the detach_cb callback won't work properly anyway.
> > 
> If set_isolation_state/set_allocation_state is called on target without
> spapr_phb_remove_pci_device being called earlier, drc->detach_cb is
> null. Its value is spapr_phb_remove_pci_device_cb and is set in
> spapr_phb_remove_pci_device.
> 
> You are right about detach_cb. It needs be restored.

Right.

It sounds like detach_cb is doing double duty - it is pointing to what
the right detach function is, and also acting as a flag to say if a
detach operation is necessary.  This doesn't play well with migration.

In order to do sane migration, I suspect we need to split this into
different components - the callback value can maybe move to the class
instead of the DRC instance (or just use a switch on drc_type).  The
flag can just become a boolean which we can migrate.

> >> +}
> >> +
> >>  static int spapr_pci_post_load(void *opaque, int version_id)
> >>  {
> >>      sPAPRPHBState *sphb = opaque;
> >>      gpointer key, value;
> >>      int i;
> >> +    PCIBus *bus = PCI_HOST_BRIDGE(sphb)->bus;
> >> +    unsigned int bus_no = 0;
> >> +
> >> +    /* Set detach_cb for the drc unconditionally after migration */
> >> +    if (bus) {
> >> +        pci_for_each_device(bus, pci_bus_num(bus), spapr_pci_set_detach_cb,
> >> +                            &bus_no);
> >> +    }
> >>  
> >>      for (i = 0; i < sphb->msi_devs_num; ++i) {
> >>          key = g_memdup(&sphb->msi_devs[i].key,
> >> diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h
> >> index fa531d5..17589c8 100644
> >> --- a/include/hw/ppc/spapr_drc.h
> >> +++ b/include/hw/ppc/spapr_drc.h
> >> @@ -192,6 +192,15 @@ typedef struct sPAPRDRConnectorClass {
> >>                     void *detach_cb_opaque, Error **errp);
> >>      bool (*release_pending)(sPAPRDRConnector *drc);
> >>      void (*set_signalled)(sPAPRDRConnector *drc);
> >> +
> >> +    /*
> >> +     * QEMU interface for setting detach_cb after migration.
> >> +     * detach_cb in the DRC state is a function pointer that cannot be
> >> +     * migrated. We set it right after migration so that a migrated
> >> +     * hot-unplug event could finish its work.
> >> +     */
> >> +    void (*postmigrate_set_detach_cb)(sPAPRDRConnector *drc,
> >> +                                      spapr_drc_detach_cb *detach_cb);
> >>  } sPAPRDRConnectorClass;
> >>  
> >>  sPAPRDRConnector *spapr_dr_connector_new(Object *owner,
> > 
> 
> Thanks,
> Jianjun
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [Qemu-devel] [QEMU PATCH v5 1/6] migration: alternative way to set instance_id in SaveStateEntry
  2016-10-07  8:07         ` Dr. David Alan Gilbert
@ 2016-10-10  5:31           ` David Gibson
  2016-10-11 16:17             ` Michael Roth
  0 siblings, 1 reply; 66+ messages in thread
From: David Gibson @ 2016-10-10  5:31 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Jianjun Duan, qemu-devel, qemu-ppc, dmitry, peter.maydell,
	kraxel, mst, pbonzini, veroniabahaa, quintela, amit.shah, mreitz,
	kwolf, rth, aurelien, leon.alrae, blauwirbel, mark.cave-ayland,
	mdroth

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

On Fri, Oct 07, 2016 at 09:07:49AM +0100, Dr. David Alan Gilbert wrote:
> * David Gibson (david@gibson.dropbear.id.au) wrote:
> > On Wed, Oct 05, 2016 at 09:44:57AM -0700, Jianjun Duan wrote:
> > > Please see comments below:
> > > 
> > > On 10/05/2016 03:12 AM, Dr. David Alan Gilbert wrote:
> > > > * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> > > >> In QOM(QEMU Object Model) migrated objects are identified with instance_id
> > > >> which is calculated automatically using their path in the QOM composition
> > > >> tree. For some objects, this path could change from source to target in
> > > >> migration. To migrate such objects, we need to make sure the instance_id does
> > > >> not change from source to target. We add a hook in DeviceClass to do customized
> > > >> instance_id calculation in such cases.
> > > > 
> > > > Can you explain a bit about why the path changes from source to destination;
> > > > the path here should be a feature of the guest state not the host, and so I
> > > > don't understand why it changes.
> > > Please see the discussion with David in the previous versions:
> > > http://lists.nongnu.org/archive/html/qemu-ppc/2016-06/msg00062.html
> > 
> > Um.. your description above really isn't an accurate summary of that
> > discussion.
> > 
> > The point is not that the qom path will vary from source to
> > destination for some arbitrary reason, but rather that we anticipate
> > future changes in the QOM structure.  Specifically we're considering
> > eliminating the DRC objects, and folding their (limited) state into an
> > array in the parent object (either the machine or a PCI host bridge).
> > 
> > That would change the qom paths, and hence the auto-generated instance
> > ids, which would break migration between qemu versions before and
> > after the restructure.
> > 
> > I'm not sure that changing the instance ids is enough though, anyway,
> > since we're talking about eliminating the object entirely, the
> > class/type information in the migration stream also wouldn't match.
> > 
> > Dave, if you have ideas on how to deal with that, I'd love to hear
> > them
> 
> Eliminating the object entirely would be tricky to deal with;
> allowing the structure to change would work if instead of a custom instance_id
> you had a custom idstr.

Sorry, two misunderstandings here.

  * When I said "structure" I meant in the high-level sense of what
    objects exist and are responsible for what things, not in the
    'struct WhateverState' sense.

  * In fact right now eliminating the objects would be ok, since they
    have no migration state (which causes the problems this series is
    trying to address).  But applying this series which adds migration
    state would make it difficult to eliminate the objects in future.
    That's an awkward constraint given that we've already got some
    hints that these objects are not a good idea.

> However, the question then becomes why is the structure changing so much;
> ideally things in the migration stream should represent some tangible object
> that corresponds to something real, but (again ideally) the contents
> of the stream should reflect the state of those objects not the current
> implementation - so if you want to change the implementation the stream
> doesn't change.  Is it your implementation, or the understanding of what
> the objects actually represent that's in flux?

So, the objects in question are DRCs - "Dynamic Re-configuration
Connector"; silly IBM talk for "a port into which something can be
hotplugged", bascially.  These aren't "real" devices, but rather a
firmware/hypervisor abstraction which are used to describe a hotplug
point.  Each DRC allows either one CPU core, one PCI device, or one
LMB (256MiB chunk of RAM) to be hotplugged (or removed).  The PCI DRCs
are "owned" by the PCI host bridge to which the device would be
connected, the CPU and memory DRCs are owned by the machine.

The state variables which Jianjun Duan is adding to migration are
values defined in the PAPR (hypervisor interface) spec, and so are
tangible enough to be sensible to migrate.  At the moment, each LMB is
represented by a discrete QOM object, but I've been thinking for a
while that this may be a mistake.  In particular it's a problem for
the LMB DRCs - because each LMB is only 256MiB of memory, we end up
with thousands, maybe tens of thousands of DRC objects on a guest with
with large maxmem (even if initial memory is small).  The QOM
infrastructure doesn't deal terribly well that many object child
properties.

The construction of those DRCs used to be an N^3 algorithm, which as
you'd imagine caused horrible startup times with large maxmem (minutes
to hours above ~512GiB).  We fixed it to be only N^2, so now the
startup delays are merely bad (at least once you get to ~2TiB+
maxmem).

We could fix that by changing QOM to use a hash or tree for object
children, instead of a plain list, but I'm not sure if it makes sense
to do that with only this use case.

So, for some time, I've been considering rewriting the DRC stuff to be
implemented via QOM interface on the "owner" object, rather than
separate objects for every single connector.

So the difficulty is that if we add the state migration to the DRC
objects as they stand, we prevent ourselves from doing a refactor
that's probably a good idea.  But no-one's yet had time to actually
thrash out such a refactor. :/

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 2/6] migration: spapr_drc: defined VMStateDescription struct
  2016-10-10  5:09       ` David Gibson
@ 2016-10-10 16:48         ` Jianjun Duan
  0 siblings, 0 replies; 66+ messages in thread
From: Jianjun Duan @ 2016-10-10 16:48 UTC (permalink / raw)
  To: David Gibson
  Cc: qemu-devel, qemu-ppc, dmitry, peter.maydell, kraxel, mst,
	pbonzini, veroniabahaa, quintela, amit.shah, mreitz, kwolf, rth,
	aurelien, leon.alrae, blauwirbel, mark.cave-ayland, mdroth,
	dgilbert



On 10/09/2016 10:09 PM, David Gibson wrote:
> On Fri, Oct 07, 2016 at 10:17:45AM -0700, Jianjun Duan wrote:
>>
>>
>> On 10/06/2016 08:12 PM, David Gibson wrote:
>>> On Mon, Oct 03, 2016 at 11:24:53AM -0700, Jianjun Duan wrote:
>>>> To manage hotplug/unplug of dynamic resources such as PCI cards,
>>>> memory, and CPU on sPAPR guests, a firmware abstraction known as
>>>> a Dynamic Resource Connector (DRC) is used to assign a particular
>>>> dynamic resource to the guest, and provide an interface for the
>>>> guest to manage configuration/removal of the resource associated
>>>> with it.
>>>>
>>>> To migrate the hotplugged resources in migration, the
>>>> associated DRC state need be migrated. To migrate the DRC state,
>>>> we defined the VMStateDescription struct for spapr_drc to enable
>>>> the transmission of spapr_drc state in migration.
>>>>
>>>> Not all the elements in the DRC state are migrated. Only those
>>>> ones modifiable or needed by guest actions or device add/remove
>>>> operation are migrated. From the perspective of device
>>>> hotplugging, if we hotplug a device on the source, we need to
>>>> "coldplug" it on the target. The states across two hosts for the
>>>> same device are not the same. Ideally we want the states be same
>>>> after migration so that the device would function as hotplugged
>>>> on the target. For example we can unplug it. The minimum DRC
>>>> state we need to transfer should cover all the pieces changed by
>>>> hotplugging. Out of the elements of the DRC state, isolation_state,
>>>> allocation_sate, and configured are involved in the DR state
>>>> transition diagram from PAPR+ 2.7, 13.4. configured and signalled
>>>> are needed in attaching and detaching devices. indicator_state
>>>> provides users with hardware state information. These 6 elements
>>>> are migrated.
>>>
>>> Hmm.. are you saying that the DRC state of a coldplugged device (after
>>> we've fully booted) is different from the DRC state of a hotplugged
>>> device (after all the hotplug operations have fully completed)?
>>>
>>> If that's correct that sounds like a general bug in the DRC state
>>> management, not something only related to migration.
>>>
>>> Looking at the code, though, that doesn't really seem to be what it's
>>> doing.
>>>
>>
>> After hotplugging a device, changes may be made to its DRC state on the
>> source. But on target the state is fresh. The possible changes are shown
>> in spapr_drc_needed function.
> 
> Ok.  If you can somehow include the content of the paragraph above in
> your commit messages that would make the rationale clearer.
> 
Will do.
>>>> detach_cb in the DRC state is a function pointer that cannot be
>>>> migrated. We set it right after DRC state is migrated so that
>>>> a migrated hot-unplug event could finish its work.
>>>>
>>>> The instance_id is used to identify objects in migration. We set
>>>> instance_id of DRC using the unique index so that it is the same
>>>> across migration.
>>>>
>>>> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
>>>> ---
>>>>  hw/ppc/spapr_drc.c         | 69 ++++++++++++++++++++++++++++++++++++++++++++++
>>>>  hw/ppc/spapr_pci.c         | 22 +++++++++++++++
>>>>  include/hw/ppc/spapr_drc.h |  9 ++++++
>>>>  3 files changed, 100 insertions(+)
>>>>
>>>> diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
>>>> index 6e54fd4..369ec02 100644
>>>> --- a/hw/ppc/spapr_drc.c
>>>> +++ b/hw/ppc/spapr_drc.c
>>>> @@ -615,6 +615,71 @@ static void spapr_dr_connector_instance_init(Object *obj)
>>>>                          NULL, NULL, NULL, NULL);
>>>>  }
>>>>  
>>>> +static bool spapr_drc_needed(void *opaque)
>>>> +{
>>>> +    sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;
>>>> +    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
>>>> +    bool rc = false;
>>>> +    sPAPRDREntitySense value;
>>>> +
>>>> +    drck->entity_sense(drc, &value);
>>>> +    /* If no dev is plugged in there is no need to migrate the DRC state */
>>>> +    if (value != SPAPR_DR_ENTITY_SENSE_PRESENT) {
>>>> +        return false;
>>>> +    }
>>>> +    /*
>>>> +     * If there is dev plugged in, we need to migrate the DRC state when
>>>> +     * it is different from cold-plugged state
>>>> +     */
>>>> +    switch(drc->type) {
>>>> +    /* for PCI type */
>>>> +    case SPAPR_DR_CONNECTOR_TYPE_PCI:
>>>> +        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) &&
>>>> +               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) &&
>>>> +               drc->configured && drc->signalled && !drc->awaiting_release);
>>>> +        break;
>>>> +    /* for LMB type */
>>>> +    case SPAPR_DR_CONNECTOR_TYPE_LMB:
>>>> +        rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) &&
>>>> +               (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) &&
>>>> +               drc->configured && drc->signalled && !drc->awaiting_release);
>>>> +        break;
>>>
>>> What about CPU type?z
>>
>> For CPU Type, those states don't change from source to host.
> 
> Is that a property of the CPU type specifically, or is that just
> because current guests don't mess with the CPU DRC states the way they
> do with other devices?
> 
Need to double check. From the experiments I had done, I didn't see any
changes.
>>>> +    default:
>>>> +        ;
>>>> +    }
>>>> +
>>>> +    return rc;
>>>> +}
>>>> +
>>>> +/* detach_cb needs be set since it is not migrated */
>>>> +static void postmigrate_set_detach_cb(sPAPRDRConnector *drc,
>>>> +                                      spapr_drc_detach_cb *detach_cb)
>>>> +{
>>>> +    drc->detach_cb = detach_cb;
>>>> +}
>>>> +
>>>> +/* return the unique drc index as instance_id for qom interfaces*/
>>>> +static int get_instance_id(DeviceState *dev)
>>>> +{
>>>> +    return (int)get_index(SPAPR_DR_CONNECTOR(OBJECT(dev)));
>>>> +}
>>>> +
>>>> +static const VMStateDescription vmstate_spapr_drc = {
>>>> +    .name = "spapr_drc",
>>>> +    .version_id = 1,
>>>> +    .minimum_version_id = 1,
>>>> +    .needed = spapr_drc_needed,
>>>> +    .fields  = (VMStateField []) {
>>>> +        VMSTATE_UINT32(isolation_state, sPAPRDRConnector),
>>>> +        VMSTATE_UINT32(allocation_state, sPAPRDRConnector),
>>>> +        VMSTATE_UINT32(indicator_state, sPAPRDRConnector),
>>>> +        VMSTATE_BOOL(configured, sPAPRDRConnector),
>>>> +        VMSTATE_BOOL(awaiting_release, sPAPRDRConnector),
>>>> +        VMSTATE_BOOL(signalled, sPAPRDRConnector),
>>>> +        VMSTATE_END_OF_LIST()
>>>> +    }
>>>> +};
>>>> +
>>>>  static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
>>>>  {
>>>>      DeviceClass *dk = DEVICE_CLASS(k);
>>>> @@ -623,6 +688,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
>>>>      dk->reset = reset;
>>>>      dk->realize = realize;
>>>>      dk->unrealize = unrealize;
>>>> +    dk->vmsd = &vmstate_spapr_drc;
>>>> +    dk->dev_get_instance_id = get_instance_id;
>>>>      drck->set_isolation_state = set_isolation_state;
>>>>      drck->set_indicator_state = set_indicator_state;
>>>>      drck->set_allocation_state = set_allocation_state;
>>>> @@ -636,6 +703,8 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data)
>>>>      drck->detach = detach;
>>>>      drck->release_pending = release_pending;
>>>>      drck->set_signalled = set_signalled;
>>>> +    drck->postmigrate_set_detach_cb = postmigrate_set_detach_cb;
>>>> +
>>>>      /*
>>>>       * Reason: it crashes FIXME find and document the real reason
>>>>       */
>>>> diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
>>>> index 4f00865..080471c 100644
>>>> --- a/hw/ppc/spapr_pci.c
>>>> +++ b/hw/ppc/spapr_pci.c
>>>> @@ -1594,11 +1594,33 @@ static void spapr_pci_pre_save(void *opaque)
>>>>      }
>>>>  }
>>>>  
>>>> +/*
>>>> + * detach_cb in the DRC state is a function pointer that cannot be
>>>> + * migrated. We set it right after migration so that a migrated
>>>> + * hot-unplug event could finish its work.
>>>> + */
>>>> +static void spapr_pci_set_detach_cb(PCIBus *bus, PCIDevice *pdev,
>>>> +                                 void *opaque)
>>>> +{
>>>> +    sPAPRPHBState *sphb = opaque;
>>>> +    sPAPRDRConnector *drc = spapr_phb_get_pci_drc(sphb, pdev);
>>>> +    sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
>>>> +    drck->postmigrate_set_detach_cb(drc, spapr_phb_remove_pci_device_cb);
>>>
>>> Why is spapr_phb_remove_pci_device_cb the right callback rather than
>>> something else?  This doesn't seem sensible.
>>>
>>> More to the point, you're not restoring detach_cb_opaque, which means
>>> the detach_cb callback won't work properly anyway.
>>>
>> If set_isolation_state/set_allocation_state is called on target without
>> spapr_phb_remove_pci_device being called earlier, drc->detach_cb is
>> null. Its value is spapr_phb_remove_pci_device_cb and is set in
>> spapr_phb_remove_pci_device.
>>
>> You are right about detach_cb. It needs be restored.
> 
> Right.
> 
> It sounds like detach_cb is doing double duty - it is pointing to what
> the right detach function is, and also acting as a flag to say if a
> detach operation is necessary.  This doesn't play well with migration.
> 
> In order to do sane migration, I suspect we need to split this into
> different components - the callback value can maybe move to the class
> instead of the DRC instance (or just use a switch on drc_type).  The
> flag can just become a boolean which we can migrate.
> 

Maybe we can set all these callbacks when DRC is inited?


Thanks,
Jianjun
>>>> +}
>>>> +
>>>>  static int spapr_pci_post_load(void *opaque, int version_id)
>>>>  {
>>>>      sPAPRPHBState *sphb = opaque;
>>>>      gpointer key, value;
>>>>      int i;
>>>> +    PCIBus *bus = PCI_HOST_BRIDGE(sphb)->bus;
>>>> +    unsigned int bus_no = 0;
>>>> +
>>>> +    /* Set detach_cb for the drc unconditionally after migration */
>>>> +    if (bus) {
>>>> +        pci_for_each_device(bus, pci_bus_num(bus), spapr_pci_set_detach_cb,
>>>> +                            &bus_no);
>>>> +    }
>>>>  
>>>>      for (i = 0; i < sphb->msi_devs_num; ++i) {
>>>>          key = g_memdup(&sphb->msi_devs[i].key,
>>>> diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h
>>>> index fa531d5..17589c8 100644
>>>> --- a/include/hw/ppc/spapr_drc.h
>>>> +++ b/include/hw/ppc/spapr_drc.h
>>>> @@ -192,6 +192,15 @@ typedef struct sPAPRDRConnectorClass {
>>>>                     void *detach_cb_opaque, Error **errp);
>>>>      bool (*release_pending)(sPAPRDRConnector *drc);
>>>>      void (*set_signalled)(sPAPRDRConnector *drc);
>>>> +
>>>> +    /*
>>>> +     * QEMU interface for setting detach_cb after migration.
>>>> +     * detach_cb in the DRC state is a function pointer that cannot be
>>>> +     * migrated. We set it right after migration so that a migrated
>>>> +     * hot-unplug event could finish its work.
>>>> +     */
>>>> +    void (*postmigrate_set_detach_cb)(sPAPRDRConnector *drc,
>>>> +                                      spapr_drc_detach_cb *detach_cb);
>>>>  } sPAPRDRConnectorClass;
>>>>  
>>>>  sPAPRDRConnector *spapr_dr_connector_new(Object *owner,
>>>
>>
>> Thanks,
>> Jianjun
>>
> 

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-08 19:28                         ` Halil Pasic
@ 2016-10-10 21:29                           ` Jianjun Duan
  2016-10-11  7:33                             ` Paolo Bonzini
  2016-10-10 21:40                           ` Jianjun Duan
  1 sibling, 1 reply; 66+ messages in thread
From: Jianjun Duan @ 2016-10-10 21:29 UTC (permalink / raw)
  To: Halil Pasic, Paolo Bonzini, Dr. David Alan Gilbert
  Cc: veroniabahaa, peter.maydell, mdroth, mst, quintela,
	mark.cave-ayland, qemu-devel, mreitz, blauwirbel, amit.shah,
	qemu-ppc, kraxel, dmitry, kwolf, rth, leon.alrae, aurelien,
	david



On 10/08/2016 12:28 PM, Halil Pasic wrote:
> 
> 
> On 10/08/2016 01:37 PM, Paolo Bonzini wrote:
>>> Even though most put/get have no issues now, when somebody writes a new
>>>> put, he or she could run into issues if only checking the type
>>>> signature. It makes the code more readable.
> 
>> No, it doesn't because one is left wondering what is VMS_LINKED about.
> 
> I agree with Paolo. IMHO VMS_LINKED is conceptually difficult in  a sense
> that it's quite different that what we have currently. I have the feeling,
> conceptually, we are trying to fit in something like data structures with a
> type parameter (the element type) here. AFAIU what vmstate currently can is
> directed acyclic graphs of certain stuff (and also completely custom
> handling based on custom put/get).
> 
You are right. What we have in VMSTATE now cannot handle a recursive (or
cyclic as you call it) structure. The idea was to use VMS_LINKED to
indicate a recursive structure. In this patch is used on a queue. It can
also be used on list or trees.
In this regard, VMS_LINKED does represent something.

Thanks,
Jianjun

>> What is the relation between linked datastructures and passing some
>> arguments as NULL/noon-NULL?
> 
> IFAIU we need those for the datastructure because it's linked and has
> a type parameter (element type). The two last arguments are for
> the element type. These were added by the previous patch because
> the old VMStateInfo did not need these. So we drastically changed
> the scope of VMStateInfo with the previous patch and I'm not
> sure I like this.
> 
> I will have to stare at this a bit longer to bring something more
> constructive than these (largely feeling-based) remarks.
> 
> Cheers,
> Halil
> 

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-08 19:28                         ` Halil Pasic
  2016-10-10 21:29                           ` Jianjun Duan
@ 2016-10-10 21:40                           ` Jianjun Duan
  1 sibling, 0 replies; 66+ messages in thread
From: Jianjun Duan @ 2016-10-10 21:40 UTC (permalink / raw)
  To: Halil Pasic, Paolo Bonzini, Dr. David Alan Gilbert
  Cc: veroniabahaa, peter.maydell, quintela, mst, mark.cave-ayland,
	mdroth, qemu-devel, blauwirbel, dmitry, qemu-ppc, kraxel, david,
	amit.shah, kwolf, mreitz, leon.alrae, aurelien, rth



On 10/08/2016 12:28 PM, Halil Pasic wrote:
> 
> 
> On 10/08/2016 01:37 PM, Paolo Bonzini wrote:
>>> Even though most put/get have no issues now, when somebody writes a new
>>>> put, he or she could run into issues if only checking the type
>>>> signature. It makes the code more readable.
> 
>> No, it doesn't because one is left wondering what is VMS_LINKED about.
> 
> I agree with Paolo. IMHO VMS_LINKED is conceptually difficult in  a sense
> that it's quite different that what we have currently. I have the feeling,
> conceptually, we are trying to fit in something like data structures with a
> type parameter (the element type) here. AFAIU what vmstate currently can is
> directed acyclic graphs of certain stuff (and also completely custom
> handling based on custom put/get).
> 
You are right. What we have in vmstate now cannot handle a recursive or
cyclic structure in a generic way. VMS_LINKED is intended to indicate a
recursive structure, with the newly added parameters of put/get
providing information about the element type in the recursive structure.

Thanks,
Jianjun
>> What is the relation between linked datastructures and passing some
>> arguments as NULL/noon-NULL?
> 
> IFAIU we need those for the datastructure because it's linked and has
> a type parameter (element type). The two last arguments are for
> the element type. These were added by the previous patch because
> the old VMStateInfo did not need these. So we drastically changed
> the scope of VMStateInfo with the previous patch and I'm not
> sure I like this.
> 
> I will have to stare at this a bit longer to bring something more
> constructive than these (largely feeling-based) remarks.
> 
> Cheers,
> Halil
> 

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 4/6] migration: migrate QTAILQ
  2016-10-10 21:29                           ` Jianjun Duan
@ 2016-10-11  7:33                             ` Paolo Bonzini
  0 siblings, 0 replies; 66+ messages in thread
From: Paolo Bonzini @ 2016-10-11  7:33 UTC (permalink / raw)
  To: Jianjun Duan, Halil Pasic, Dr. David Alan Gilbert
  Cc: veroniabahaa, peter.maydell, quintela, mst, mark.cave-ayland,
	mdroth, qemu-devel, blauwirbel, dmitry, qemu-ppc, kraxel, david,
	amit.shah, kwolf, mreitz, leon.alrae, aurelien, rth



On 10/10/2016 23:29, Jianjun Duan wrote:
> You are right. What we have in VMSTATE now cannot handle a recursive (or
> cyclic as you call it) structure. The idea was to use VMS_LINKED to
> indicate a recursive structure.

Sure, but it's unnecessary.  If you didn't have VMS_LINKED, no one would
notice the difference.

Yes, existing VMStateInfos didn't need the new arguments, the new one
does.  So you add the new arguments.  There's no need to add the flag.

Paolo

> In this patch is used on a queue. It can
> also be used on list or trees.
> In this regard, VMS_LINKED does represent something.

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

* Re: [Qemu-devel] [QEMU PATCH v5 1/6] migration: alternative way to set instance_id in SaveStateEntry
  2016-10-10  5:31           ` David Gibson
@ 2016-10-11 16:17             ` Michael Roth
  2016-10-11 23:37               ` David Gibson
  0 siblings, 1 reply; 66+ messages in thread
From: Michael Roth @ 2016-10-11 16:17 UTC (permalink / raw)
  To: David Gibson, Dr. David Alan Gilbert
  Cc: Jianjun Duan, qemu-devel, qemu-ppc, dmitry, peter.maydell,
	kraxel, mst, pbonzini, veroniabahaa, quintela, amit.shah, mreitz,
	kwolf, rth, aurelien, leon.alrae, blauwirbel, mark.cave-ayland

Quoting David Gibson (2016-10-10 00:31:20)
> On Fri, Oct 07, 2016 at 09:07:49AM +0100, Dr. David Alan Gilbert wrote:
> > * David Gibson (david@gibson.dropbear.id.au) wrote:
> > > On Wed, Oct 05, 2016 at 09:44:57AM -0700, Jianjun Duan wrote:
> > > > Please see comments below:
> > > > 
> > > > On 10/05/2016 03:12 AM, Dr. David Alan Gilbert wrote:
> > > > > * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> > > > >> In QOM(QEMU Object Model) migrated objects are identified with instance_id
> > > > >> which is calculated automatically using their path in the QOM composition
> > > > >> tree. For some objects, this path could change from source to target in
> > > > >> migration. To migrate such objects, we need to make sure the instance_id does
> > > > >> not change from source to target. We add a hook in DeviceClass to do customized
> > > > >> instance_id calculation in such cases.
> > > > > 
> > > > > Can you explain a bit about why the path changes from source to destination;
> > > > > the path here should be a feature of the guest state not the host, and so I
> > > > > don't understand why it changes.
> > > > Please see the discussion with David in the previous versions:
> > > > http://lists.nongnu.org/archive/html/qemu-ppc/2016-06/msg00062.html
> > > 
> > > Um.. your description above really isn't an accurate summary of that
> > > discussion.
> > > 
> > > The point is not that the qom path will vary from source to
> > > destination for some arbitrary reason, but rather that we anticipate
> > > future changes in the QOM structure.  Specifically we're considering
> > > eliminating the DRC objects, and folding their (limited) state into an
> > > array in the parent object (either the machine or a PCI host bridge).
> > > 
> > > That would change the qom paths, and hence the auto-generated instance
> > > ids, which would break migration between qemu versions before and
> > > after the restructure.
> > > 
> > > I'm not sure that changing the instance ids is enough though, anyway,
> > > since we're talking about eliminating the object entirely, the
> > > class/type information in the migration stream also wouldn't match.
> > > 
> > > Dave, if you have ideas on how to deal with that, I'd love to hear
> > > them
> > 
> > Eliminating the object entirely would be tricky to deal with;
> > allowing the structure to change would work if instead of a custom instance_id
> > you had a custom idstr.
> 
> Sorry, two misunderstandings here.
> 
>   * When I said "structure" I meant in the high-level sense of what
>     objects exist and are responsible for what things, not in the
>     'struct WhateverState' sense.
> 
>   * In fact right now eliminating the objects would be ok, since they
>     have no migration state (which causes the problems this series is
>     trying to address).  But applying this series which adds migration
>     state would make it difficult to eliminate the objects in future.
>     That's an awkward constraint given that we've already got some
>     hints that these objects are not a good idea.
> 
> > However, the question then becomes why is the structure changing so much;
> > ideally things in the migration stream should represent some tangible object
> > that corresponds to something real, but (again ideally) the contents
> > of the stream should reflect the state of those objects not the current
> > implementation - so if you want to change the implementation the stream
> > doesn't change.  Is it your implementation, or the understanding of what
> > the objects actually represent that's in flux?
> 
> So, the objects in question are DRCs - "Dynamic Re-configuration
> Connector"; silly IBM talk for "a port into which something can be
> hotplugged", bascially.  These aren't "real" devices, but rather a
> firmware/hypervisor abstraction which are used to describe a hotplug
> point.  Each DRC allows either one CPU core, one PCI device, or one
> LMB (256MiB chunk of RAM) to be hotplugged (or removed).  The PCI DRCs
> are "owned" by the PCI host bridge to which the device would be
> connected, the CPU and memory DRCs are owned by the machine.
> 
> The state variables which Jianjun Duan is adding to migration are
> values defined in the PAPR (hypervisor interface) spec, and so are
> tangible enough to be sensible to migrate.  At the moment, each LMB is
> represented by a discrete QOM object, but I've been thinking for a
> while that this may be a mistake.  In particular it's a problem for
> the LMB DRCs - because each LMB is only 256MiB of memory, we end up
> with thousands, maybe tens of thousands of DRC objects on a guest with
> with large maxmem (even if initial memory is small).  The QOM
> infrastructure doesn't deal terribly well that many object child
> properties.
> 
> The construction of those DRCs used to be an N^3 algorithm, which as
> you'd imagine caused horrible startup times with large maxmem (minutes
> to hours above ~512GiB).  We fixed it to be only N^2, so now the
> startup delays are merely bad (at least once you get to ~2TiB+
> maxmem).
> 
> We could fix that by changing QOM to use a hash or tree for object
> children, instead of a plain list, but I'm not sure if it makes sense
> to do that with only this use case.

Is that still as much an issue as of this patch?

commit b604a854e843505007c59d68112c654556102a20
Author: Pavel Fedin <p.fedin@samsung.com>
Date:   Tue Oct 13 13:37:45 2015 +0100

    qom: Replace object property list with GHashTable
    
    ARM GICv3 systems with large number of CPUs create lots of IRQ pins. Since
    every pin is represented as a property, number of these properties becomes
    very large. Every property add first makes sure there's no duplicates.
    Traversing the list becomes very slow, therefore QEMU initialization takes
    significant time (several seconds for e. g. 16 CPUs).
    
    This patch replaces list with GHashTable, making lookup very fast. The only
    drawback is that object_child_foreach() and object_child_foreach_recursive()
    cannot add or remove properties during traversal, since GHashTableIter does
    not have modify-safe version. However, the code seems not to modify objects
    via these functions.

> 
> So, for some time, I've been considering rewriting the DRC stuff to be
> implemented via QOM interface on the "owner" object, rather than
> separate objects for every single connector.

At a high-level I think I'd prefer improving QOM over working around it's
performance issues. It seems like those limits are bound to be pushed
eventually given the wide range of hardware it's meant to support
in theory.

But identifying a DRC state in the migration stream with a stable value based
on DRC index makes sense either way. If I understand this patch it seems
like we have that: if a custom instance_id getter is available, we avoid
using the QOM path for idstr and use the default of vmsd->name, then use
the instance_id from the getter. If we dropped DRCs as objects, we'd need
a mechanism other than DeviceClass->dev_get_instance_id() to provide this
custom instance_id, but otherwise so long as the state was the same, and
the VMSD was the same, it seems like it should be doable in theory.

> 
> So the difficulty is that if we add the state migration to the DRC
> objects as they stand, we prevent ourselves from doing a refactor
> that's probably a good idea.  But no-one's yet had time to actually
> thrash out such a refactor. :/
> 
> -- 
> David Gibson                    | I'll have my music baroque, and my code
> david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
>                                 | _way_ _around_!
> http://www.ozlabs.org/~dgibson

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

* Re: [Qemu-devel] [QEMU PATCH v5 1/6] migration: alternative way to set instance_id in SaveStateEntry
  2016-10-11 16:17             ` Michael Roth
@ 2016-10-11 23:37               ` David Gibson
  0 siblings, 0 replies; 66+ messages in thread
From: David Gibson @ 2016-10-11 23:37 UTC (permalink / raw)
  To: Michael Roth
  Cc: Dr. David Alan Gilbert, Jianjun Duan, qemu-devel, qemu-ppc,
	dmitry, peter.maydell, kraxel, mst, pbonzini, veroniabahaa,
	quintela, amit.shah, mreitz, kwolf, rth, aurelien, leon.alrae,
	blauwirbel, mark.cave-ayland

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

On Tue, Oct 11, 2016 at 11:17:35AM -0500, Michael Roth wrote:
> Quoting David Gibson (2016-10-10 00:31:20)
> > On Fri, Oct 07, 2016 at 09:07:49AM +0100, Dr. David Alan Gilbert wrote:
> > > * David Gibson (david@gibson.dropbear.id.au) wrote:
> > > > On Wed, Oct 05, 2016 at 09:44:57AM -0700, Jianjun Duan wrote:
> > > > > Please see comments below:
> > > > > 
> > > > > On 10/05/2016 03:12 AM, Dr. David Alan Gilbert wrote:
> > > > > > * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> > > > > >> In QOM(QEMU Object Model) migrated objects are identified with instance_id
> > > > > >> which is calculated automatically using their path in the QOM composition
> > > > > >> tree. For some objects, this path could change from source to target in
> > > > > >> migration. To migrate such objects, we need to make sure the instance_id does
> > > > > >> not change from source to target. We add a hook in DeviceClass to do customized
> > > > > >> instance_id calculation in such cases.
> > > > > > 
> > > > > > Can you explain a bit about why the path changes from source to destination;
> > > > > > the path here should be a feature of the guest state not the host, and so I
> > > > > > don't understand why it changes.
> > > > > Please see the discussion with David in the previous versions:
> > > > > http://lists.nongnu.org/archive/html/qemu-ppc/2016-06/msg00062.html
> > > > 
> > > > Um.. your description above really isn't an accurate summary of that
> > > > discussion.
> > > > 
> > > > The point is not that the qom path will vary from source to
> > > > destination for some arbitrary reason, but rather that we anticipate
> > > > future changes in the QOM structure.  Specifically we're considering
> > > > eliminating the DRC objects, and folding their (limited) state into an
> > > > array in the parent object (either the machine or a PCI host bridge).
> > > > 
> > > > That would change the qom paths, and hence the auto-generated instance
> > > > ids, which would break migration between qemu versions before and
> > > > after the restructure.
> > > > 
> > > > I'm not sure that changing the instance ids is enough though, anyway,
> > > > since we're talking about eliminating the object entirely, the
> > > > class/type information in the migration stream also wouldn't match.
> > > > 
> > > > Dave, if you have ideas on how to deal with that, I'd love to hear
> > > > them
> > > 
> > > Eliminating the object entirely would be tricky to deal with;
> > > allowing the structure to change would work if instead of a custom instance_id
> > > you had a custom idstr.
> > 
> > Sorry, two misunderstandings here.
> > 
> >   * When I said "structure" I meant in the high-level sense of what
> >     objects exist and are responsible for what things, not in the
> >     'struct WhateverState' sense.
> > 
> >   * In fact right now eliminating the objects would be ok, since they
> >     have no migration state (which causes the problems this series is
> >     trying to address).  But applying this series which adds migration
> >     state would make it difficult to eliminate the objects in future.
> >     That's an awkward constraint given that we've already got some
> >     hints that these objects are not a good idea.
> > 
> > > However, the question then becomes why is the structure changing so much;
> > > ideally things in the migration stream should represent some tangible object
> > > that corresponds to something real, but (again ideally) the contents
> > > of the stream should reflect the state of those objects not the current
> > > implementation - so if you want to change the implementation the stream
> > > doesn't change.  Is it your implementation, or the understanding of what
> > > the objects actually represent that's in flux?
> > 
> > So, the objects in question are DRCs - "Dynamic Re-configuration
> > Connector"; silly IBM talk for "a port into which something can be
> > hotplugged", bascially.  These aren't "real" devices, but rather a
> > firmware/hypervisor abstraction which are used to describe a hotplug
> > point.  Each DRC allows either one CPU core, one PCI device, or one
> > LMB (256MiB chunk of RAM) to be hotplugged (or removed).  The PCI DRCs
> > are "owned" by the PCI host bridge to which the device would be
> > connected, the CPU and memory DRCs are owned by the machine.
> > 
> > The state variables which Jianjun Duan is adding to migration are
> > values defined in the PAPR (hypervisor interface) spec, and so are
> > tangible enough to be sensible to migrate.  At the moment, each LMB is
> > represented by a discrete QOM object, but I've been thinking for a
> > while that this may be a mistake.  In particular it's a problem for
> > the LMB DRCs - because each LMB is only 256MiB of memory, we end up
> > with thousands, maybe tens of thousands of DRC objects on a guest with
> > with large maxmem (even if initial memory is small).  The QOM
> > infrastructure doesn't deal terribly well that many object child
> > properties.
> > 
> > The construction of those DRCs used to be an N^3 algorithm, which as
> > you'd imagine caused horrible startup times with large maxmem (minutes
> > to hours above ~512GiB).  We fixed it to be only N^2, so now the
> > startup delays are merely bad (at least once you get to ~2TiB+
> > maxmem).
> > 
> > We could fix that by changing QOM to use a hash or tree for object
> > children, instead of a plain list, but I'm not sure if it makes sense
> > to do that with only this use case.
> 
> Is that still as much an issue as of this patch?
> 
> commit b604a854e843505007c59d68112c654556102a20
> Author: Pavel Fedin <p.fedin@samsung.com>
> Date:   Tue Oct 13 13:37:45 2015 +0100
> 
>     qom: Replace object property list with GHashTable
>     
>     ARM GICv3 systems with large number of CPUs create lots of IRQ pins. Since
>     every pin is represented as a property, number of these properties becomes
>     very large. Every property add first makes sure there's no duplicates.
>     Traversing the list becomes very slow, therefore QEMU initialization takes
>     significant time (several seconds for e. g. 16 CPUs).
>     
>     This patch replaces list with GHashTable, making lookup very fast. The only
>     drawback is that object_child_foreach() and object_child_foreach_recursive()
>     cannot add or remove properties during traversal, since GHashTableIter does
>     not have modify-safe version. However, the code seems not to modify objects
>     via these functions.

Huh.. good point.  I'd completely forgotten that change had already
happened.

> > So, for some time, I've been considering rewriting the DRC stuff to be
> > implemented via QOM interface on the "owner" object, rather than
> > separate objects for every single connector.
> 
> At a high-level I think I'd prefer improving QOM over working around it's
> performance issues. It seems like those limits are bound to be pushed
> eventually given the wide range of hardware it's meant to support
> in theory.

Yeah, given we already have that hash, it probably makes sense to keep
the DRCs as "real" objects.

> But identifying a DRC state in the migration stream with a stable value based
> on DRC index makes sense either way. If I understand this patch it seems
> like we have that: if a custom instance_id getter is available, we avoid
> using the QOM path for idstr and use the default of vmsd->name, then use
> the instance_id from the getter. If we dropped DRCs as objects, we'd need
> a mechanism other than DeviceClass->dev_get_instance_id() to provide this
> custom instance_id, but otherwise so long as the state was the same, and
> the VMSD was the same, it seems like it should be doable in theory.

So, as noted in other comments, I'm not sure we actually need a new
mechanism for overriding the instance id.  But regardless of the
mechanism once we have a stable id based on the DRC index, yes it
should be ok to migrate the state variables of each DRC this way.

> 
> > 
> > So the difficulty is that if we add the state migration to the DRC
> > objects as they stand, we prevent ourselves from doing a refactor
> > that's probably a good idea.  But no-one's yet had time to actually
> > thrash out such a refactor. :/
> > 
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [Qemu-devel] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 3/6] migration: extend VMStateInfo Jianjun Duan
  2016-10-07 12:08   ` Dr. David Alan Gilbert
@ 2016-10-12 11:59   ` Halil Pasic
  2016-10-12 12:07     ` Paolo Bonzini
  1 sibling, 1 reply; 66+ messages in thread
From: Halil Pasic @ 2016-10-12 11:59 UTC (permalink / raw)
  To: Jianjun Duan, qemu-devel
  Cc: veroniabahaa, peter.maydell, dgilbert, mst, quintela,
	mark.cave-ayland, mdroth, mreitz, blauwirbel, amit.shah,
	qemu-ppc, kraxel, kwolf, dmitry, pbonzini, rth, leon.alrae,
	aurelien, david

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



On 10/03/2016 08:24 PM, Jianjun Duan wrote:
> Current migration code cannot handle some data structures such as
> QTAILQ in qemu/queue.h. Here we extend the signatures of put/get
> in VMStateInfo so that customized handling is supported.
> 
> Signed-off-by: Jianjun Duan <duanj@linux.vnet.ibm.com>
> ---
>  hw/net/vmxnet3.c            | 18 ++++++---
>  hw/nvram/eeprom93xx.c       |  6 ++-
>  hw/nvram/fw_cfg.c           |  6 ++-
>  hw/pci/msix.c               |  6 ++-
>  hw/pci/pci.c                | 12 ++++--
>  hw/pci/shpc.c               |  5 ++-
>  hw/scsi/scsi-bus.c          |  6 ++-
>  hw/timer/twl92230.c         |  6 ++-
>  hw/usb/redirect.c           | 18 ++++++---
>  hw/virtio/virtio-pci.c      |  6 ++-
>  hw/virtio/virtio.c          |  6 ++-
>  include/migration/vmstate.h | 10 +++--
>  migration/savevm.c          |  5 ++-
>  migration/vmstate.c         | 95 ++++++++++++++++++++++++++++-----------------
>  target-alpha/machine.c      |  5 ++-
>  target-arm/machine.c        | 12 ++++--
>  target-i386/machine.c       | 21 ++++++----
>  target-mips/machine.c       | 10 +++--
>  target-ppc/machine.c        | 10 +++--
>  target-sparc/machine.c      |  5 ++-
>  20 files changed, 171 insertions(+), 97 deletions(-)

Hi Jianjun!

I'm not happy with the intrusive nature of this patch. We end up
with a bunch of unused parameters. 

Have you considered something like:

typedef struct {
[..]
    union{
        const VMStateInfo *info;
        const VMStateLinked *linked;
    };
    enum VMStateFlags flags;
[..]
} VMStateField;

/**
*  Handle linked datastructures. VMStateField.liked s to be used
* in conjunction with VMStateField.vmsd which describes a node of
* the datastucture without the pointers representing the links.
* The links are embedded in the node starting at VMStateField.start.
* The on wire representation of the information contained in links
* and the head element if the responsibility of a particular VMStateField
* instance.  VMStateLinked is responsible for saving/loading the whole 
* sub-tree whose root is the field in question including the allocation of
* memory for the nodes. The presence of VMStateField.linked is indicated
* by the VMS_LINKED flag in VMStateField.flags.
*/
struct VMStateLinked {                                       
    const char *name;                                                           
    void (*save)(QEMUFile *f, void *pv, VMStateField *field, QJSON *vmdesc);
    int (*load)(QEMUFile *f, void *pv, VMStateField *field);                                     
    /* Maybe: size_t offset_links; */                                                    
};

IMHO this would:
* allow us to keep the good old MVStateInfo objects unmodified and
  the semantic of VMStateInfo unchanged
* make clear that VMStateLinked does not care about the calculated size
  and provide a new anchor for documentation
* if overloading the semantic of VMStateField.start is not desired we
  could put it into  VMStateLinked, if needed we could also put more
  stuff in there
* have clearer separation between special handling for (linked/certain)
  data structures and the usual scenario with the DAG.

I would also suggest unit tests in test/test-vmstate.c. Maybe with
that the vmstate migration of QTAILQ could be factored out as a separate
patch series.

Cheers,
Halil



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

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

* Re: [Qemu-devel] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-12 11:59   ` [Qemu-devel] " Halil Pasic
@ 2016-10-12 12:07     ` Paolo Bonzini
  2016-10-12 12:30       ` Halil Pasic
  2016-10-12 17:27       ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
  0 siblings, 2 replies; 66+ messages in thread
From: Paolo Bonzini @ 2016-10-12 12:07 UTC (permalink / raw)
  To: Halil Pasic, Jianjun Duan, qemu-devel
  Cc: veroniabahaa, peter.maydell, dgilbert, mst, quintela,
	mark.cave-ayland, mdroth, mreitz, blauwirbel, amit.shah,
	qemu-ppc, kraxel, kwolf, dmitry, rth, leon.alrae, aurelien,
	david



On 12/10/2016 13:59, Halil Pasic wrote:
> IMHO this would:
> * allow us to keep the good old MVStateInfo objects unmodified and
>   the semantic of VMStateInfo unchanged
> * make clear that VMStateLinked does not care about the calculated size
>   and provide a new anchor for documentation
> * if overloading the semantic of VMStateField.start is not desired we
>   could put it into  VMStateLinked, if needed we could also put more
>   stuff in there
> * have clearer separation between special handling for (linked/certain)
>   data structures and the usual scenario with the DAG.

No, I disagree.  We shouldn't be worried about making intrusive changes
to all invocations or declarations, if that leads to a simpler API.

I agree that overloading .start can be a bit ugly but you can choose to
overload .num_offset instead, which is already better.

> I would also suggest unit tests in test/test-vmstate.c. Maybe with
> that the vmstate migration of QTAILQ could be factored out as a separate
> patch series.

Yes, definitely.

Paolo

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

* Re: [Qemu-devel] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-12 12:07     ` Paolo Bonzini
@ 2016-10-12 12:30       ` Halil Pasic
  2016-10-12 14:59         ` Dr. David Alan Gilbert
  2016-10-12 17:27       ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
  1 sibling, 1 reply; 66+ messages in thread
From: Halil Pasic @ 2016-10-12 12:30 UTC (permalink / raw)
  To: Paolo Bonzini, Jianjun Duan, qemu-devel
  Cc: veroniabahaa, peter.maydell, dgilbert, mst, quintela,
	mark.cave-ayland, mdroth, mreitz, blauwirbel, amit.shah,
	qemu-ppc, kraxel, kwolf, dmitry, rth, leon.alrae, aurelien,
	david



On 10/12/2016 02:07 PM, Paolo Bonzini wrote:
> 
> On 12/10/2016 13:59, Halil Pasic wrote:
>> > IMHO this would:
>> > * allow us to keep the good old MVStateInfo objects unmodified and
>> >   the semantic of VMStateInfo unchanged
>> > * make clear that VMStateLinked does not care about the calculated size
>> >   and provide a new anchor for documentation
>> > * if overloading the semantic of VMStateField.start is not desired we
>> >   could put it into  VMStateLinked, if needed we could also put more
>> >   stuff in there
>> > * have clearer separation between special handling for (linked/certain)
>> >   data structures and the usual scenario with the DAG.
> No, I disagree.  We shouldn't be worried about making intrusive changes
> to all invocations or declarations, if that leads to a simpler API.

Paolo I agree on a theoretical level. It's just I do not see why this
particular change makes the API simpler. In my opinion this complicates
things because now all VMStateInfo's can do funky stuff. Having additional
state you can poke is rarely a simplification. Same goes for lots
of arguments especially if some of them are barely ever used. These
additional parameters contribute nothing for the large majority
of the cases (except maybe some head scratching when reading
the code).

No strong opinion here, it's just that I don't understand. I think one
trait of a simple API is that it is easy to document. Unfortunately
the documentation is quite sparse and in the patch the signature
change goes undocumented.

Well as I said, just an idea, motivated by how I understood he role of
VMStateInfo form reading the code.

Cheers,
Halil

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

* Re: [Qemu-devel] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-12 12:30       ` Halil Pasic
@ 2016-10-12 14:59         ` Dr. David Alan Gilbert
  2016-10-13 10:33           ` Halil Pasic
  0 siblings, 1 reply; 66+ messages in thread
From: Dr. David Alan Gilbert @ 2016-10-12 14:59 UTC (permalink / raw)
  To: Halil Pasic
  Cc: Paolo Bonzini, Jianjun Duan, qemu-devel, veroniabahaa,
	peter.maydell, mst, quintela, mark.cave-ayland, mdroth, mreitz,
	blauwirbel, amit.shah, qemu-ppc, kraxel, kwolf, dmitry, rth,
	leon.alrae, aurelien, david

* Halil Pasic (pasic@linux.vnet.ibm.com) wrote:
> 
> 
> On 10/12/2016 02:07 PM, Paolo Bonzini wrote:
> > 
> > On 12/10/2016 13:59, Halil Pasic wrote:
> >> > IMHO this would:
> >> > * allow us to keep the good old MVStateInfo objects unmodified and
> >> >   the semantic of VMStateInfo unchanged
> >> > * make clear that VMStateLinked does not care about the calculated size
> >> >   and provide a new anchor for documentation
> >> > * if overloading the semantic of VMStateField.start is not desired we
> >> >   could put it into  VMStateLinked, if needed we could also put more
> >> >   stuff in there
> >> > * have clearer separation between special handling for (linked/certain)
> >> >   data structures and the usual scenario with the DAG.
> > No, I disagree.  We shouldn't be worried about making intrusive changes
> > to all invocations or declarations, if that leads to a simpler API.
> 
> Paolo I agree on a theoretical level. It's just I do not see why this
> particular change makes the API simpler. In my opinion this complicates
> things because now all VMStateInfo's can do funky stuff. Having additional
> state you can poke is rarely a simplification. Same goes for lots
> of arguments especially if some of them are barely ever used. These
> additional parameters contribute nothing for the large majority
> of the cases (except maybe some head scratching when reading
> the code).

I think it might depend how many VMStateInfo's we have.
My ideal rule would be there are no .get/.put implementations outside
of migration/ and we can trust that they would never do anything silly (right?);
so the extra parameters aren't going to be misused too badly.

However, we're probably quite a way from pulling all of the weirder
.get/.put implementations back in.

Dave

> No strong opinion here, it's just that I don't understand. I think one
> trait of a simple API is that it is easy to document. Unfortunately
> the documentation is quite sparse and in the patch the signature
> change goes undocumented.
> 
> Well as I said, just an idea, motivated by how I understood he role of
> VMStateInfo form reading the code.
> 
> Cheers,
> Halil
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-12 12:07     ` Paolo Bonzini
  2016-10-12 12:30       ` Halil Pasic
@ 2016-10-12 17:27       ` Jianjun Duan
  2016-10-13  8:22         ` Paolo Bonzini
  1 sibling, 1 reply; 66+ messages in thread
From: Jianjun Duan @ 2016-10-12 17:27 UTC (permalink / raw)
  To: Paolo Bonzini, Halil Pasic, qemu-devel
  Cc: veroniabahaa, peter.maydell, dgilbert, mst, quintela,
	mark.cave-ayland, mdroth, mreitz, blauwirbel, amit.shah,
	qemu-ppc, kraxel, kwolf, dmitry, rth, leon.alrae, aurelien,
	david



On 10/12/2016 05:07 AM, Paolo Bonzini wrote:
> 
> 
> On 12/10/2016 13:59, Halil Pasic wrote:
>> IMHO this would:
>> * allow us to keep the good old MVStateInfo objects unmodified and
>>   the semantic of VMStateInfo unchanged
>> * make clear that VMStateLinked does not care about the calculated size
>>   and provide a new anchor for documentation
>> * if overloading the semantic of VMStateField.start is not desired we
>>   could put it into  VMStateLinked, if needed we could also put more
>>   stuff in there
>> * have clearer separation between special handling for (linked/certain)
>>   data structures and the usual scenario with the DAG.
> 
> No, I disagree.  We shouldn't be worried about making intrusive changes
> to all invocations or declarations, if that leads to a simpler API.
> 
If VMStateInfo was meant for complete customization, then it was missing
some parts. I think the API is indeed simpler. Just like
definition for VMStateField. Not all of its fields are used all time.

> I agree that overloading .start can be a bit ugly but you can choose to
> overload .num_offset instead, which is already better.
>
I did considered num_offset. But it is associated with an actual field.
On the other hand, start means the start position of the q in the
structure. So it is not that far stretched.

>> I would also suggest unit tests in test/test-vmstate.c. Maybe with
>> that the vmstate migration of QTAILQ could be factored out as a separate
>> patch series.
> 
> Yes, definitely.
> 
This sounds a good idea. Will do it.

> Paolo
> 
Thanks,
Jianjun

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-12 17:27       ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
@ 2016-10-13  8:22         ` Paolo Bonzini
  2016-10-13 10:48           ` Halil Pasic
  0 siblings, 1 reply; 66+ messages in thread
From: Paolo Bonzini @ 2016-10-13  8:22 UTC (permalink / raw)
  To: Jianjun Duan
  Cc: Halil Pasic, qemu-devel, veroniabahaa, peter maydell, dgilbert,
	mst, quintela, mark cave-ayland, mdroth, mreitz, blauwirbel,
	amit shah, qemu-ppc, kraxel, kwolf, dmitry, rth, leon alrae,
	aurelien, david


> > No, I disagree.  We shouldn't be worried about making intrusive changes
> > to all invocations or declarations, if that leads to a simpler API.
> 
> If VMStateInfo was meant for complete customization, then it was missing
> some parts. I think the API is indeed simpler. Just like
> definition for VMStateField. Not all of its fields are used all time.

Code moves.  We can decide how much customization to allow of VMStateInfo.

You said it: "Not all of its fields are used all time".  Likewise, not
all arguments are used all time for get/put, but it's not an issue if they
are still there!  So this patch is good, but at the same time VMS_LINKED is
pointless.

Paolo

> > I agree that overloading .start can be a bit ugly but you can choose to
> > overload .num_offset instead, which is already better.
> >
> I did considered num_offset. But it is associated with an actual field.
> On the other hand, start means the start position of the q in the
> structure. So it is not that far stretched.
> 
> >> I would also suggest unit tests in test/test-vmstate.c. Maybe with
> >> that the vmstate migration of QTAILQ could be factored out as a separate
> >> patch series.
> > 
> > Yes, definitely.
> > 
> This sounds a good idea. Will do it.
> 
> > Paolo
> > 
> Thanks,
> Jianjun
> 
> 

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

* Re: [Qemu-devel] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-12 14:59         ` Dr. David Alan Gilbert
@ 2016-10-13 10:33           ` Halil Pasic
  2016-10-13 11:12             ` Dr. David Alan Gilbert
  0 siblings, 1 reply; 66+ messages in thread
From: Halil Pasic @ 2016-10-13 10:33 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Paolo Bonzini, Jianjun Duan, qemu-devel, veroniabahaa,
	peter.maydell, mst, quintela, mark.cave-ayland, mdroth, mreitz,
	blauwirbel, amit.shah, qemu-ppc, kraxel, kwolf, dmitry, rth,
	leon.alrae, aurelien, david

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



On 10/12/2016 04:59 PM, Dr. David Alan Gilbert wrote:
>> Paolo I agree on a theoretical level. It's just I do not see why this
>> > particular change makes the API simpler. In my opinion this complicates
>> > things because now all VMStateInfo's can do funky stuff. Having additional
>> > state you can poke is rarely a simplification. Same goes for lots
>> > of arguments especially if some of them are barely ever used. These
>> > additional parameters contribute nothing for the large majority
>> > of the cases (except maybe some head scratching when reading
>> > the code).
> I think it might depend how many VMStateInfo's we have.
> My ideal rule would be there are no .get/.put implementations outside
> of migration/ and we can trust that they would never do anything silly (right?);

Your statement about ideally no .get/.put implementations outside
of migration/ is consistent with my initial understanding of VMStateInfo:
It's there to take care of the marshaling between the on wire representation
and the in memory representation of a single and preferably primitive
vmstate field (not consisting of further fields). Complex stuff like
arrays, structs, indirection via pointers and possibly allocation is
preferably handled elsewhere. So VMStateInfo is the basic building stones,
and the only place which should write to/read from the stream (in
ideal vmstate).

So in a perfect vmstate world complete type of VMStateInfo is not part of the
API (you do not care about how it's done outside vmstate/), but only the
(possibly pointers to) VMStateInfo's supported by the vmstate API.

Of course this is not realistic, at least at the moment.

On the other hand if VMStateInfo is meant for complete customization,
as Jianjun has put it, then it obviously has to be a full fledged member
of the API, and I think then your ideal rule makes no sense to me.

I also do think we will always need something for handling special
cases because we need to maintain compatibility -- see virtio migration
for example.

> so the extra parameters aren't going to be misused too badly.
> 

What would you consider bad misuse? I do not see this as a big concern
at the moment.

Cheers,
Halil

> However, we're probably quite a way from pulling all of the weirder
> .get/.put implementations back in.
> 
> Dave
> 


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

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-13  8:22         ` Paolo Bonzini
@ 2016-10-13 10:48           ` Halil Pasic
  2016-10-13 11:20             ` Paolo Bonzini
  2016-10-13 16:23             ` Jianjun Duan
  0 siblings, 2 replies; 66+ messages in thread
From: Halil Pasic @ 2016-10-13 10:48 UTC (permalink / raw)
  To: Paolo Bonzini, Jianjun Duan
  Cc: qemu-devel, veroniabahaa, peter maydell, dgilbert, mst, quintela,
	mark cave-ayland, mdroth, mreitz, blauwirbel, amit shah,
	qemu-ppc, kraxel, kwolf, dmitry, rth, leon alrae, aurelien,
	david

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



On 10/13/2016 10:22 AM, Paolo Bonzini wrote:
>>> No, I disagree.  We shouldn't be worried about making intrusive changes
>>> > > to all invocations or declarations, if that leads to a simpler API.
>> > 
>> > If VMStateInfo was meant for complete customization, then it was missing
>> > some parts. I think the API is indeed simpler. Just like
>> > definition for VMStateField. Not all of its fields are used all time.
> Code moves.  We can decide how much customization to allow of VMStateInfo.
> 
> You said it: "Not all of its fields are used all time".  Likewise, not
> all arguments are used all time for get/put, but it's not an issue if they
> are still there!  So this patch is good, but at the same time VMS_LINKED is
> pointless.
> 
> Paolo
> 

I'm fine with this. I just think, it would be nice if the contract between
the vmstate-core and the client code implementing VMStateInfo callbacks
could be documented, including when are certain parameters valid, what
they stand for, and how are they supposed to be used for the next version of
the patch. Just to improve readability. Would this be OK with everybody?

By the way the flag VMS_SINGLE is documented as ignored. Should we drop
it?



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

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

* Re: [Qemu-devel] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-13 10:33           ` Halil Pasic
@ 2016-10-13 11:12             ` Dr. David Alan Gilbert
  0 siblings, 0 replies; 66+ messages in thread
From: Dr. David Alan Gilbert @ 2016-10-13 11:12 UTC (permalink / raw)
  To: Halil Pasic
  Cc: Paolo Bonzini, Jianjun Duan, qemu-devel, veroniabahaa,
	peter.maydell, mst, quintela, mark.cave-ayland, mdroth, mreitz,
	blauwirbel, amit.shah, qemu-ppc, kraxel, kwolf, dmitry, rth,
	leon.alrae, aurelien, david

* Halil Pasic (pasic@linux.vnet.ibm.com) wrote:
> 
> 
> On 10/12/2016 04:59 PM, Dr. David Alan Gilbert wrote:
> >> Paolo I agree on a theoretical level. It's just I do not see why this
> >> > particular change makes the API simpler. In my opinion this complicates
> >> > things because now all VMStateInfo's can do funky stuff. Having additional
> >> > state you can poke is rarely a simplification. Same goes for lots
> >> > of arguments especially if some of them are barely ever used. These
> >> > additional parameters contribute nothing for the large majority
> >> > of the cases (except maybe some head scratching when reading
> >> > the code).
> > I think it might depend how many VMStateInfo's we have.
> > My ideal rule would be there are no .get/.put implementations outside
> > of migration/ and we can trust that they would never do anything silly (right?);
> 
> Your statement about ideally no .get/.put implementations outside
> of migration/ is consistent with my initial understanding of VMStateInfo:
> It's there to take care of the marshaling between the on wire representation
> and the in memory representation of a single and preferably primitive
> vmstate field (not consisting of further fields). Complex stuff like
> arrays, structs, indirection via pointers and possibly allocation is
> preferably handled elsewhere. So VMStateInfo is the basic building stones,
> and the only place which should write to/read from the stream (in
> ideal vmstate).
> 
> So in a perfect vmstate world complete type of VMStateInfo is not part of the
> API (you do not care about how it's done outside vmstate/), but only the
> (possibly pointers to) VMStateInfo's supported by the vmstate API.
> 
> Of course this is not realistic, at least at the moment.
> 
> On the other hand if VMStateInfo is meant for complete customization,
> as Jianjun has put it, then it obviously has to be a full fledged member
> of the API, and I think then your ideal rule makes no sense to me.
> 
> I also do think we will always need something for handling special
> cases because we need to maintain compatibility -- see virtio migration
> for example.
> 
> > so the extra parameters aren't going to be misused too badly.
> > 
> 
> What would you consider bad misuse? I do not see this as a big concern
> at the moment.

I don't know; but the only justification for needing the VMS_LINKED flag
was that only those functions that were marked with VMS_LINKED would
be passed the new field.

Dave

> Cheers,
> Halil
> 
> > However, we're probably quite a way from pulling all of the weirder
> > .get/.put implementations back in.
> > 
> > Dave
> > 
> 



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

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-13 10:48           ` Halil Pasic
@ 2016-10-13 11:20             ` Paolo Bonzini
  2016-10-13 16:23             ` Jianjun Duan
  1 sibling, 0 replies; 66+ messages in thread
From: Paolo Bonzini @ 2016-10-13 11:20 UTC (permalink / raw)
  To: Halil Pasic, Jianjun Duan
  Cc: qemu-devel, veroniabahaa, peter maydell, dgilbert, mst, quintela,
	mark cave-ayland, mdroth, mreitz, blauwirbel, amit shah,
	qemu-ppc, kraxel, kwolf, dmitry, rth, leon alrae, aurelien,
	david



On 13/10/2016 12:48, Halil Pasic wrote:
>> > 
> I'm fine with this. I just think, it would be nice if the contract between
> the vmstate-core and the client code implementing VMStateInfo callbacks
> could be documented, including when are certain parameters valid, what
> they stand for, and how are they supposed to be used for the next version of
> the patch. Just to improve readability. Would this be OK with everybody?
> 
> By the way the flag VMS_SINGLE is documented as ignored. Should we drop
> it?

Yes, I think so.

Paolo

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-13 10:48           ` Halil Pasic
  2016-10-13 11:20             ` Paolo Bonzini
@ 2016-10-13 16:23             ` Jianjun Duan
  2016-10-13 16:32               ` Halil Pasic
  1 sibling, 1 reply; 66+ messages in thread
From: Jianjun Duan @ 2016-10-13 16:23 UTC (permalink / raw)
  To: Halil Pasic, Paolo Bonzini
  Cc: qemu-devel, veroniabahaa, peter maydell, dgilbert, mst, quintela,
	mark cave-ayland, mdroth, mreitz, blauwirbel, amit shah,
	qemu-ppc, kraxel, kwolf, dmitry, rth, leon alrae, aurelien,
	david



On 10/13/2016 03:48 AM, Halil Pasic wrote:
> 
> 
> On 10/13/2016 10:22 AM, Paolo Bonzini wrote:
>>>> No, I disagree.  We shouldn't be worried about making intrusive changes
>>>>>> to all invocations or declarations, if that leads to a simpler API.
>>>>
>>>> If VMStateInfo was meant for complete customization, then it was missing
>>>> some parts. I think the API is indeed simpler. Just like
>>>> definition for VMStateField. Not all of its fields are used all time.
>> Code moves.  We can decide how much customization to allow of VMStateInfo.
>>
>> You said it: "Not all of its fields are used all time".  Likewise, not
>> all arguments are used all time for get/put, but it's not an issue if they
>> are still there!  So this patch is good, but at the same time VMS_LINKED is
>> pointless.
>>
>> Paolo
>>
> 
> I'm fine with this. I just think, it would be nice if the contract between
> the vmstate-core and the client code implementing VMStateInfo callbacks
> could be documented, including when are certain parameters valid, what
> they stand for, and how are they supposed to be used for the next version of
> the patch. Just to improve readability. Would this be OK with everybody?
> 
> By the way the flag VMS_SINGLE is documented as ignored. Should we drop
> it?
> 
I will prepare the VMStateInfo and QTAIL stuff as a separated series. If
indeed VMS_SINGLE is ignored, I can drop it here. It is similar to
VMS_LINKED situation.

Thanks,
Jianjun
> 

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-13 16:23             ` Jianjun Duan
@ 2016-10-13 16:32               ` Halil Pasic
  2016-10-13 16:35                 ` Jianjun Duan
  0 siblings, 1 reply; 66+ messages in thread
From: Halil Pasic @ 2016-10-13 16:32 UTC (permalink / raw)
  To: Jianjun Duan, Paolo Bonzini
  Cc: qemu-devel, veroniabahaa, peter maydell, dgilbert, mst, quintela,
	mark cave-ayland, mdroth, mreitz, blauwirbel, amit shah,
	qemu-ppc, kraxel, kwolf, dmitry, rth, leon alrae, aurelien,
	david



On 10/13/2016 06:23 PM, Jianjun Duan wrote:
> 
> 
> On 10/13/2016 03:48 AM, Halil Pasic wrote:
>>
>>
>> On 10/13/2016 10:22 AM, Paolo Bonzini wrote:
>>>>> No, I disagree.  We shouldn't be worried about making intrusive changes
>>>>>>> to all invocations or declarations, if that leads to a simpler API.
>>>>>
>>>>> If VMStateInfo was meant for complete customization, then it was missing
>>>>> some parts. I think the API is indeed simpler. Just like
>>>>> definition for VMStateField. Not all of its fields are used all time.
>>> Code moves.  We can decide how much customization to allow of VMStateInfo.
>>>
>>> You said it: "Not all of its fields are used all time".  Likewise, not
>>> all arguments are used all time for get/put, but it's not an issue if they
>>> are still there!  So this patch is good, but at the same time VMS_LINKED is
>>> pointless.
>>>
>>> Paolo
>>>
>>
>> I'm fine with this. I just think, it would be nice if the contract between
>> the vmstate-core and the client code implementing VMStateInfo callbacks
>> could be documented, including when are certain parameters valid, what
>> they stand for, and how are they supposed to be used for the next version of
>> the patch. Just to improve readability. Would this be OK with everybody?
>>
>> By the way the flag VMS_SINGLE is documented as ignored. Should we drop
>> it?
>>
> I will prepare the VMStateInfo and QTAIL stuff as a separated series. If
> indeed VMS_SINGLE is ignored, I can drop it here. It is similar to
> VMS_LINKED situation.
> 
> Thanks,
> Jianjun

I think it's completely unrelated, so I would not lump it together with
the QTAILQ stuff.

How do you feel about the apidoc part?

Cheers,
Halil

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

* Re: [Qemu-devel] [Qemu-ppc] [QEMU PATCH v5 3/6] migration: extend VMStateInfo
  2016-10-13 16:32               ` Halil Pasic
@ 2016-10-13 16:35                 ` Jianjun Duan
  0 siblings, 0 replies; 66+ messages in thread
From: Jianjun Duan @ 2016-10-13 16:35 UTC (permalink / raw)
  To: Halil Pasic, Paolo Bonzini
  Cc: qemu-devel, veroniabahaa, peter maydell, dgilbert, mst, quintela,
	mark cave-ayland, mdroth, mreitz, blauwirbel, amit shah,
	qemu-ppc, kraxel, kwolf, dmitry, rth, leon alrae, aurelien,
	david



On 10/13/2016 09:32 AM, Halil Pasic wrote:
> 
> 
> On 10/13/2016 06:23 PM, Jianjun Duan wrote:
>>
>>
>> On 10/13/2016 03:48 AM, Halil Pasic wrote:
>>>
>>>
>>> On 10/13/2016 10:22 AM, Paolo Bonzini wrote:
>>>>>> No, I disagree.  We shouldn't be worried about making intrusive changes
>>>>>>>> to all invocations or declarations, if that leads to a simpler API.
>>>>>>
>>>>>> If VMStateInfo was meant for complete customization, then it was missing
>>>>>> some parts. I think the API is indeed simpler. Just like
>>>>>> definition for VMStateField. Not all of its fields are used all time.
>>>> Code moves.  We can decide how much customization to allow of VMStateInfo.
>>>>
>>>> You said it: "Not all of its fields are used all time".  Likewise, not
>>>> all arguments are used all time for get/put, but it's not an issue if they
>>>> are still there!  So this patch is good, but at the same time VMS_LINKED is
>>>> pointless.
>>>>
>>>> Paolo
>>>>
>>>
>>> I'm fine with this. I just think, it would be nice if the contract between
>>> the vmstate-core and the client code implementing VMStateInfo callbacks
>>> could be documented, including when are certain parameters valid, what
>>> they stand for, and how are they supposed to be used for the next version of
>>> the patch. Just to improve readability. Would this be OK with everybody?
>>>
>>> By the way the flag VMS_SINGLE is documented as ignored. Should we drop
>>> it?
>>>
>> I will prepare the VMStateInfo and QTAIL stuff as a separated series. If
>> indeed VMS_SINGLE is ignored, I can drop it here. It is similar to
>> VMS_LINKED situation.
>>
>> Thanks,
>> Jianjun
> 
> I think it's completely unrelated, so I would not lump it together with
> the QTAILQ stuff.
> 
> How do you feel about the apidoc part?
> 
I will add some comments inside vmstate_save/load_state about it.

Thanks,
Jianjun

> Cheers,
> Halil
> 

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

* Re: [Qemu-devel] [QEMU PATCH v5 1/6] migration: alternative way to set instance_id in SaveStateEntry
  2016-10-07  2:54       ` David Gibson
  2016-10-07  8:07         ` Dr. David Alan Gilbert
@ 2016-11-15 23:45         ` Michael Roth
  1 sibling, 0 replies; 66+ messages in thread
From: Michael Roth @ 2016-11-15 23:45 UTC (permalink / raw)
  To: David Gibson, Jianjun Duan
  Cc: Dr. David Alan Gilbert, qemu-devel, qemu-ppc, dmitry,
	peter.maydell, kraxel, mst, pbonzini, veroniabahaa, quintela,
	amit.shah, mreitz, kwolf, rth, aurelien, leon.alrae, blauwirbel,
	mark.cave-ayland

Quoting David Gibson (2016-10-06 21:54:42)
> On Wed, Oct 05, 2016 at 09:44:57AM -0700, Jianjun Duan wrote:
> > Please see comments below:
> > 
> > On 10/05/2016 03:12 AM, Dr. David Alan Gilbert wrote:
> > > * Jianjun Duan (duanj@linux.vnet.ibm.com) wrote:
> > >> In QOM(QEMU Object Model) migrated objects are identified with instance_id
> > >> which is calculated automatically using their path in the QOM composition
> > >> tree. For some objects, this path could change from source to target in
> > >> migration. To migrate such objects, we need to make sure the instance_id does
> > >> not change from source to target. We add a hook in DeviceClass to do customized
> > >> instance_id calculation in such cases.
> > > 
> > > Can you explain a bit about why the path changes from source to destination;
> > > the path here should be a feature of the guest state not the host, and so I
> > > don't understand why it changes.
> > Please see the discussion with David in the previous versions:
> > http://lists.nongnu.org/archive/html/qemu-ppc/2016-06/msg00062.html
> 
> Um.. your description above really isn't an accurate summary of that
> discussion.
> 
> The point is not that the qom path will vary from source to
> destination for some arbitrary reason, but rather that we anticipate
> future changes in the QOM structure.  Specifically we're considering
> eliminating the DRC objects, and folding their (limited) state into an
> array in the parent object (either the machine or a PCI host bridge).
> 
> That would change the qom paths, and hence the auto-generated instance
> ids, which would break migration between qemu versions before and
> after the restructure.
> 
> I'm not sure that changing the instance ids is enough though, anyway,
> since we're talking about eliminating the object entirely, the
> class/type information in the migration stream also wouldn't match.
> 
> Dave, if you have ideas on how to deal with that, I'd love to hear
> them
> 
> > 
> > >> As a result, in these cases compat will not be set in the concerned
> > >> SaveStateEntry. This will prevent the inconsistent idstr to be sent over in
> > >> migration. We could have set alias_id in a similar way. But that will be
> > >> overloading the purpose of alias_id.
> > >>
> > >> The first application will be setting instance_id for DRC using its unique
> > >> index. Doing this makes the instance_id of DRC to be consistent across migration
> > >> and supports flexible management of DRC objects in migration.
> > > 
> > > Is there a reason to use a custom instance_id rather than a custom idstr
> > 
> > It can be done either way. But it is easier to deal with a integer than
> > a string.
> 
> A bit, but I don't think that's a good enough reason to introduce a
> second mechanism for overriding instance id allocations.

I'm looking at picking up this patch and the next for DRC migration
since it turns out it's needed to fix memory unplug after migration.

I think the gist of it is that vmstate_register() doesn't provide
a way to specify a custom idstr, and instead relies on vmsd->name
 (or qom-path for Devices), only register_savevm_live() does. Both
however provide a way of specifying a custom instance_id. The only
real issue is that in the case of Devices we end up ignoring the
instance_id. So I propose using the existing interface to set the
instance_id, and relegating all knowledge of
DeviceClass->dev_get_instance_id() to qdev (and other callers
as-needed). Maybe something like this?

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index d835e62..7323152 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -933,7 +933,11 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
         }
 
         if (qdev_get_vmsd(dev)) {
-            vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
+            int instance_id = DEVICE_GET_CLASS(dev)->dev_get_instance_id
+                ? DEVICE_GET_CLASS(dev)->dev_get_instance_id(dev)
+                : -1;
+
+            vmstate_register_with_alias_id(dev, instance_id, qdev_get_vmsd(dev), dev,
                                            dev->instance_id_alias,
                                            dev->alias_required_for_version);
         }
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 2c97347..a012e8e 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -139,6 +139,12 @@ typedef struct DeviceClass {
     qdev_initfn init; /* TODO remove, once users are converted to realize */
     qdev_event exit; /* TODO remove, once users are converted to unrealize */
     const char *bus_type;
+
+    /* When this field is set, qemu will use it to get an unique instance_id
+     * instead of calculating an auto idstr and instanc_id for the relevant
+     * SaveStateEntry
+     */
+    int (*dev_get_instance_id)(DeviceState *dev);
 } DeviceClass;
 
 typedef struct NamedGPIOList NamedGPIOList;
diff --git a/migration/savevm.c b/migration/savevm.c
index 0363372..a95fff9 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -556,7 +556,7 @@ int register_savevm_live(DeviceState *dev,
         se->is_ram = 1;
     }
 
-    if (dev) {
+    if (dev && instance_id == -1) {
         char *id = qdev_get_dev_path(dev);
         if (id) {
             pstrcpy(se->idstr, sizeof(se->idstr), id);
@@ -640,7 +640,7 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
     se->vmsd = vmsd;
     se->alias_id = alias_id;
 
-    if (dev) {
+    if (dev && instance_id == -1) {
         char *id = qdev_get_dev_path(dev);
         if (id) {
             pstrcpy(se->idstr, sizeof(se->idstr), id);

> 
> -- 
> David Gibson                    | I'll have my music baroque, and my code
> david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
>                                 | _way_ _around_!
> http://www.ozlabs.org/~dgibson

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

end of thread, other threads:[~2016-11-15 23:45 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-03 18:24 [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together Jianjun Duan
2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 1/6] migration: alternative way to set instance_id in SaveStateEntry Jianjun Duan
2016-10-05 10:12   ` Dr. David Alan Gilbert
2016-10-05 16:44     ` Jianjun Duan
2016-10-07  2:54       ` David Gibson
2016-10-07  8:07         ` Dr. David Alan Gilbert
2016-10-10  5:31           ` David Gibson
2016-10-11 16:17             ` Michael Roth
2016-10-11 23:37               ` David Gibson
2016-11-15 23:45         ` Michael Roth
2016-10-05 16:46     ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 2/6] migration: spapr_drc: defined VMStateDescription struct Jianjun Duan
2016-10-05 11:38   ` Dr. David Alan Gilbert
2016-10-07  3:17     ` David Gibson
2016-10-07  3:12   ` David Gibson
2016-10-07 17:17     ` Jianjun Duan
2016-10-10  5:09       ` David Gibson
2016-10-10 16:48         ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 3/6] migration: extend VMStateInfo Jianjun Duan
2016-10-07 12:08   ` Dr. David Alan Gilbert
2016-10-07 16:35     ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
2016-10-07 18:42       ` Dr. David Alan Gilbert
2016-10-10  5:02         ` David Gibson
2016-10-12 11:59   ` [Qemu-devel] " Halil Pasic
2016-10-12 12:07     ` Paolo Bonzini
2016-10-12 12:30       ` Halil Pasic
2016-10-12 14:59         ` Dr. David Alan Gilbert
2016-10-13 10:33           ` Halil Pasic
2016-10-13 11:12             ` Dr. David Alan Gilbert
2016-10-12 17:27       ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
2016-10-13  8:22         ` Paolo Bonzini
2016-10-13 10:48           ` Halil Pasic
2016-10-13 11:20             ` Paolo Bonzini
2016-10-13 16:23             ` Jianjun Duan
2016-10-13 16:32               ` Halil Pasic
2016-10-13 16:35                 ` Jianjun Duan
2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 4/6] migration: migrate QTAILQ Jianjun Duan
2016-10-05 16:56   ` Dr. David Alan Gilbert
2016-10-05 17:19     ` Jianjun Duan
2016-10-06 19:01       ` Dr. David Alan Gilbert
2016-10-06 19:49         ` Jianjun Duan
2016-10-07  3:25         ` David Gibson
2016-10-07 14:31         ` Paolo Bonzini
2016-10-07 14:34           ` Dr. David Alan Gilbert
2016-10-07 16:31             ` [Qemu-devel] [Qemu-ppc] " Jianjun Duan
2016-10-07 16:32               ` Paolo Bonzini
2016-10-07 17:25                 ` Jianjun Duan
2016-10-07 17:34                   ` Dr. David Alan Gilbert
2016-10-07 17:43                     ` Jianjun Duan
2016-10-08 11:37                       ` Paolo Bonzini
2016-10-08 19:28                         ` Halil Pasic
2016-10-10 21:29                           ` Jianjun Duan
2016-10-11  7:33                             ` Paolo Bonzini
2016-10-10 21:40                           ` Jianjun Duan
2016-10-06 11:05     ` [Qemu-devel] " Paolo Bonzini
2016-10-06 11:56       ` Dr. David Alan Gilbert
2016-10-06 12:23         ` Paolo Bonzini
2016-10-06 15:21           ` Dr. David Alan Gilbert
2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 5/6] migration: spapr: migrate ccs_list in spapr state Jianjun Duan
2016-10-07  3:36   ` David Gibson
2016-10-07 14:52     ` Michael Roth
2016-10-10  5:05       ` David Gibson
2016-10-03 18:24 ` [Qemu-devel] [QEMU PATCH v5 6/6] migration: spapr: migrate pending_events of " Jianjun Duan
2016-10-03 18:35 ` [Qemu-devel] [QEMU PATCH v5 0/6] migration: ensure hotplug and migration work together no-reply
2016-10-03 19:00 ` no-reply
2016-10-03 19:11 ` Jianjun Duan

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.