Re: [PATCH RFC 2/2] vhost: packed ring support
On 2018年02月27日 17:03, Tiwei Bie wrote: On Wed, Feb 14, 2018 at 10:37:09AM +0800, Jason Wang wrote: [...] +static void set_desc_used(struct vhost_virtqueue *vq, + struct vring_desc_packed *desc, bool wrap_counter) +{ + __virtio16 flags = desc->flags; + + if (wrap_counter) { + desc->flags |= cpu_to_vhost16(vq, DESC_AVAIL); + desc->flags |= cpu_to_vhost16(vq, DESC_USED); + } else { + desc->flags &= ~cpu_to_vhost16(vq, DESC_AVAIL); + desc->flags &= ~cpu_to_vhost16(vq, DESC_USED); + } + + desc->flags = flags; The `desc->flags` is restored after the change. Right, will fix. +} + +static int vhost_get_vq_desc_packed(struct vhost_virtqueue *vq, + struct iovec iov[], unsigned int iov_size, + unsigned int *out_num, unsigned int *in_num, + struct vhost_log *log, + unsigned int *log_num) +{ + struct vring_desc_packed desc; + int ret, access, i; + u16 avail_idx = vq->last_avail_idx; + + /* When we start there are none of either input nor output. */ + *out_num = *in_num = 0; + if (unlikely(log)) + *log_num = 0; + + do { + unsigned int iov_count = *in_num + *out_num; + + i = vq->last_avail_idx & (vq->num - 1); The queue size may not be a power of 2 in packed ring. Will fix this too. Thanks Best regards, Tiwei Bie
Re: [PATCH RFC 2/2] vhost: packed ring support
On 2018年02月27日 17:03, Tiwei Bie wrote: On Wed, Feb 14, 2018 at 10:37:09AM +0800, Jason Wang wrote: [...] +static void set_desc_used(struct vhost_virtqueue *vq, + struct vring_desc_packed *desc, bool wrap_counter) +{ + __virtio16 flags = desc->flags; + + if (wrap_counter) { + desc->flags |= cpu_to_vhost16(vq, DESC_AVAIL); + desc->flags |= cpu_to_vhost16(vq, DESC_USED); + } else { + desc->flags &= ~cpu_to_vhost16(vq, DESC_AVAIL); + desc->flags &= ~cpu_to_vhost16(vq, DESC_USED); + } + + desc->flags = flags; The `desc->flags` is restored after the change. Right, will fix. +} + +static int vhost_get_vq_desc_packed(struct vhost_virtqueue *vq, + struct iovec iov[], unsigned int iov_size, + unsigned int *out_num, unsigned int *in_num, + struct vhost_log *log, + unsigned int *log_num) +{ + struct vring_desc_packed desc; + int ret, access, i; + u16 avail_idx = vq->last_avail_idx; + + /* When we start there are none of either input nor output. */ + *out_num = *in_num = 0; + if (unlikely(log)) + *log_num = 0; + + do { + unsigned int iov_count = *in_num + *out_num; + + i = vq->last_avail_idx & (vq->num - 1); The queue size may not be a power of 2 in packed ring. Will fix this too. Thanks Best regards, Tiwei Bie
Re: [PATCH RFC 2/2] vhost: packed ring support
On Wed, Feb 14, 2018 at 10:37:09AM +0800, Jason Wang wrote: [...] > +static void set_desc_used(struct vhost_virtqueue *vq, > + struct vring_desc_packed *desc, bool wrap_counter) > +{ > + __virtio16 flags = desc->flags; > + > + if (wrap_counter) { > + desc->flags |= cpu_to_vhost16(vq, DESC_AVAIL); > + desc->flags |= cpu_to_vhost16(vq, DESC_USED); > + } else { > + desc->flags &= ~cpu_to_vhost16(vq, DESC_AVAIL); > + desc->flags &= ~cpu_to_vhost16(vq, DESC_USED); > + } > + > + desc->flags = flags; The `desc->flags` is restored after the change. > +} > + > +static int vhost_get_vq_desc_packed(struct vhost_virtqueue *vq, > + struct iovec iov[], unsigned int iov_size, > + unsigned int *out_num, unsigned int *in_num, > + struct vhost_log *log, > + unsigned int *log_num) > +{ > + struct vring_desc_packed desc; > + int ret, access, i; > + u16 avail_idx = vq->last_avail_idx; > + > + /* When we start there are none of either input nor output. */ > + *out_num = *in_num = 0; > + if (unlikely(log)) > + *log_num = 0; > + > + do { > + unsigned int iov_count = *in_num + *out_num; > + > + i = vq->last_avail_idx & (vq->num - 1); The queue size may not be a power of 2 in packed ring. Best regards, Tiwei Bie
Re: [PATCH RFC 2/2] vhost: packed ring support
On Wed, Feb 14, 2018 at 10:37:09AM +0800, Jason Wang wrote: [...] > +static void set_desc_used(struct vhost_virtqueue *vq, > + struct vring_desc_packed *desc, bool wrap_counter) > +{ > + __virtio16 flags = desc->flags; > + > + if (wrap_counter) { > + desc->flags |= cpu_to_vhost16(vq, DESC_AVAIL); > + desc->flags |= cpu_to_vhost16(vq, DESC_USED); > + } else { > + desc->flags &= ~cpu_to_vhost16(vq, DESC_AVAIL); > + desc->flags &= ~cpu_to_vhost16(vq, DESC_USED); > + } > + > + desc->flags = flags; The `desc->flags` is restored after the change. > +} > + > +static int vhost_get_vq_desc_packed(struct vhost_virtqueue *vq, > + struct iovec iov[], unsigned int iov_size, > + unsigned int *out_num, unsigned int *in_num, > + struct vhost_log *log, > + unsigned int *log_num) > +{ > + struct vring_desc_packed desc; > + int ret, access, i; > + u16 avail_idx = vq->last_avail_idx; > + > + /* When we start there are none of either input nor output. */ > + *out_num = *in_num = 0; > + if (unlikely(log)) > + *log_num = 0; > + > + do { > + unsigned int iov_count = *in_num + *out_num; > + > + i = vq->last_avail_idx & (vq->num - 1); The queue size may not be a power of 2 in packed ring. Best regards, Tiwei Bie
[PATCH RFC 2/2] vhost: packed ring support
Signed-off-by: Jason Wang--- drivers/vhost/net.c | 14 +- drivers/vhost/vhost.c | 351 ++ drivers/vhost/vhost.h | 6 +- 3 files changed, 343 insertions(+), 28 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index c613d2e..65b27c9 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -67,7 +67,8 @@ enum { VHOST_NET_FEATURES = VHOST_FEATURES | (1ULL << VHOST_NET_F_VIRTIO_NET_HDR) | (1ULL << VIRTIO_NET_F_MRG_RXBUF) | -(1ULL << VIRTIO_F_IOMMU_PLATFORM) +(1ULL << VIRTIO_F_IOMMU_PLATFORM) | +(1ULL << VIRTIO_F_RING_PACKED) }; enum { @@ -473,6 +474,7 @@ static void handle_tx(struct vhost_net *net) struct socket *sock; struct vhost_net_ubuf_ref *uninitialized_var(ubufs); bool zcopy, zcopy_used; + struct vring_used_elem used; mutex_lock(>mutex); sock = vq->private_data; @@ -494,6 +496,8 @@ static void handle_tx(struct vhost_net *net) vhost_zerocopy_signal_used(net, vq); + used.idx = vq->last_avail_idx & (vq->num - 1); + used.wrap_counter = vq->used_wrap_counter; head = vhost_net_tx_get_vq_desc(net, vq, vq->iov, ARRAY_SIZE(vq->iov), , ); @@ -515,6 +519,8 @@ static void handle_tx(struct vhost_net *net) } /* Skip header. TODO: support TSO. */ len = iov_length(vq->iov, out); + used.id = head; + used.len = 0; iov_iter_init(_iter, WRITE, vq->iov, out, len); iov_iter_advance(_iter, hdr_size); /* Sanity check */ @@ -576,7 +582,7 @@ static void handle_tx(struct vhost_net *net) pr_debug("Truncated TX packet: " " len %d != %zd\n", err, len); if (!zcopy_used) - vhost_add_used_and_signal(>dev, vq, head, 0); + vhost_add_used_and_signal_n(>dev, vq, , 1); else vhost_zerocopy_signal_used(net, vq); vhost_net_tx_packet(net); @@ -691,6 +697,8 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, r = -ENOBUFS; goto err; } + heads[headcount].idx = vq->last_avail_idx & (vq->num - 1); + heads[headcount].wrap_counter = vq->used_wrap_counter; r = vhost_get_vq_desc(vq, vq->iov + seg, ARRAY_SIZE(vq->iov) - seg, , , log, log_num); @@ -780,6 +788,8 @@ static void handle_rx(struct vhost_net *net) vq_log = unlikely(vhost_has_feature(vq, VHOST_F_LOG_ALL)) ? vq->log : NULL; mergeable = vhost_has_feature(vq, VIRTIO_NET_F_MRG_RXBUF); + /* FIXME: workaround for current dpdk prototype */ + mergeable = false; while ((sock_len = vhost_net_rx_peek_head_len(net, sock->sk))) { sock_len += sock_hlen; diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 2db5af8..5667d03 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -324,6 +324,7 @@ static void vhost_vq_reset(struct vhost_dev *dev, vhost_reset_is_le(vq); vhost_disable_cross_endian(vq); vq->busyloop_timeout = 0; + vq->used_wrap_counter = true; vq->umem = NULL; vq->iotlb = NULL; __vhost_vq_meta_reset(vq); @@ -1136,10 +1137,22 @@ static int vhost_iotlb_miss(struct vhost_virtqueue *vq, u64 iova, int access) return 0; } -static int vq_access_ok(struct vhost_virtqueue *vq, unsigned int num, - struct vring_desc __user *desc, - struct vring_avail __user *avail, - struct vring_used __user *used) +static int vq_access_ok_packed(struct vhost_virtqueue *vq, unsigned int num, + struct vring_desc __user *desc, + struct vring_avail __user *avail, + struct vring_used __user *used) +{ + struct vring_desc_packed *packed = (struct vring_desc_packed *)desc; + + /* FIXME: check device area and driver area */ + return access_ok(VERIFY_READ, packed, num * sizeof(*packed)) && + access_ok(VERIFY_WRITE, packed, num * sizeof(*packed)); +} + +static int vq_access_ok_split(struct vhost_virtqueue *vq, unsigned int num, + struct vring_desc __user *desc, + struct vring_avail __user *avail, + struct vring_used __user *used) { size_t s = vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX) ?
[PATCH RFC 2/2] vhost: packed ring support
Signed-off-by: Jason Wang --- drivers/vhost/net.c | 14 +- drivers/vhost/vhost.c | 351 ++ drivers/vhost/vhost.h | 6 +- 3 files changed, 343 insertions(+), 28 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index c613d2e..65b27c9 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -67,7 +67,8 @@ enum { VHOST_NET_FEATURES = VHOST_FEATURES | (1ULL << VHOST_NET_F_VIRTIO_NET_HDR) | (1ULL << VIRTIO_NET_F_MRG_RXBUF) | -(1ULL << VIRTIO_F_IOMMU_PLATFORM) +(1ULL << VIRTIO_F_IOMMU_PLATFORM) | +(1ULL << VIRTIO_F_RING_PACKED) }; enum { @@ -473,6 +474,7 @@ static void handle_tx(struct vhost_net *net) struct socket *sock; struct vhost_net_ubuf_ref *uninitialized_var(ubufs); bool zcopy, zcopy_used; + struct vring_used_elem used; mutex_lock(>mutex); sock = vq->private_data; @@ -494,6 +496,8 @@ static void handle_tx(struct vhost_net *net) vhost_zerocopy_signal_used(net, vq); + used.idx = vq->last_avail_idx & (vq->num - 1); + used.wrap_counter = vq->used_wrap_counter; head = vhost_net_tx_get_vq_desc(net, vq, vq->iov, ARRAY_SIZE(vq->iov), , ); @@ -515,6 +519,8 @@ static void handle_tx(struct vhost_net *net) } /* Skip header. TODO: support TSO. */ len = iov_length(vq->iov, out); + used.id = head; + used.len = 0; iov_iter_init(_iter, WRITE, vq->iov, out, len); iov_iter_advance(_iter, hdr_size); /* Sanity check */ @@ -576,7 +582,7 @@ static void handle_tx(struct vhost_net *net) pr_debug("Truncated TX packet: " " len %d != %zd\n", err, len); if (!zcopy_used) - vhost_add_used_and_signal(>dev, vq, head, 0); + vhost_add_used_and_signal_n(>dev, vq, , 1); else vhost_zerocopy_signal_used(net, vq); vhost_net_tx_packet(net); @@ -691,6 +697,8 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, r = -ENOBUFS; goto err; } + heads[headcount].idx = vq->last_avail_idx & (vq->num - 1); + heads[headcount].wrap_counter = vq->used_wrap_counter; r = vhost_get_vq_desc(vq, vq->iov + seg, ARRAY_SIZE(vq->iov) - seg, , , log, log_num); @@ -780,6 +788,8 @@ static void handle_rx(struct vhost_net *net) vq_log = unlikely(vhost_has_feature(vq, VHOST_F_LOG_ALL)) ? vq->log : NULL; mergeable = vhost_has_feature(vq, VIRTIO_NET_F_MRG_RXBUF); + /* FIXME: workaround for current dpdk prototype */ + mergeable = false; while ((sock_len = vhost_net_rx_peek_head_len(net, sock->sk))) { sock_len += sock_hlen; diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 2db5af8..5667d03 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -324,6 +324,7 @@ static void vhost_vq_reset(struct vhost_dev *dev, vhost_reset_is_le(vq); vhost_disable_cross_endian(vq); vq->busyloop_timeout = 0; + vq->used_wrap_counter = true; vq->umem = NULL; vq->iotlb = NULL; __vhost_vq_meta_reset(vq); @@ -1136,10 +1137,22 @@ static int vhost_iotlb_miss(struct vhost_virtqueue *vq, u64 iova, int access) return 0; } -static int vq_access_ok(struct vhost_virtqueue *vq, unsigned int num, - struct vring_desc __user *desc, - struct vring_avail __user *avail, - struct vring_used __user *used) +static int vq_access_ok_packed(struct vhost_virtqueue *vq, unsigned int num, + struct vring_desc __user *desc, + struct vring_avail __user *avail, + struct vring_used __user *used) +{ + struct vring_desc_packed *packed = (struct vring_desc_packed *)desc; + + /* FIXME: check device area and driver area */ + return access_ok(VERIFY_READ, packed, num * sizeof(*packed)) && + access_ok(VERIFY_WRITE, packed, num * sizeof(*packed)); +} + +static int vq_access_ok_split(struct vhost_virtqueue *vq, unsigned int num, + struct vring_desc __user *desc, + struct vring_avail __user *avail, + struct vring_used __user *used) { size_t s = vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX) ? 2 : 0; @@ -1151,6