Re: [PATCH RFC 2/2] vhost: packed ring support

2018-02-27 Thread Jason Wang



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

2018-02-27 Thread Jason Wang



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

2018-02-27 Thread Tiwei Bie
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

2018-02-27 Thread Tiwei Bie
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

2018-02-13 Thread Jason Wang
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

2018-02-13 Thread Jason Wang
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