s390x: vmstatify config migration for virtio-ccw

Let's vmstatify virtio_ccw_save_config and virtio_ccw_load_config for
flexibility (extending using subsections) and for fun.

To achieve this we need to hack the config_vector, which is VirtIODevice
(that is common virtio) state, in the middle of the VirtioCcwDevice state
representation.  This is somewhat ugly, but we have no choice because the
stream format needs to be preserved.

Almost no changes in behavior. Exception is everything that comes with
vmstate like extra bookkeeping about what's in the stream, and maybe some
extra checks and better error reporting.

Signed-off-by: Halil Pasic <pasic@linux.vnet.ibm.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Message-Id: <20170703213414.94298-1-pasic@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
This commit is contained in:
Halil Pasic 2017-07-03 23:34:14 +02:00 committed by Christian Borntraeger
parent 2185c93ba8
commit 517ff12c7d
7 changed files with 358 additions and 237 deletions

View file

@ -34,9 +34,87 @@
#include "virtio-ccw.h"
#include "trace.h"
#include "hw/s390x/css-bridge.h"
#include "hw/s390x/s390-virtio-ccw.h"
#define NR_CLASSIC_INDICATOR_BITS 64
static int virtio_ccw_dev_post_load(void *opaque, int version_id)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(opaque);
CcwDevice *ccw_dev = CCW_DEVICE(dev);
CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
ccw_dev->sch->driver_data = dev;
if (ccw_dev->sch->thinint_active) {
dev->routes.adapter.adapter_id = css_get_adapter_id(
CSS_IO_ADAPTER_VIRTIO,
dev->thinint_isc);
}
/* Re-fill subch_id after loading the subchannel states.*/
if (ck->refill_ids) {
ck->refill_ids(ccw_dev);
}
return 0;
}
typedef struct VirtioCcwDeviceTmp {
VirtioCcwDevice *parent;
uint16_t config_vector;
} VirtioCcwDeviceTmp;
static void virtio_ccw_dev_tmp_pre_save(void *opaque)
{
VirtioCcwDeviceTmp *tmp = opaque;
VirtioCcwDevice *dev = tmp->parent;
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
tmp->config_vector = vdev->config_vector;
}
static int virtio_ccw_dev_tmp_post_load(void *opaque, int version_id)
{
VirtioCcwDeviceTmp *tmp = opaque;
VirtioCcwDevice *dev = tmp->parent;
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
vdev->config_vector = tmp->config_vector;
return 0;
}
const VMStateDescription vmstate_virtio_ccw_dev_tmp = {
.name = "s390_virtio_ccw_dev_tmp",
.pre_save = virtio_ccw_dev_tmp_pre_save,
.post_load = virtio_ccw_dev_tmp_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT16(config_vector, VirtioCcwDeviceTmp),
VMSTATE_END_OF_LIST()
}
};
const VMStateDescription vmstate_virtio_ccw_dev = {
.name = "s390_virtio_ccw_dev",
.version_id = 1,
.minimum_version_id = 1,
.post_load = virtio_ccw_dev_post_load,
.fields = (VMStateField[]) {
VMSTATE_CCW_DEVICE(parent_obj, VirtioCcwDevice),
VMSTATE_PTR_TO_IND_ADDR(indicators, VirtioCcwDevice),
VMSTATE_PTR_TO_IND_ADDR(indicators2, VirtioCcwDevice),
VMSTATE_PTR_TO_IND_ADDR(summary_indicator, VirtioCcwDevice),
/*
* Ugly hack because VirtIODevice does not migrate itself.
* This also makes legacy via vmstate_save_state possible.
*/
VMSTATE_WITH_TMP(VirtioCcwDevice, VirtioCcwDeviceTmp,
vmstate_virtio_ccw_dev_tmp),
VMSTATE_STRUCT(routes, VirtioCcwDevice, 1, vmstate_adapter_routes,
AdapterRoutes),
VMSTATE_UINT8(thinint_isc, VirtioCcwDevice),
VMSTATE_INT32(revision, VirtioCcwDevice),
VMSTATE_END_OF_LIST()
}
};
static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
VirtioCcwDevice *dev);
@ -1239,89 +1317,13 @@ static int virtio_ccw_load_queue(DeviceState *d, int n, QEMUFile *f)
static void virtio_ccw_save_config(DeviceState *d, QEMUFile *f)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
CcwDevice *ccw_dev = CCW_DEVICE(d);
SubchDev *s = ccw_dev->sch;
VirtIODevice *vdev = virtio_ccw_get_vdev(s);
subch_device_save(s, f);
if (dev->indicators != NULL) {
qemu_put_be32(f, dev->indicators->len);
qemu_put_be64(f, dev->indicators->addr);
} else {
qemu_put_be32(f, 0);
qemu_put_be64(f, 0UL);
}
if (dev->indicators2 != NULL) {
qemu_put_be32(f, dev->indicators2->len);
qemu_put_be64(f, dev->indicators2->addr);
} else {
qemu_put_be32(f, 0);
qemu_put_be64(f, 0UL);
}
if (dev->summary_indicator != NULL) {
qemu_put_be32(f, dev->summary_indicator->len);
qemu_put_be64(f, dev->summary_indicator->addr);
} else {
qemu_put_be32(f, 0);
qemu_put_be64(f, 0UL);
}
qemu_put_be16(f, vdev->config_vector);
qemu_put_be64(f, dev->routes.adapter.ind_offset);
qemu_put_byte(f, dev->thinint_isc);
qemu_put_be32(f, dev->revision);
vmstate_save_state(f, &vmstate_virtio_ccw_dev, dev, NULL);
}
static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
CcwDevice *ccw_dev = CCW_DEVICE(d);
CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
SubchDev *s = ccw_dev->sch;
VirtIODevice *vdev = virtio_ccw_get_vdev(s);
int len;
int ret;
s->driver_data = dev;
ret = subch_device_load(s, f);
if (ret) {
return ret;
}
/* Re-fill subch_id after loading the subchannel states.*/
if (ck->refill_ids) {
ck->refill_ids(ccw_dev);
}
len = qemu_get_be32(f);
if (len != 0) {
dev->indicators = get_indicator(qemu_get_be64(f), len);
} else {
qemu_get_be64(f);
dev->indicators = NULL;
}
len = qemu_get_be32(f);
if (len != 0) {
dev->indicators2 = get_indicator(qemu_get_be64(f), len);
} else {
qemu_get_be64(f);
dev->indicators2 = NULL;
}
len = qemu_get_be32(f);
if (len != 0) {
dev->summary_indicator = get_indicator(qemu_get_be64(f), len);
} else {
qemu_get_be64(f);
dev->summary_indicator = NULL;
}
qemu_get_be16s(f, &vdev->config_vector);
dev->routes.adapter.ind_offset = qemu_get_be64(f);
dev->thinint_isc = qemu_get_byte(f);
dev->revision = qemu_get_be32(f);
if (s->thinint_active) {
dev->routes.adapter.adapter_id = css_get_adapter_id(
CSS_IO_ADAPTER_VIRTIO,
dev->thinint_isc);
}
return 0;
return vmstate_load_state(f, &vmstate_virtio_ccw_dev, dev, 1);
}
static void virtio_ccw_pre_plugged(DeviceState *d, Error **errp)