diff options
Diffstat (limited to 'hw')
| -rw-r--r-- | hw/char/exynos4210_uart.c | 2 | ||||
| -rw-r--r-- | hw/display/g364fb.c | 2 | ||||
| -rw-r--r-- | hw/dma/pl330.c | 8 | ||||
| -rw-r--r-- | hw/intc/exynos4210_gic.c | 2 | ||||
| -rw-r--r-- | hw/ipmi/isa_ipmi_bt.c | 6 | ||||
| -rw-r--r-- | hw/net/virtio-net.c | 316 | ||||
| -rw-r--r-- | hw/net/vmxnet3.c | 2 | ||||
| -rw-r--r-- | hw/nvram/mac_nvram.c | 2 | ||||
| -rw-r--r-- | hw/nvram/spapr_nvram.c | 2 | ||||
| -rw-r--r-- | hw/sd/sdhci.c | 2 | ||||
| -rw-r--r-- | hw/timer/m48t59.c | 2 |
11 files changed, 225 insertions, 121 deletions
diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c index 7c16e894e2..b75f28d473 100644 --- a/hw/char/exynos4210_uart.c +++ b/hw/char/exynos4210_uart.c @@ -561,7 +561,7 @@ static const VMStateDescription vmstate_exynos4210_uart_fifo = { .fields = (VMStateField[]) { VMSTATE_UINT32(sp, Exynos4210UartFIFO), VMSTATE_UINT32(rp, Exynos4210UartFIFO), - VMSTATE_VBUFFER_UINT32(data, Exynos4210UartFIFO, 1, NULL, 0, size), + VMSTATE_VBUFFER_UINT32(data, Exynos4210UartFIFO, 1, NULL, size), VMSTATE_END_OF_LIST() } }; diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c index 70ef2c7453..8cdc205dd9 100644 --- a/hw/display/g364fb.c +++ b/hw/display/g364fb.c @@ -464,7 +464,7 @@ static const VMStateDescription vmstate_g364fb = { .minimum_version_id = 1, .post_load = g364fb_post_load, .fields = (VMStateField[]) { - VMSTATE_VBUFFER_UINT32(vram, G364State, 1, NULL, 0, vram_size), + VMSTATE_VBUFFER_UINT32(vram, G364State, 1, NULL, vram_size), VMSTATE_BUFFER_UNSAFE(color_palette, G364State, 0, 256 * 3), VMSTATE_BUFFER_UNSAFE(cursor_palette, G364State, 0, 9), VMSTATE_UINT16_ARRAY(cursor, G364State, 512), diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c index c0bd9fec30..32cf8399b8 100644 --- a/hw/dma/pl330.c +++ b/hw/dma/pl330.c @@ -173,8 +173,8 @@ static const VMStateDescription vmstate_pl330_fifo = { .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_VBUFFER_UINT32(buf, PL330Fifo, 1, NULL, 0, buf_size), - VMSTATE_VBUFFER_UINT32(tag, PL330Fifo, 1, NULL, 0, buf_size), + VMSTATE_VBUFFER_UINT32(buf, PL330Fifo, 1, NULL, buf_size), + VMSTATE_VBUFFER_UINT32(tag, PL330Fifo, 1, NULL, buf_size), VMSTATE_UINT32(head, PL330Fifo), VMSTATE_UINT32(num, PL330Fifo), VMSTATE_UINT32(buf_size, PL330Fifo), @@ -282,8 +282,8 @@ static const VMStateDescription vmstate_pl330 = { VMSTATE_STRUCT(manager, PL330State, 0, vmstate_pl330_chan, PL330Chan), VMSTATE_STRUCT_VARRAY_UINT32(chan, PL330State, num_chnls, 0, vmstate_pl330_chan, PL330Chan), - VMSTATE_VBUFFER_UINT32(lo_seqn, PL330State, 1, NULL, 0, num_chnls), - VMSTATE_VBUFFER_UINT32(hi_seqn, PL330State, 1, NULL, 0, num_chnls), + VMSTATE_VBUFFER_UINT32(lo_seqn, PL330State, 1, NULL, num_chnls), + VMSTATE_VBUFFER_UINT32(hi_seqn, PL330State, 1, NULL, num_chnls), VMSTATE_STRUCT(fifo, PL330State, 0, vmstate_pl330_fifo, PL330Fifo), VMSTATE_STRUCT(read_queue, PL330State, 0, vmstate_pl330_queue, PL330Queue), diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c index fd7a8f3058..2a55817b76 100644 --- a/hw/intc/exynos4210_gic.c +++ b/hw/intc/exynos4210_gic.c @@ -393,7 +393,7 @@ static const VMStateDescription vmstate_exynos4210_irq_gate = { .version_id = 2, .minimum_version_id = 2, .fields = (VMStateField[]) { - VMSTATE_VBUFFER_UINT32(level, Exynos4210IRQGateState, 1, NULL, 0, n_in), + VMSTATE_VBUFFER_UINT32(level, Exynos4210IRQGateState, 1, NULL, n_in), VMSTATE_END_OF_LIST() } }; diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c index f03661715c..1c69cb33f8 100644 --- a/hw/ipmi/isa_ipmi_bt.c +++ b/hw/ipmi/isa_ipmi_bt.c @@ -471,10 +471,8 @@ static const VMStateDescription vmstate_ISAIPMIBTDevice = { VMSTATE_BOOL(bt.use_irq, ISAIPMIBTDevice), VMSTATE_BOOL(bt.irqs_enabled, ISAIPMIBTDevice), VMSTATE_UINT32(bt.outpos, ISAIPMIBTDevice), - VMSTATE_VBUFFER_UINT32(bt.outmsg, ISAIPMIBTDevice, 1, NULL, 0, - bt.outlen), - VMSTATE_VBUFFER_UINT32(bt.inmsg, ISAIPMIBTDevice, 1, NULL, 0, - bt.inlen), + VMSTATE_VBUFFER_UINT32(bt.outmsg, ISAIPMIBTDevice, 1, NULL, bt.outlen), + VMSTATE_VBUFFER_UINT32(bt.inmsg, ISAIPMIBTDevice, 1, NULL, bt.inlen), VMSTATE_UINT8(bt.control_reg, ISAIPMIBTDevice), VMSTATE_UINT8(bt.mask_reg, ISAIPMIBTDevice), VMSTATE_UINT8(bt.waiting_rsp, ISAIPMIBTDevice), diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 7b3ad4a9f0..354a19eab8 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -1557,119 +1557,22 @@ static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue) virtio_net_set_queues(n); } -static void virtio_net_save_device(VirtIODevice *vdev, QEMUFile *f) +static int virtio_net_post_load_device(void *opaque, int version_id) { - VirtIONet *n = VIRTIO_NET(vdev); - int i; - - qemu_put_buffer(f, n->mac, ETH_ALEN); - qemu_put_be32(f, n->vqs[0].tx_waiting); - qemu_put_be32(f, n->mergeable_rx_bufs); - qemu_put_be16(f, n->status); - qemu_put_byte(f, n->promisc); - qemu_put_byte(f, n->allmulti); - qemu_put_be32(f, n->mac_table.in_use); - qemu_put_buffer(f, n->mac_table.macs, n->mac_table.in_use * ETH_ALEN); - qemu_put_buffer(f, (uint8_t *)n->vlans, MAX_VLAN >> 3); - qemu_put_be32(f, n->has_vnet_hdr); - qemu_put_byte(f, n->mac_table.multi_overflow); - qemu_put_byte(f, n->mac_table.uni_overflow); - qemu_put_byte(f, n->alluni); - qemu_put_byte(f, n->nomulti); - qemu_put_byte(f, n->nouni); - qemu_put_byte(f, n->nobcast); - qemu_put_byte(f, n->has_ufo); - if (n->max_queues > 1) { - qemu_put_be16(f, n->max_queues); - qemu_put_be16(f, n->curr_queues); - for (i = 1; i < n->curr_queues; i++) { - qemu_put_be32(f, n->vqs[i].tx_waiting); - } - } - - if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) { - qemu_put_be64(f, n->curr_guest_offloads); - } -} - -static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f, - int version_id) -{ - VirtIONet *n = VIRTIO_NET(vdev); + VirtIONet *n = opaque; + VirtIODevice *vdev = VIRTIO_DEVICE(n); int i, link_down; - qemu_get_buffer(f, n->mac, ETH_ALEN); - n->vqs[0].tx_waiting = qemu_get_be32(f); - - virtio_net_set_mrg_rx_bufs(n, qemu_get_be32(f), + virtio_net_set_mrg_rx_bufs(n, n->mergeable_rx_bufs, virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)); - n->status = qemu_get_be16(f); - - n->promisc = qemu_get_byte(f); - n->allmulti = qemu_get_byte(f); - - n->mac_table.in_use = qemu_get_be32(f); /* MAC_TABLE_ENTRIES may be different from the saved image */ - if (n->mac_table.in_use <= MAC_TABLE_ENTRIES) { - qemu_get_buffer(f, n->mac_table.macs, - n->mac_table.in_use * ETH_ALEN); - } else { - int64_t i; - - /* Overflow detected - can happen if source has a larger MAC table. - * We simply set overflow flag so there's no need to maintain the - * table of addresses, discard them all. - * Note: 64 bit math to avoid integer overflow. - */ - for (i = 0; i < (int64_t)n->mac_table.in_use * ETH_ALEN; ++i) { - qemu_get_byte(f); - } - n->mac_table.multi_overflow = n->mac_table.uni_overflow = 1; + if (n->mac_table.in_use > MAC_TABLE_ENTRIES) { n->mac_table.in_use = 0; } - - qemu_get_buffer(f, (uint8_t *)n->vlans, MAX_VLAN >> 3); - - if (qemu_get_be32(f) && !peer_has_vnet_hdr(n)) { - error_report("virtio-net: saved image requires vnet_hdr=on"); - return -1; - } - - n->mac_table.multi_overflow = qemu_get_byte(f); - n->mac_table.uni_overflow = qemu_get_byte(f); - - n->alluni = qemu_get_byte(f); - n->nomulti = qemu_get_byte(f); - n->nouni = qemu_get_byte(f); - n->nobcast = qemu_get_byte(f); - - if (qemu_get_byte(f) && !peer_has_ufo(n)) { - error_report("virtio-net: saved image requires TUN_F_UFO support"); - return -1; - } - if (n->max_queues > 1) { - if (n->max_queues != qemu_get_be16(f)) { - error_report("virtio-net: different max_queues "); - return -1; - } - - n->curr_queues = qemu_get_be16(f); - if (n->curr_queues > n->max_queues) { - error_report("virtio-net: curr_queues %x > max_queues %x", - n->curr_queues, n->max_queues); - return -1; - } - for (i = 1; i < n->curr_queues; i++) { - n->vqs[i].tx_waiting = qemu_get_be32(f); - } - } - - if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) { - n->curr_guest_offloads = qemu_get_be64(f); - } else { + if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) { n->curr_guest_offloads = virtio_net_supported_guest_offloads(n); } @@ -1703,6 +1606,210 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f, return 0; } +/* tx_waiting field of a VirtIONetQueue */ +static const VMStateDescription vmstate_virtio_net_queue_tx_waiting = { + .name = "virtio-net-queue-tx_waiting", + .fields = (VMStateField[]) { + VMSTATE_UINT32(tx_waiting, VirtIONetQueue), + VMSTATE_END_OF_LIST() + }, +}; + +static bool max_queues_gt_1(void *opaque, int version_id) +{ + return VIRTIO_NET(opaque)->max_queues > 1; +} + +static bool has_ctrl_guest_offloads(void *opaque, int version_id) +{ + return virtio_vdev_has_feature(VIRTIO_DEVICE(opaque), + VIRTIO_NET_F_CTRL_GUEST_OFFLOADS); +} + +static bool mac_table_fits(void *opaque, int version_id) +{ + return VIRTIO_NET(opaque)->mac_table.in_use <= MAC_TABLE_ENTRIES; +} + +static bool mac_table_doesnt_fit(void *opaque, int version_id) +{ + return !mac_table_fits(opaque, version_id); +} + +/* This temporary type is shared by all the WITH_TMP methods + * although only some fields are used by each. + */ +struct VirtIONetMigTmp { + VirtIONet *parent; + VirtIONetQueue *vqs_1; + uint16_t curr_queues_1; + uint8_t has_ufo; + uint32_t has_vnet_hdr; +}; + +/* The 2nd and subsequent tx_waiting flags are loaded later than + * the 1st entry in the queues and only if there's more than one + * entry. We use the tmp mechanism to calculate a temporary + * pointer and count and also validate the count. + */ + +static void virtio_net_tx_waiting_pre_save(void *opaque) +{ + struct VirtIONetMigTmp *tmp = opaque; + + tmp->vqs_1 = tmp->parent->vqs + 1; + tmp->curr_queues_1 = tmp->parent->curr_queues - 1; + if (tmp->parent->curr_queues == 0) { + tmp->curr_queues_1 = 0; + } +} + +static int virtio_net_tx_waiting_pre_load(void *opaque) +{ + struct VirtIONetMigTmp *tmp = opaque; + + /* Reuse the pointer setup from save */ + virtio_net_tx_waiting_pre_save(opaque); + + if (tmp->parent->curr_queues > tmp->parent->max_queues) { + error_report("virtio-net: curr_queues %x > max_queues %x", + tmp->parent->curr_queues, tmp->parent->max_queues); + + return -EINVAL; + } + + return 0; /* all good */ +} + +static const VMStateDescription vmstate_virtio_net_tx_waiting = { + .name = "virtio-net-tx_waiting", + .pre_load = virtio_net_tx_waiting_pre_load, + .pre_save = virtio_net_tx_waiting_pre_save, + .fields = (VMStateField[]) { + VMSTATE_STRUCT_VARRAY_POINTER_UINT16(vqs_1, struct VirtIONetMigTmp, + curr_queues_1, + vmstate_virtio_net_queue_tx_waiting, + struct VirtIONetQueue), + VMSTATE_END_OF_LIST() + }, +}; + +/* the 'has_ufo' flag is just tested; if the incoming stream has the + * flag set we need to check that we have it + */ +static int virtio_net_ufo_post_load(void *opaque, int version_id) +{ + struct VirtIONetMigTmp *tmp = opaque; + + if (tmp->has_ufo && !peer_has_ufo(tmp->parent)) { + error_report("virtio-net: saved image requires TUN_F_UFO support"); + return -EINVAL; + } + + return 0; +} + +static void virtio_net_ufo_pre_save(void *opaque) +{ + struct VirtIONetMigTmp *tmp = opaque; + + tmp->has_ufo = tmp->parent->has_ufo; +} + +static const VMStateDescription vmstate_virtio_net_has_ufo = { + .name = "virtio-net-ufo", + .post_load = virtio_net_ufo_post_load, + .pre_save = virtio_net_ufo_pre_save, + .fields = (VMStateField[]) { + VMSTATE_UINT8(has_ufo, struct VirtIONetMigTmp), + VMSTATE_END_OF_LIST() + }, +}; + +/* the 'has_vnet_hdr' flag is just tested; if the incoming stream has the + * flag set we need to check that we have it + */ +static int virtio_net_vnet_post_load(void *opaque, int version_id) +{ + struct VirtIONetMigTmp *tmp = opaque; + + if (tmp->has_vnet_hdr && !peer_has_vnet_hdr(tmp->parent)) { + error_report("virtio-net: saved image requires vnet_hdr=on"); + return -EINVAL; + } + + return 0; +} + +static void virtio_net_vnet_pre_save(void *opaque) +{ + struct VirtIONetMigTmp *tmp = opaque; + + tmp->has_vnet_hdr = tmp->parent->has_vnet_hdr; +} + +static const VMStateDescription vmstate_virtio_net_has_vnet = { + .name = "virtio-net-vnet", + .post_load = virtio_net_vnet_post_load, + .pre_save = virtio_net_vnet_pre_save, + .fields = (VMStateField[]) { + VMSTATE_UINT32(has_vnet_hdr, struct VirtIONetMigTmp), + VMSTATE_END_OF_LIST() + }, +}; + +static const VMStateDescription vmstate_virtio_net_device = { + .name = "virtio-net-device", + .version_id = VIRTIO_NET_VM_VERSION, + .minimum_version_id = VIRTIO_NET_VM_VERSION, + .post_load = virtio_net_post_load_device, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(mac, VirtIONet, ETH_ALEN), + VMSTATE_STRUCT_POINTER(vqs, VirtIONet, + vmstate_virtio_net_queue_tx_waiting, + VirtIONetQueue), + VMSTATE_UINT32(mergeable_rx_bufs, VirtIONet), + VMSTATE_UINT16(status, VirtIONet), + VMSTATE_UINT8(promisc, VirtIONet), + VMSTATE_UINT8(allmulti, VirtIONet), + VMSTATE_UINT32(mac_table.in_use, VirtIONet), + + /* Guarded pair: If it fits we load it, else we throw it away + * - can happen if source has a larger MAC table.; post-load + * sets flags in this case. + */ + VMSTATE_VBUFFER_MULTIPLY(mac_table.macs, VirtIONet, + 0, mac_table_fits, mac_table.in_use, + ETH_ALEN), + VMSTATE_UNUSED_VARRAY_UINT32(VirtIONet, mac_table_doesnt_fit, 0, + mac_table.in_use, ETH_ALEN), + + /* Note: This is an array of uint32's that's always been saved as a + * buffer; hold onto your endiannesses; it's actually used as a bitmap + * but based on the uint. + */ + VMSTATE_BUFFER_POINTER_UNSAFE(vlans, VirtIONet, 0, MAX_VLAN >> 3), + VMSTATE_WITH_TMP(VirtIONet, struct VirtIONetMigTmp, + vmstate_virtio_net_has_vnet), + VMSTATE_UINT8(mac_table.multi_overflow, VirtIONet), + VMSTATE_UINT8(mac_table.uni_overflow, VirtIONet), + VMSTATE_UINT8(alluni, VirtIONet), + VMSTATE_UINT8(nomulti, VirtIONet), + VMSTATE_UINT8(nouni, VirtIONet), + VMSTATE_UINT8(nobcast, VirtIONet), + VMSTATE_WITH_TMP(VirtIONet, struct VirtIONetMigTmp, + vmstate_virtio_net_has_ufo), + VMSTATE_SINGLE_TEST(max_queues, VirtIONet, max_queues_gt_1, 0, + vmstate_info_uint16_equal, uint16_t), + VMSTATE_UINT16_TEST(curr_queues, VirtIONet, max_queues_gt_1), + VMSTATE_WITH_TMP(VirtIONet, struct VirtIONetMigTmp, + vmstate_virtio_net_tx_waiting), + VMSTATE_UINT64_TEST(curr_guest_offloads, VirtIONet, + has_ctrl_guest_offloads), + VMSTATE_END_OF_LIST() + }, +}; + static NetClientInfo net_virtio_info = { .type = NET_CLIENT_DRIVER_NIC, .size = sizeof(NICState), @@ -1989,9 +2096,8 @@ static void virtio_net_class_init(ObjectClass *klass, void *data) vdc->set_status = virtio_net_set_status; vdc->guest_notifier_mask = virtio_net_guest_notifier_mask; vdc->guest_notifier_pending = virtio_net_guest_notifier_pending; - vdc->load = virtio_net_load_device; - vdc->save = virtio_net_save_device; vdc->legacy_features |= (0x1 << VIRTIO_NET_F_GSO); + vdc->vmsd = &vmstate_virtio_net_device; } static const TypeInfo virtio_net_info = { diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 7dd456551c..e13a798b3b 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -2397,7 +2397,7 @@ static const VMStateDescription vmxstate_vmxnet3_mcast_list = { .pre_load = vmxnet3_mcast_list_pre_load, .needed = vmxnet3_mc_list_needed, .fields = (VMStateField[]) { - VMSTATE_VBUFFER_UINT32(mcast_list, VMXNET3State, 0, NULL, 0, + VMSTATE_VBUFFER_UINT32(mcast_list, VMXNET3State, 0, NULL, mcast_list_buff_size), VMSTATE_END_OF_LIST() } diff --git a/hw/nvram/mac_nvram.c b/hw/nvram/mac_nvram.c index 63f9ed1d82..aef80e64df 100644 --- a/hw/nvram/mac_nvram.c +++ b/hw/nvram/mac_nvram.c @@ -82,7 +82,7 @@ static const VMStateDescription vmstate_macio_nvram = { .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_VBUFFER_UINT32(data, MacIONVRAMState, 0, NULL, 0, size), + VMSTATE_VBUFFER_UINT32(data, MacIONVRAMState, 0, NULL, size), VMSTATE_END_OF_LIST() } }; diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c index eb42ea323f..65ba188555 100644 --- a/hw/nvram/spapr_nvram.c +++ b/hw/nvram/spapr_nvram.c @@ -224,7 +224,7 @@ static const VMStateDescription vmstate_spapr_nvram = { .post_load = spapr_nvram_post_load, .fields = (VMStateField[]) { VMSTATE_UINT32(size, sPAPRNVRAM), - VMSTATE_VBUFFER_ALLOC_UINT32(buf, sPAPRNVRAM, 1, NULL, 0, size), + VMSTATE_VBUFFER_ALLOC_UINT32(buf, sPAPRNVRAM, 1, NULL, size), VMSTATE_END_OF_LIST() }, }; diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 5bd5ab6319..da32b5f709 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -1253,7 +1253,7 @@ const VMStateDescription sdhci_vmstate = { VMSTATE_UINT16(data_count, SDHCIState), VMSTATE_UINT64(admasysaddr, SDHCIState), VMSTATE_UINT8(stopped_state, SDHCIState), - VMSTATE_VBUFFER_UINT32(fifo_buffer, SDHCIState, 1, NULL, 0, buf_maxsz), + VMSTATE_VBUFFER_UINT32(fifo_buffer, SDHCIState, 1, NULL, buf_maxsz), VMSTATE_TIMER_PTR(insert_timer, SDHCIState), VMSTATE_TIMER_PTR(transfer_timer, SDHCIState), VMSTATE_END_OF_LIST() diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c index 015797732f..474981a6ac 100644 --- a/hw/timer/m48t59.c +++ b/hw/timer/m48t59.c @@ -563,7 +563,7 @@ static const VMStateDescription vmstate_m48t59 = { .fields = (VMStateField[]) { VMSTATE_UINT8(lock, M48t59State), VMSTATE_UINT16(addr, M48t59State), - VMSTATE_VBUFFER_UINT32(buffer, M48t59State, 0, NULL, 0, size), + VMSTATE_VBUFFER_UINT32(buffer, M48t59State, 0, NULL, size), VMSTATE_END_OF_LIST() } }; |