Signed-off-by: Michael Roth <mdr...@linux.vnet.ibm.com> --- hw/virtio-serial-bus.c | 126 ++++++++++++++++++++++++++++++++++------------- 1 files changed, 91 insertions(+), 35 deletions(-)
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index a4825b9..78cd643 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -521,21 +521,28 @@ static void virtio_serial_save(QEMUFile *f, void *opaque) VirtIOSerialPort *port; uint32_t nr_active_ports; unsigned int i, max_nr_ports; + uint8_t *buf; + Visitor *v = qemu_file_get_visitor(f); + Error *err = NULL; + + visit_start_struct(v, NULL, NULL, "virtio_serial", 0, &err); /* The virtio device */ virtio_save(&s->vdev, f); /* The config space */ - qemu_put_be16s(f, &s->config.cols); - qemu_put_be16s(f, &s->config.rows); + visit_type_uint16(v, &s->config.cols, "config.cols", &err); + visit_type_uint16(v, &s->config.rows, "config.rows", &err); - qemu_put_be32s(f, &s->config.max_nr_ports); + visit_type_uint32(v, &s->config.max_nr_ports, "config.max_nr_ports", &err); /* The ports map */ max_nr_ports = tswap32(s->config.max_nr_ports); + visit_start_array(v, NULL, "ports_map", (max_nr_ports + 31) / 32, 4, &err); for (i = 0; i < (max_nr_ports + 31) / 32; i++) { - qemu_put_be32s(f, &s->ports_map[i]); + visit_type_uint32(v, &s->ports_map[i], NULL, &err); } + visit_end_array(v, &err); /* Ports */ @@ -544,31 +551,46 @@ static void virtio_serial_save(QEMUFile *f, void *opaque) nr_active_ports++; } - qemu_put_be32s(f, &nr_active_ports); + visit_type_uint32(v, &nr_active_ports, "nr_active_ports", &err); /* * Items in struct VirtIOSerialPort. */ + visit_start_list(v, "ports", &err); QTAILQ_FOREACH(port, &s->ports, next) { uint32_t elem_popped; - qemu_put_be32s(f, &port->id); - qemu_put_byte(f, port->guest_connected); - qemu_put_byte(f, port->host_connected); + visit_start_struct(v, NULL, NULL, NULL, 0, &err); + + visit_type_uint32(v, &port->id, "id", &err); + visit_type_uint8(v, (uint8_t *)&port->guest_connected, + "guest_connected", &err); + visit_type_uint8(v, (uint8_t *)&port->host_connected, + "host_connected", &err); - elem_popped = 0; + elem_popped = 0; if (port->elem.out_num) { elem_popped = 1; } - qemu_put_be32s(f, &elem_popped); + visit_type_uint32(v, &elem_popped, "elem_popped", &err); if (elem_popped) { - qemu_put_be32s(f, &port->iov_idx); - qemu_put_be64s(f, &port->iov_offset); - - qemu_put_buffer(f, (unsigned char *)&port->elem, - sizeof(port->elem)); + visit_type_uint32(v, &port->iov_idx, "iov_idx", &err); + visit_type_uint64(v, &port->iov_offset, "iov_offset", &err); + + /* FIXME: migration badness, serializing structs as blobs */ + visit_start_array(v, NULL, "elem", sizeof(port->elem), 1, &err); + buf = (uint8_t *)&port->elem; + for (i = 0; i < sizeof(port->elem); i++) { + visit_type_uint8(v, &buf[i], NULL, &err); + } + visit_end_array(v, &err); } + + visit_end_struct(v, &err); } + visit_end_list(v, &err); + + visit_end_struct(v, &err); } static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id) @@ -577,56 +599,73 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id) VirtIOSerialPort *port; uint32_t max_nr_ports, nr_active_ports, ports_map; unsigned int i; + int ret = 0; + Visitor *v = qemu_file_get_visitor(f); + Error *err = NULL; + uint8_t *buf; if (version_id > 3) { - return -EINVAL; + ret = -EINVAL; + goto out; } + visit_start_struct(v, NULL, NULL, "virtio_serial", 0, &err); + /* The virtio device */ virtio_load(&s->vdev, f); if (version_id < 2) { - return 0; + goto out; } /* The config space */ - qemu_get_be16s(f, &s->config.cols); - qemu_get_be16s(f, &s->config.rows); + visit_type_uint16(v, &s->config.cols, "config.cols", &err); + visit_type_uint16(v, &s->config.rows, "config.rows", &err); - qemu_get_be32s(f, &max_nr_ports); + visit_type_uint32(v, &max_nr_ports, "config.max_nr_ports", &err); tswap32s(&max_nr_ports); if (max_nr_ports > tswap32(s->config.max_nr_ports)) { /* Source could have had more ports than us. Fail migration. */ - return -EINVAL; + ret = -EINVAL; + goto out; } + visit_start_array(v, NULL, "ports_map", (max_nr_ports + 31) / 32, 4, &err); for (i = 0; i < (max_nr_ports + 31) / 32; i++) { - qemu_get_be32s(f, &ports_map); + visit_type_uint32(v, &ports_map, NULL, &err); if (ports_map != s->ports_map[i]) { /* * Ports active on source and destination don't * match. Fail migration. */ - return -EINVAL; + ret = -EINVAL; + goto out; } } + visit_end_array(v, &err); - qemu_get_be32s(f, &nr_active_ports); + visit_type_uint32(v, &nr_active_ports, "nr_active_ports", &err); /* Items in struct VirtIOSerialPort */ + visit_start_list(v, "ports", &err); for (i = 0; i < nr_active_ports; i++) { uint32_t id; - bool host_connected; + uint8_t host_connected; + + visit_start_struct(v, NULL, NULL, NULL, 0, &err); - id = qemu_get_be32(f); + visit_type_uint32(v, &id, "id", &err); port = find_port_by_id(s, id); if (!port) { - return -EINVAL; + ret = -EINVAL; + goto out; } - port->guest_connected = qemu_get_byte(f); - host_connected = qemu_get_byte(f); + visit_type_uint8(v, (uint8_t *)&port->guest_connected, + "guest_connected", &err); + visit_type_uint8(v, (uint8_t *)&host_connected, + "host_connected", &err); if (host_connected != port->host_connected) { /* * We have to let the guest know of the host connection @@ -639,13 +678,19 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id) if (version_id > 2) { uint32_t elem_popped; - qemu_get_be32s(f, &elem_popped); + visit_type_uint32(v, &elem_popped, "elem_popped", &err); if (elem_popped) { - qemu_get_be32s(f, &port->iov_idx); - qemu_get_be64s(f, &port->iov_offset); + visit_type_uint32(v, &port->iov_idx, "iov_idx", &err); + visit_type_uint64(v, &port->iov_offset, "iov_offset", &err); + + /* FIXME: migration badness, serializing structs as blobs */ + visit_start_array(v, NULL, "elem", sizeof(port->elem), 1, &err); + buf = (uint8_t *)&port->elem; + for (i = 0; i < sizeof(port->elem); i++) { + visit_type_uint8(v, &buf[i], NULL, &err); + } + visit_end_array(v, &err); - qemu_get_buffer(f, (unsigned char *)&port->elem, - sizeof(port->elem)); virtqueue_map_sg(port->elem.in_sg, port->elem.in_addr, port->elem.in_num, 1); virtqueue_map_sg(port->elem.out_sg, port->elem.out_addr, @@ -658,8 +703,19 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id) virtio_serial_throttle_port(port, false); } } + visit_end_struct(v, &err); } - return 0; + visit_end_list(v, &err); + + visit_end_struct(v, &err); + + if (err) { + error_report("error loading virtio-net state: %s", error_get_pretty(err)); + ret = -EINVAL; + } +out: + error_free(err); + return ret; } static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent); -- 1.7.4.1