From: "Michael S. Tsirkin" <mst@redhat.com>
To: qemu-devel@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>,
Stefan Hajnoczi <stefanha@redhat.com>,
Igor Mammedov <imammedo@redhat.com>
Subject: [Qemu-devel] [PULL 06/16] virtio: introduce virtio_map
Date: Thu, 29 Oct 2015 11:39:36 +0200 [thread overview]
Message-ID: <1446111531-5755-7-git-send-email-mst@redhat.com> (raw)
In-Reply-To: <1446111531-5755-1-git-send-email-mst@redhat.com>
virtio_map_sg currently fails if one of the entries it's mapping is
contigious in GPA but not HVA address space. Introduce virtio_map which
handles this by splitting sg entries.
This new API generally turns out to be a good idea since it's harder to
misuse: at least in one case the existing one was used incorrectly.
This will still fail if there's no space left in the sg, but luckily max
queue size in use is currently 256, while max sg size is 1024, so we
should be OK even is all entries happen to cross a single DIMM boundary.
Won't work well with very small DIMM sizes, unfortunately:
e.g. this will fail with 4K DIMMs where a single
request might span a large number of DIMMs.
Let's hope these are uncommon - at least we are not breaking things.
Note: virtio-scsi calls virtio_map_sg on data loaded from network, and
validates input, asserting on failure. Copy the validating code here -
it will be dropped from virtio-scsi in a follow-up patch.
Reported-by: Igor Mammedov <imammedo@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
---
include/hw/virtio/virtio.h | 1 +
hw/virtio/virtio.c | 56 ++++++++++++++++++++++++++++++++++++++--------
2 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 9d09115..9d9abb4 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -153,6 +153,7 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
void virtqueue_map_sg(struct iovec *sg, hwaddr *addr,
size_t num_sg, int is_write);
+void virtqueue_map(VirtQueueElement *elem);
int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem);
int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes,
unsigned int out_bytes);
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index d0bc72e..943b990 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -448,28 +448,66 @@ int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes,
return in_bytes <= in_total && out_bytes <= out_total;
}
-void virtqueue_map_sg(struct iovec *sg, hwaddr *addr,
- size_t num_sg, int is_write)
+static void virtqueue_map_iovec(struct iovec *sg, hwaddr *addr,
+ unsigned int *num_sg, unsigned int max_size,
+ int is_write)
{
unsigned int i;
hwaddr len;
- if (num_sg > VIRTQUEUE_MAX_SIZE) {
- error_report("virtio: map attempt out of bounds: %zd > %d",
- num_sg, VIRTQUEUE_MAX_SIZE);
- exit(1);
- }
+ /* Note: this function MUST validate input, some callers
+ * are passing in num_sg values received over the network.
+ */
+ /* TODO: teach all callers that this can fail, and return failure instead
+ * of asserting here.
+ * When we do, we might be able to re-enable NDEBUG below.
+ */
+#ifdef NDEBUG
+#error building with NDEBUG is not supported
+#endif
+ assert(*num_sg <= max_size);
- for (i = 0; i < num_sg; i++) {
+ for (i = 0; i < *num_sg; i++) {
len = sg[i].iov_len;
sg[i].iov_base = cpu_physical_memory_map(addr[i], &len, is_write);
- if (sg[i].iov_base == NULL || len != sg[i].iov_len) {
+ if (!sg[i].iov_base) {
error_report("virtio: error trying to map MMIO memory");
exit(1);
}
+ if (len == sg[i].iov_len) {
+ continue;
+ }
+ if (*num_sg >= max_size) {
+ error_report("virtio: memory split makes iovec too large");
+ exit(1);
+ }
+ memmove(sg + i + 1, sg + i, sizeof(*sg) * (*num_sg - i));
+ memmove(addr + i + 1, addr + i, sizeof(*addr) * (*num_sg - i));
+ assert(len < sg[i + 1].iov_len);
+ sg[i].iov_len = len;
+ addr[i + 1] += len;
+ sg[i + 1].iov_len -= len;
+ ++*num_sg;
}
}
+/* Deprecated: don't use in new code */
+void virtqueue_map_sg(struct iovec *sg, hwaddr *addr,
+ size_t num_sg, int is_write)
+{
+ virtqueue_map_iovec(sg, addr, &num_sg, num_sg, is_write);
+}
+
+void virtqueue_map(VirtQueueElement *elem)
+{
+ virtqueue_map_iovec(elem->in_sg, elem->in_addr, &elem->in_num,
+ MIN(ARRAY_SIZE(elem->in_sg), ARRAY_SIZE(elem->in_addr)),
+ 1);
+ virtqueue_map_iovec(elem->out_sg, elem->out_addr, &elem->out_num,
+ MIN(ARRAY_SIZE(elem->out_sg), ARRAY_SIZE(elem->out_addr)),
+ 0);
+}
+
int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
{
unsigned int i, head, max;
--
MST
next prev parent reply other threads:[~2015-10-29 9:39 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-10-29 9:39 [Qemu-devel] [PULL 00/16] virtio, pc, memory: fixes+features for 2.5 Michael S. Tsirkin
2015-10-29 9:39 ` [Qemu-devel] [PULL 01/16] vhost-user: cleanup struct size math Michael S. Tsirkin
2015-10-29 9:39 ` [Qemu-devel] [PULL 02/16] vhost-user: cleanup msg " Michael S. Tsirkin
2015-10-29 9:39 ` [Qemu-devel] [PULL 03/16] vhost-user-test: fix up rhel6 build Michael S. Tsirkin
2015-10-29 9:39 ` [Qemu-devel] [PULL 04/16] pc: memhp: do not emit inserting event for coldplugged DIMMs Michael S. Tsirkin
2015-10-29 9:39 ` [Qemu-devel] [PULL 05/16] mmap-alloc: fix error handling Michael S. Tsirkin
2015-10-29 9:39 ` Michael S. Tsirkin [this message]
2015-10-29 9:39 ` [Qemu-devel] [PULL 07/16] virtio: switch to virtio_map Michael S. Tsirkin
2015-10-29 9:39 ` [Qemu-devel] [PULL 08/16] virtio-blk: convert to virtqueue_map Michael S. Tsirkin
2015-10-29 9:39 ` [Qemu-devel] [PULL 09/16] virtio-serial: convert to virtio_map Michael S. Tsirkin
2015-10-29 9:39 ` [Qemu-devel] [PULL 10/16] virtio-scsi: convert to virtqueue_map Michael S. Tsirkin
2015-10-29 9:39 ` [Qemu-devel] [PULL 11/16] virtio: drop virtqueue_map_sg Michael S. Tsirkin
2015-10-29 9:39 ` [Qemu-devel] [PULL 12/16] Revert "pc: memhp: force gaps between DIMM's GPA" Michael S. Tsirkin
2015-10-29 9:39 ` [Qemu-devel] [PULL 13/16] Revert "memhp: extend address auto assignment to support gaps" Michael S. Tsirkin
2015-10-29 9:39 ` [Qemu-devel] [PULL 14/16] tests/vhost-user-bridge: add vhost-user bridge application Michael S. Tsirkin
2015-10-29 9:40 ` [Qemu-devel] [PULL 15/16] remove function during multi-function hot-add Michael S. Tsirkin
2015-10-29 9:40 ` [Qemu-devel] [PULL 16/16] enable " Michael S. Tsirkin
2015-10-29 11:09 ` [Qemu-devel] [PULL 00/16] virtio, pc, memory: fixes+features for 2.5 Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1446111531-5755-7-git-send-email-mst@redhat.com \
--to=mst@redhat.com \
--cc=imammedo@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).