From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53908) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1a1Huh-0000ay-Ih for qemu-devel@nongnu.org; Tue, 24 Nov 2015 13:02:05 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1a1Hue-0005og-M7 for qemu-devel@nongnu.org; Tue, 24 Nov 2015 13:01:59 -0500 From: Paolo Bonzini Date: Tue, 24 Nov 2015 19:00:56 +0100 Message-Id: <1448388091-117282-6-git-send-email-pbonzini@redhat.com> In-Reply-To: <1448388091-117282-1-git-send-email-pbonzini@redhat.com> References: <1448388091-117282-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH 05/40] virtio: read/write the VirtQueueElement a field at a time List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org, qemu-block@nongnu.org Signed-off-by: Paolo Bonzini --- hw/virtio/virtio.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index fd63206..f5f8108 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -578,14 +578,105 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz) void *qemu_get_virtqueue_element(QEMUFile *f, size_t sz) { VirtQueueElement *elem = g_malloc(sz); - qemu_get_buffer(f, (uint8_t *)elem, sizeof(VirtQueueElement)); + bool swap; + hwaddr addr[VIRTQUEUE_MAX_SIZE]; + struct iovec iov[VIRTQUEUE_MAX_SIZE]; + uint64_t scratch; + int i; + + qemu_get_be32s(f, &elem->index); + qemu_get_be32s(f, &elem->out_num); + qemu_get_be32s(f, &elem->in_num); + + swap = (elem->out_num & 0xFFFF0000) || (elem->in_num & 0xFFFF0000); + if (swap) { + bswap32s(&elem->index); + bswap32s(&elem->out_num); + bswap32s(&elem->in_num); + } + + for (i = 0; i < elem->in_num; i++) { + qemu_get_be64s(f, &elem->in_addr[i]); + if (swap) { + bswap64s(&elem->in_addr[i]); + } + } + if (i < ARRAY_SIZE(addr)) { + qemu_get_buffer(f, (uint8_t *)addr, sizeof(addr) - i * sizeof(addr[0])); + } + + for (i = 0; i < elem->out_num; i++) { + qemu_get_be64s(f, &elem->out_addr[i]); + if (swap) { + bswap64s(&elem->out_addr[i]); + } + } + if (i < ARRAY_SIZE(addr)) { + qemu_get_buffer(f, (uint8_t *)addr, sizeof(addr) - i * sizeof(addr[0])); + } + + for (i = 0; i < elem->in_num; i++) { + (void) qemu_get_be64(f); /* base */ + qemu_get_be64s(f, &scratch); /* length */ + if (swap) { + bswap64s(&scratch); + } + elem->in_sg[i].iov_len = scratch; + } + if (i < ARRAY_SIZE(iov)) { + qemu_get_buffer(f, (uint8_t *)iov, sizeof(iov) - i * sizeof(iov[0])); + } + + for (i = 0; i < elem->out_num; i++) { + (void) qemu_get_be64(f); /* base */ + qemu_get_be64s(f, &scratch); /* length */ + if (swap) { + bswap64s(&scratch); + } + elem->out_sg[i].iov_len = scratch; + } + if (i < ARRAY_SIZE(iov)) { + qemu_get_buffer(f, (uint8_t *)iov, sizeof(iov) - i * sizeof(iov[0])); + } + virtqueue_map(elem); return elem; } void qemu_put_virtqueue_element(QEMUFile *f, VirtQueueElement *elem) { - qemu_put_buffer(f, (uint8_t *)elem, sizeof(VirtQueueElement)); + hwaddr addr[VIRTQUEUE_MAX_SIZE]; + struct iovec iov[VIRTQUEUE_MAX_SIZE]; + int i; + + memset(addr, 0, sizeof(addr)); + memset(iov, 0, sizeof(iov)); + + qemu_put_be32s(f, &elem->index); + qemu_put_be32s(f, &elem->out_num); + qemu_put_be32s(f, &elem->in_num); + + for (i = 0; i < elem->in_num; i++) { + qemu_put_be64s(f, &elem->in_addr[i]); + } + qemu_put_buffer(f, (uint8_t *)addr, sizeof(addr) - i * sizeof(addr[0])); + + for (i = 0; i < elem->out_num; i++) { + qemu_put_be64s(f, &elem->out_addr[i]); + } + qemu_put_buffer(f, (uint8_t *)addr, sizeof(addr) - i * sizeof(addr[0])); + + for (i = 0; i < elem->in_num; i++) { + qemu_put_be64(f, 0); + qemu_put_be64(f, elem->in_sg[i].iov_len); + } + qemu_put_buffer(f, (uint8_t *)iov, sizeof(iov) - i * sizeof(iov[0])); + + for (i = 0; i < elem->out_num; i++) { + qemu_put_be64(f, 0); + qemu_put_be64(f, elem->out_sg[i].iov_len); + } + qemu_put_buffer(f, (uint8_t *)iov, sizeof(iov) - i * sizeof(iov[0])); } /* virtio device */ -- 1.8.3.1