aboutsummaryrefslogtreecommitdiff
path: root/hw/virtio
diff options
context:
space:
mode:
Diffstat (limited to 'hw/virtio')
-rw-r--r--hw/virtio/vhost-backend.c7
-rw-r--r--hw/virtio/vhost-user.c6
-rw-r--r--hw/virtio/vhost.c37
-rw-r--r--hw/virtio/virtio-iommu.c16
4 files changed, 62 insertions, 4 deletions
diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
index 4de8b6b..8e58157 100644
--- a/hw/virtio/vhost-backend.c
+++ b/hw/virtio/vhost-backend.c
@@ -146,6 +146,12 @@ static int vhost_kernel_set_vring_call(struct vhost_dev *dev,
return vhost_kernel_call(dev, VHOST_SET_VRING_CALL, file);
}
+static int vhost_kernel_set_vring_err(struct vhost_dev *dev,
+ struct vhost_vring_file *file)
+{
+ return vhost_kernel_call(dev, VHOST_SET_VRING_ERR, file);
+}
+
static int vhost_kernel_set_vring_busyloop_timeout(struct vhost_dev *dev,
struct vhost_vring_state *s)
{
@@ -309,6 +315,7 @@ const VhostOps kernel_ops = {
.vhost_get_vring_base = vhost_kernel_get_vring_base,
.vhost_set_vring_kick = vhost_kernel_set_vring_kick,
.vhost_set_vring_call = vhost_kernel_set_vring_call,
+ .vhost_set_vring_err = vhost_kernel_set_vring_err,
.vhost_set_vring_busyloop_timeout =
vhost_kernel_set_vring_busyloop_timeout,
.vhost_set_features = vhost_kernel_set_features,
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 4b9be26..75b8df2 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -1313,6 +1313,11 @@ static int vhost_user_set_vring_call(struct vhost_dev *dev,
return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_CALL, file);
}
+static int vhost_user_set_vring_err(struct vhost_dev *dev,
+ struct vhost_vring_file *file)
+{
+ return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_ERR, file);
+}
static int vhost_user_get_u64(struct vhost_dev *dev, int request, uint64_t *u64)
{
@@ -2616,6 +2621,7 @@ const VhostOps user_ops = {
.vhost_get_vring_base = vhost_user_get_vring_base,
.vhost_set_vring_kick = vhost_user_set_vring_kick,
.vhost_set_vring_call = vhost_user_set_vring_call,
+ .vhost_set_vring_err = vhost_user_set_vring_err,
.vhost_set_features = vhost_user_set_features,
.vhost_get_features = vhost_user_get_features,
.vhost_set_owner = vhost_user_set_owner,
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 6c41fa1..0827d63 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1278,6 +1278,19 @@ static int vhost_virtqueue_set_busyloop_timeout(struct vhost_dev *dev,
return 0;
}
+static void vhost_virtqueue_error_notifier(EventNotifier *n)
+{
+ struct vhost_virtqueue *vq = container_of(n, struct vhost_virtqueue,
+ error_notifier);
+ struct vhost_dev *dev = vq->dev;
+ int index = vq - dev->vqs;
+
+ if (event_notifier_test_and_clear(n) && dev->vdev) {
+ VHOST_OPS_DEBUG(-EINVAL, "vhost vring error in virtqueue %d",
+ dev->vq_index + index);
+ }
+}
+
static int vhost_virtqueue_init(struct vhost_dev *dev,
struct vhost_virtqueue *vq, int n)
{
@@ -1299,7 +1312,27 @@ static int vhost_virtqueue_init(struct vhost_dev *dev,
vq->dev = dev;
+ if (dev->vhost_ops->vhost_set_vring_err) {
+ r = event_notifier_init(&vq->error_notifier, 0);
+ if (r < 0) {
+ goto fail_call;
+ }
+
+ file.fd = event_notifier_get_fd(&vq->error_notifier);
+ r = dev->vhost_ops->vhost_set_vring_err(dev, &file);
+ if (r) {
+ VHOST_OPS_DEBUG(r, "vhost_set_vring_err failed");
+ goto fail_err;
+ }
+
+ event_notifier_set_handler(&vq->error_notifier,
+ vhost_virtqueue_error_notifier);
+ }
+
return 0;
+
+fail_err:
+ event_notifier_cleanup(&vq->error_notifier);
fail_call:
event_notifier_cleanup(&vq->masked_notifier);
return r;
@@ -1308,6 +1341,10 @@ fail_call:
static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq)
{
event_notifier_cleanup(&vq->masked_notifier);
+ if (vq->dev->vhost_ops->vhost_set_vring_err) {
+ event_notifier_set_handler(&vq->error_notifier, NULL);
+ event_notifier_cleanup(&vq->error_notifier);
+ }
}
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
index 7c122ab..281152d 100644
--- a/hw/virtio/virtio-iommu.c
+++ b/hw/virtio/virtio-iommu.c
@@ -675,11 +675,10 @@ static int virtio_iommu_probe(VirtIOIOMMU *s,
static int virtio_iommu_iov_to_req(struct iovec *iov,
unsigned int iov_cnt,
- void *req, size_t req_sz)
+ void *req, size_t payload_sz)
{
- size_t sz, payload_sz = req_sz - sizeof(struct virtio_iommu_req_tail);
+ size_t sz = iov_to_buf(iov, iov_cnt, 0, req, payload_sz);
- sz = iov_to_buf(iov, iov_cnt, 0, req, payload_sz);
if (unlikely(sz != payload_sz)) {
return VIRTIO_IOMMU_S_INVAL;
}
@@ -692,7 +691,8 @@ static int virtio_iommu_handle_ ## __req(VirtIOIOMMU *s, \
unsigned int iov_cnt) \
{ \
struct virtio_iommu_req_ ## __req req; \
- int ret = virtio_iommu_iov_to_req(iov, iov_cnt, &req, sizeof(req)); \
+ int ret = virtio_iommu_iov_to_req(iov, iov_cnt, &req, \
+ sizeof(req) - sizeof(struct virtio_iommu_req_tail));\
\
return ret ? ret : virtio_iommu_ ## __req(s, &req); \
}
@@ -1322,6 +1322,14 @@ static int iommu_post_load(void *opaque, int version_id)
VirtIOIOMMU *s = opaque;
g_tree_foreach(s->domains, reconstruct_endpoints, s);
+
+ /*
+ * Memory regions are dynamically turned on/off depending on
+ * 'config.bypass' and attached domain type if there is. After
+ * migration, we need to make sure the memory regions are
+ * still correct.
+ */
+ virtio_iommu_switch_address_space_all(s);
return 0;
}