diff options
-rw-r--r-- | drivers/vhost/net.c | 4 | ||||
-rw-r--r-- | drivers/vhost/test.c | 5 | ||||
-rw-r--r-- | drivers/vhost/vhost.c | 87 | ||||
-rw-r--r-- | drivers/vhost/vhost.h | 1 |
4 files changed, 64 insertions, 33 deletions
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index f0fd52cdfadc..70ac60437d17 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c | |||
@@ -703,6 +703,10 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) | |||
703 | vhost_net_disable_vq(n, vq); | 703 | vhost_net_disable_vq(n, vq); |
704 | rcu_assign_pointer(vq->private_data, sock); | 704 | rcu_assign_pointer(vq->private_data, sock); |
705 | vhost_net_enable_vq(n, vq); | 705 | vhost_net_enable_vq(n, vq); |
706 | |||
707 | r = vhost_init_used(vq); | ||
708 | if (r) | ||
709 | goto err_vq; | ||
706 | } | 710 | } |
707 | 711 | ||
708 | mutex_unlock(&vq->mutex); | 712 | mutex_unlock(&vq->mutex); |
diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c index 734e1d74ad80..fc9a1d75281f 100644 --- a/drivers/vhost/test.c +++ b/drivers/vhost/test.c | |||
@@ -195,8 +195,13 @@ static long vhost_test_run(struct vhost_test *n, int test) | |||
195 | lockdep_is_held(&vq->mutex)); | 195 | lockdep_is_held(&vq->mutex)); |
196 | rcu_assign_pointer(vq->private_data, priv); | 196 | rcu_assign_pointer(vq->private_data, priv); |
197 | 197 | ||
198 | r = vhost_init_used(&n->vqs[index]); | ||
199 | |||
198 | mutex_unlock(&vq->mutex); | 200 | mutex_unlock(&vq->mutex); |
199 | 201 | ||
202 | if (r) | ||
203 | goto err; | ||
204 | |||
200 | if (oldpriv) { | 205 | if (oldpriv) { |
201 | vhost_test_flush_vq(n, index); | 206 | vhost_test_flush_vq(n, index); |
202 | } | 207 | } |
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 5ef2f62becf4..c14c42b95ab8 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
@@ -629,17 +629,6 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) | |||
629 | return 0; | 629 | return 0; |
630 | } | 630 | } |
631 | 631 | ||
632 | static int init_used(struct vhost_virtqueue *vq, | ||
633 | struct vring_used __user *used) | ||
634 | { | ||
635 | int r = put_user(vq->used_flags, &used->flags); | ||
636 | |||
637 | if (r) | ||
638 | return r; | ||
639 | vq->signalled_used_valid = false; | ||
640 | return get_user(vq->last_used_idx, &used->idx); | ||
641 | } | ||
642 | |||
643 | static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | 632 | static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) |
644 | { | 633 | { |
645 | struct file *eventfp, *filep = NULL, | 634 | struct file *eventfp, *filep = NULL, |
@@ -752,10 +741,6 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
752 | } | 741 | } |
753 | } | 742 | } |
754 | 743 | ||
755 | r = init_used(vq, (struct vring_used __user *)(unsigned long) | ||
756 | a.used_user_addr); | ||
757 | if (r) | ||
758 | break; | ||
759 | vq->log_used = !!(a.flags & (0x1 << VHOST_VRING_F_LOG)); | 744 | vq->log_used = !!(a.flags & (0x1 << VHOST_VRING_F_LOG)); |
760 | vq->desc = (void __user *)(unsigned long)a.desc_user_addr; | 745 | vq->desc = (void __user *)(unsigned long)a.desc_user_addr; |
761 | vq->avail = (void __user *)(unsigned long)a.avail_user_addr; | 746 | vq->avail = (void __user *)(unsigned long)a.avail_user_addr; |
@@ -1010,6 +995,57 @@ int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, | |||
1010 | return 0; | 995 | return 0; |
1011 | } | 996 | } |
1012 | 997 | ||
998 | static int vhost_update_used_flags(struct vhost_virtqueue *vq) | ||
999 | { | ||
1000 | void __user *used; | ||
1001 | if (__put_user(vq->used_flags, &vq->used->flags) < 0) | ||
1002 | return -EFAULT; | ||
1003 | if (unlikely(vq->log_used)) { | ||
1004 | /* Make sure the flag is seen before log. */ | ||
1005 | smp_wmb(); | ||
1006 | /* Log used flag write. */ | ||
1007 | used = &vq->used->flags; | ||
1008 | log_write(vq->log_base, vq->log_addr + | ||
1009 | (used - (void __user *)vq->used), | ||
1010 | sizeof vq->used->flags); | ||
1011 | if (vq->log_ctx) | ||
1012 | eventfd_signal(vq->log_ctx, 1); | ||
1013 | } | ||
1014 | return 0; | ||
1015 | } | ||
1016 | |||
1017 | static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event) | ||
1018 | { | ||
1019 | if (__put_user(vq->avail_idx, vhost_avail_event(vq))) | ||
1020 | return -EFAULT; | ||
1021 | if (unlikely(vq->log_used)) { | ||
1022 | void __user *used; | ||
1023 | /* Make sure the event is seen before log. */ | ||
1024 | smp_wmb(); | ||
1025 | /* Log avail event write */ | ||
1026 | used = vhost_avail_event(vq); | ||
1027 | log_write(vq->log_base, vq->log_addr + | ||
1028 | (used - (void __user *)vq->used), | ||
1029 | sizeof *vhost_avail_event(vq)); | ||
1030 | if (vq->log_ctx) | ||
1031 | eventfd_signal(vq->log_ctx, 1); | ||
1032 | } | ||
1033 | return 0; | ||
1034 | } | ||
1035 | |||
1036 | int vhost_init_used(struct vhost_virtqueue *vq) | ||
1037 | { | ||
1038 | int r; | ||
1039 | if (!vq->private_data) | ||
1040 | return 0; | ||
1041 | |||
1042 | r = vhost_update_used_flags(vq); | ||
1043 | if (r) | ||
1044 | return r; | ||
1045 | vq->signalled_used_valid = false; | ||
1046 | return get_user(vq->last_used_idx, &vq->used->idx); | ||
1047 | } | ||
1048 | |||
1013 | static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len, | 1049 | static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len, |
1014 | struct iovec iov[], int iov_size) | 1050 | struct iovec iov[], int iov_size) |
1015 | { | 1051 | { |
@@ -1481,34 +1517,20 @@ bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) | |||
1481 | return false; | 1517 | return false; |
1482 | vq->used_flags &= ~VRING_USED_F_NO_NOTIFY; | 1518 | vq->used_flags &= ~VRING_USED_F_NO_NOTIFY; |
1483 | if (!vhost_has_feature(dev, VIRTIO_RING_F_EVENT_IDX)) { | 1519 | if (!vhost_has_feature(dev, VIRTIO_RING_F_EVENT_IDX)) { |
1484 | r = put_user(vq->used_flags, &vq->used->flags); | 1520 | r = vhost_update_used_flags(vq); |
1485 | if (r) { | 1521 | if (r) { |
1486 | vq_err(vq, "Failed to enable notification at %p: %d\n", | 1522 | vq_err(vq, "Failed to enable notification at %p: %d\n", |
1487 | &vq->used->flags, r); | 1523 | &vq->used->flags, r); |
1488 | return false; | 1524 | return false; |
1489 | } | 1525 | } |
1490 | } else { | 1526 | } else { |
1491 | r = put_user(vq->avail_idx, vhost_avail_event(vq)); | 1527 | r = vhost_update_avail_event(vq, vq->avail_idx); |
1492 | if (r) { | 1528 | if (r) { |
1493 | vq_err(vq, "Failed to update avail event index at %p: %d\n", | 1529 | vq_err(vq, "Failed to update avail event index at %p: %d\n", |
1494 | vhost_avail_event(vq), r); | 1530 | vhost_avail_event(vq), r); |
1495 | return false; | 1531 | return false; |
1496 | } | 1532 | } |
1497 | } | 1533 | } |
1498 | if (unlikely(vq->log_used)) { | ||
1499 | void __user *used; | ||
1500 | /* Make sure data is seen before log. */ | ||
1501 | smp_wmb(); | ||
1502 | used = vhost_has_feature(dev, VIRTIO_RING_F_EVENT_IDX) ? | ||
1503 | &vq->used->flags : vhost_avail_event(vq); | ||
1504 | /* Log used flags or event index entry write. Both are 16 bit | ||
1505 | * fields. */ | ||
1506 | log_write(vq->log_base, vq->log_addr + | ||
1507 | (used - (void __user *)vq->used), | ||
1508 | sizeof(u16)); | ||
1509 | if (vq->log_ctx) | ||
1510 | eventfd_signal(vq->log_ctx, 1); | ||
1511 | } | ||
1512 | /* They could have slipped one in as we were doing that: make | 1534 | /* They could have slipped one in as we were doing that: make |
1513 | * sure it's written, then check again. */ | 1535 | * sure it's written, then check again. */ |
1514 | smp_mb(); | 1536 | smp_mb(); |
@@ -1531,7 +1553,7 @@ void vhost_disable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) | |||
1531 | return; | 1553 | return; |
1532 | vq->used_flags |= VRING_USED_F_NO_NOTIFY; | 1554 | vq->used_flags |= VRING_USED_F_NO_NOTIFY; |
1533 | if (!vhost_has_feature(dev, VIRTIO_RING_F_EVENT_IDX)) { | 1555 | if (!vhost_has_feature(dev, VIRTIO_RING_F_EVENT_IDX)) { |
1534 | r = put_user(vq->used_flags, &vq->used->flags); | 1556 | r = vhost_update_used_flags(vq); |
1535 | if (r) | 1557 | if (r) |
1536 | vq_err(vq, "Failed to enable notification at %p: %d\n", | 1558 | vq_err(vq, "Failed to enable notification at %p: %d\n", |
1537 | &vq->used->flags, r); | 1559 | &vq->used->flags, r); |
@@ -1556,7 +1578,6 @@ struct vhost_ubuf_ref *vhost_ubuf_alloc(struct vhost_virtqueue *vq, | |||
1556 | if (!ubufs) | 1578 | if (!ubufs) |
1557 | return ERR_PTR(-ENOMEM); | 1579 | return ERR_PTR(-ENOMEM); |
1558 | kref_init(&ubufs->kref); | 1580 | kref_init(&ubufs->kref); |
1559 | kref_get(&ubufs->kref); | ||
1560 | init_waitqueue_head(&ubufs->wait); | 1581 | init_waitqueue_head(&ubufs->wait); |
1561 | ubufs->vq = vq; | 1582 | ubufs->vq = vq; |
1562 | return ubufs; | 1583 | return ubufs; |
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 1544b782529b..14c9abf0d800 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h | |||
@@ -174,6 +174,7 @@ int vhost_get_vq_desc(struct vhost_dev *, struct vhost_virtqueue *, | |||
174 | struct vhost_log *log, unsigned int *log_num); | 174 | struct vhost_log *log, unsigned int *log_num); |
175 | void vhost_discard_vq_desc(struct vhost_virtqueue *, int n); | 175 | void vhost_discard_vq_desc(struct vhost_virtqueue *, int n); |
176 | 176 | ||
177 | int vhost_init_used(struct vhost_virtqueue *); | ||
177 | int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len); | 178 | int vhost_add_used(struct vhost_virtqueue *, unsigned int head, int len); |
178 | int vhost_add_used_n(struct vhost_virtqueue *, struct vring_used_elem *heads, | 179 | int vhost_add_used_n(struct vhost_virtqueue *, struct vring_used_elem *heads, |
179 | unsigned count); | 180 | unsigned count); |