Signed-off-by: Michael Roth <mdr...@linux.vnet.ibm.com> --- hw/virtio.c | 122 ++++++++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 92 insertions(+), 30 deletions(-)
diff --git a/hw/virtio.c b/hw/virtio.c index 7011b5b..0471c54 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -733,53 +733,93 @@ void virtio_notify_config(VirtIODevice *vdev) void virtio_save(VirtIODevice *vdev, QEMUFile *f) { int i; + Visitor *v = qemu_file_get_visitor(f); + Error *err = NULL; + uint8_t *config; + uint64_t tmp; - if (vdev->binding->save_config) + visit_start_struct(v, NULL, NULL, "vdev", 0, &err); + + if (vdev->binding->save_config) { vdev->binding->save_config(vdev->binding_opaque, f); + } - qemu_put_8s(f, &vdev->status); - qemu_put_8s(f, &vdev->isr); - qemu_put_be16s(f, &vdev->queue_sel); - qemu_put_be32s(f, &vdev->guest_features); - qemu_put_be32(f, vdev->config_len); - qemu_put_buffer(f, vdev->config, vdev->config_len); + visit_type_uint8(v, &vdev->status, "status", &err); + visit_type_uint8(v, &vdev->isr, "isr", &err); + visit_type_uint16(v, &vdev->queue_sel, "queue_sel", &err); + visit_type_uint32(v, &vdev->guest_features, "guest_features", &err); + visit_type_uint32(v, (uint32_t *)&vdev->config_len, "config_len", &err); + visit_start_array(v, (void**)&vdev->config, "config", vdev->config_len, + sizeof(*config), &err); + config = vdev->config; + for (i = 0; i < vdev->config_len; i++) { + visit_type_uint8(v, &config[i], NULL, &err); + } + visit_end_array(v, &err); for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) { - if (vdev->vq[i].vring.num == 0) + if (vdev->vq[i].vring.num == 0) { break; + } } + visit_type_uint32(v, (uint32_t *)&i, "vq_count", &err); - qemu_put_be32(f, i); - + visit_start_list(v, "vq_info", &err); for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) { - if (vdev->vq[i].vring.num == 0) + if (vdev->vq[i].vring.num == 0) { break; + } - qemu_put_be32(f, vdev->vq[i].vring.num); - qemu_put_be64(f, vdev->vq[i].pa); - qemu_put_be16s(f, &vdev->vq[i].last_avail_idx); - if (vdev->binding->save_queue) + visit_start_struct(v, NULL, NULL, NULL, 0, &err); + + visit_type_uint32(v, &vdev->vq[i].vring.num, "vring.num", &err); + /* pa can be 32 or 64-bit depending on target, and legacy QEMUFile + * protocol expects a 64-bit, so stick with this for now + */ + tmp = vdev->vq[i].pa; + visit_type_uint64(v, &tmp, "pa", &err); + visit_type_uint16(v, &vdev->vq[i].last_avail_idx, "last_avail_idx", + &err); + if (vdev->binding->save_queue) { vdev->binding->save_queue(vdev->binding_opaque, i, f); + } + + visit_end_struct(v, &err); + } + visit_end_list(v, &err); + + visit_end_struct(v, &err); + + if (err) { + error_report("error saving virtio state: %s", error_get_pretty(err)); + error_free(err); } } int virtio_load(VirtIODevice *vdev, QEMUFile *f) { - int num, i, ret; + uint32_t num, i, ret; uint32_t features; uint32_t supported_features = vdev->binding->get_features(vdev->binding_opaque); + Visitor *v = qemu_file_get_visitor(f); + Error *err = NULL; + uint8_t *config; + uint64_t tmp; + + visit_start_struct(v, NULL, NULL, "vdev", 0, &err); if (vdev->binding->load_config) { ret = vdev->binding->load_config(vdev->binding_opaque, f); - if (ret) + if (ret) { return ret; + } } - qemu_get_8s(f, &vdev->status); - qemu_get_8s(f, &vdev->isr); - qemu_get_be16s(f, &vdev->queue_sel); - qemu_get_be32s(f, &features); + visit_type_uint8(v, &vdev->status, "status", &err); + visit_type_uint8(v, &vdev->isr, "isr", &err); + visit_type_uint16(v, &vdev->queue_sel, "queue_sel", &err); + visit_type_uint32(v, &features, "guest_features", &err); if (features & ~supported_features) { error_report("Features 0x%x unsupported. Allowed features: 0x%x", features, supported_features); @@ -788,15 +828,26 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f) if (vdev->set_features) vdev->set_features(vdev, features); vdev->guest_features = features; - vdev->config_len = qemu_get_be32(f); - qemu_get_buffer(f, vdev->config, vdev->config_len); + visit_type_uint32(v, (uint32_t *)&vdev->config_len, "config_len", &err); + visit_start_array(v, (void **)&vdev->config, "config", vdev->config_len, + sizeof(*config), &err); + config = vdev->config; + for (i = 0; i < vdev->config_len; i++) { + visit_type_uint8(v, &config[i], NULL, &err); + } + visit_end_array(v, &err); - num = qemu_get_be32(f); + visit_type_uint32(v, &num, "vq_count", &err); + visit_start_list(v, "vq_info", &err); for (i = 0; i < num; i++) { - vdev->vq[i].vring.num = qemu_get_be32(f); - vdev->vq[i].pa = qemu_get_be64(f); - qemu_get_be16s(f, &vdev->vq[i].last_avail_idx); + visit_start_struct(v, NULL, NULL, NULL, 0, &err); + + visit_type_uint32(v, &vdev->vq[i].vring.num, "vring.num", &err); + visit_type_uint64(v, &tmp, "pa", &err); + vdev->vq[i].pa = tmp; + visit_type_uint16(v, &vdev->vq[i].last_avail_idx, "last_avail_idx", + &err); vdev->vq[i].signalled_used_valid = false; vdev->vq[i].notification = true; @@ -817,13 +868,24 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f) error_report("VQ %d address 0x0 " "inconsistent with Host index 0x%x", i, vdev->vq[i].last_avail_idx); - return -1; - } + return -1; + } if (vdev->binding->load_queue) { ret = vdev->binding->load_queue(vdev->binding_opaque, i, f); - if (ret) + if (ret) { return ret; + } } + visit_end_struct(v, &err); + } + visit_end_list(v, &err); + + visit_end_struct(v, &err); + + if (err) { + error_report("error loading virtio state: %s", error_get_pretty(err)); + error_free(err); + return -1; } virtio_notify_vector(vdev, VIRTIO_NO_VECTOR); -- 1.7.4.1