vhost: accelerate metadata access through vmap()
Subsystems (6)
cover vhost: accelerate metadata access through vmap()
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of copy_user() friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual address
drivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)
Signature · 1 line
2.17.1
PATCH 1/3 vhost: generalize adding used elem
Use one generic vhost_copy_to_user() instead of two dedicated accessor. This will simplify the conversion to fine grain accessors.
--- drivers/vhost/vhost.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-)
drivers/vhost/vhost.c +1 -10
@@ -2164,16 +2164,7 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq, start = vq->last_used_idx & (vq->num -1 ); used = vq->used->ring + start; -if (count ==1 ) { -if (vhost_put_user (vq, heads[0 ].id, &used->id)) { -vq_err (vq,"Failed to write used id" ); -return -EFAULT ; - } -if (vhost_put_user (vq, heads[0 ].len, &used->len)) { -vq_err (vq,"Failed to write used len" ); -return -EFAULT ; - } - }else if (vhost_copy_to_user (vq, used, heads, count *sizeof *used)) { +if (vhost_copy_to_user (vq, used, heads, count *sizeof *used)) {vq_err (vq,"Failed to write used" );return -EFAULT ; }
Signature · 1 line
2.17.1
Michael S. Tsirkin
maintainerRe: [PATCH net-next 1/3] vhost: generalize adding used elem
Quoted 4 lines · Jason Wang
Use one generic
vhost_copy_to_user()instead of two dedicated accessor. This will simplify the conversion to fine grain accessors.Signed-off-by Jason Wang <[email protected]>
The reason we did it like this is because it was faster. Want to try benchmarking before we change it?
Quoted 28 lines
--- drivers/vhost/vhost.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-)drivers/vhost/vhost.c +1
-10@@ -2164,16 +2164,7 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq, start = vq->last_used_idx & (vq->num -1 ); used = vq->used->ring + start; -if (count ==1 ) { -if (vhost_put_user (vq, heads[0 ].id, &used->id)) { -vq_err (vq,"Failed to write used id" ); -return -EFAULT ; - } -if (vhost_put_user (vq, heads[0 ].len, &used->len)) { -vq_err (vq,"Failed to write used len" ); -return -EFAULT ; - } - }else if (vhost_copy_to_user (vq, used, heads, count *sizeof *used)) { +if (vhost_copy_to_user (vq, used, heads, count *sizeof *used)) {vq_err (vq,"Failed to write used" );return -EFAULT ; }Signature · 1 line
2.17.1
Re: [PATCH net-next 1/3] vhost: generalize adding used elem
Quoted 8 lines · Michael S. Tsirkin
Quoted 4 lines · Jason Wang
Use one generic
vhost_copy_to_user()instead of two dedicated accessor. This will simplify the conversion to fine grain accessors.Signed-off-by Jason Wang <[email protected]>The reason we did it like this is because it was faster. Want to try benchmarking before we change it?
Faster is a good side effect of such conversion. Otherwise we need two new fine grain memory accessor.
But, anyway, I can test its impact.
Thanks
Quoted 29 lines
Quoted 29 lines
--- drivers/vhost/vhost.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-)drivers/vhost/vhost.c +1
-10@@ -2164,16 +2164,7 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq, start = vq->last_used_idx & (vq->num -1 ); used = vq->used->ring + start; -if (count ==1 ) { -if (vhost_put_user (vq, heads[0 ].id, &used->id)) { -vq_err (vq,"Failed to write used id" ); -return -EFAULT ; - } -if (vhost_put_user (vq, heads[0 ].len, &used->len)) { -vq_err (vq,"Failed to write used len" ); -return -EFAULT ; - } - }else if (vhost_copy_to_user (vq, used, heads, count *sizeof *used)) { +if (vhost_copy_to_user (vq, used, heads, count *sizeof *used)) {vq_err (vq,"Failed to write used" );return -EFAULT ; }Signature · 1 line
2.17.1
Re: [PATCH net-next 1/3] vhost: generalize adding used elem
In reply to Michael S. TsirkinQuoted 8 lines · Michael S. Tsirkin
Quoted 4 lines · Jason Wang
Use one generic
vhost_copy_to_user()instead of two dedicated accessor. This will simplify the conversion to fine grain accessors.Signed-off-by Jason Wang <[email protected]>The reason we did it like this is because it was faster. Want to try benchmarking before we change it?
Faster is a good side effect of such conversion. Otherwise we need two new fine grain memory accessor.
But, anyway, I can test its impact.
Thanks
Quoted 21 lines
Quoted 21 lines
--- drivers/vhost/vhost.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-)drivers/vhost/vhost.c +0
-8@@ -2164,16 +2164,7 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq, start = vq->last_used_idx & (vq->num -1 ); used = vq->used->ring + start; -if (count ==1 ) { -if (vhost_put_user (vq, heads[0 ].id, &used->id)) { -vq_err (vq,"Failed to write used id" ); -return -EFAULT ; - } -if (vhost_put_user (vq, heads[0 ].len, &used->len)) { -vq_err (vq,"Failed to write used len" ); -return -EFAULT ;
Quoted 8 lines
Quoted 8 lines
drivers/vhost/vhost.c +1
-2- } - }else if (vhost_copy_to_user (vq, used, heads, count *sizeof *used)) { +if (vhost_copy_to_user (vq, used, heads, count *sizeof *used)) {vq_err (vq,"Failed to write used" );return -EFAULT ; }Signature · 1 line
2.17.1
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Michael S. Tsirkin
maintainerRe: [PATCH net-next 1/3] vhost: generalize adding used elem
In reply to Jason WangQuoted 4 lines · Jason Wang
Use one generic
vhost_copy_to_user()instead of two dedicated accessor. This will simplify the conversion to fine grain accessors.Signed-off-by Jason Wang <[email protected]>
The reason we did it like this is because it was faster. Want to try benchmarking before we change it?
Quoted 28 lines
--- drivers/vhost/vhost.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-)drivers/vhost/vhost.c +1
-10@@ -2164,16 +2164,7 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq, start = vq->last_used_idx & (vq->num -1 ); used = vq->used->ring + start; -if (count ==1 ) { -if (vhost_put_user (vq, heads[0 ].id, &used->id)) { -vq_err (vq,"Failed to write used id" ); -return -EFAULT ; - } -if (vhost_put_user (vq, heads[0 ].len, &used->len)) { -vq_err (vq,"Failed to write used len" ); -return -EFAULT ; - } - }else if (vhost_copy_to_user (vq, used, heads, count *sizeof *used)) { +if (vhost_copy_to_user (vq, used, heads, count *sizeof *used)) {vq_err (vq,"Failed to write used" );return -EFAULT ; }Signature · 1 line
2.17.1
PATCH 1/3 vhost: generalize adding used elem
In reply to Jason WangUse one generic vhost_copy_to_user() instead of two dedicated accessor. This will simplify the conversion to fine grain accessors.
--- drivers/vhost/vhost.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-)
drivers/vhost/vhost.c +1 -10
@@ -2164,16 +2164,7 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq, start = vq->last_used_idx & (vq->num -1 ); used = vq->used->ring + start; -if (count ==1 ) { -if (vhost_put_user (vq, heads[0 ].id, &used->id)) { -vq_err (vq,"Failed to write used id" ); -return -EFAULT ; - } -if (vhost_put_user (vq, heads[0 ].len, &used->len)) { -vq_err (vq,"Failed to write used len" ); -return -EFAULT ; - } - }else if (vhost_copy_to_user (vq, used, heads, count *sizeof *used)) { +if (vhost_copy_to_user (vq, used, heads, count *sizeof *used)) {vq_err (vq,"Failed to write used" );return -EFAULT ; }
Signature · 1 line
2.17.1
PATCH 2/3 vhost: fine grain userspace memory accessors
In reply to Jason WangThis is used to hide the metadata address from virtqueue helpers. This will allow to implement a vmap based fast accessing to metadata.
--- drivers/vhost/vhost.c | 94 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 77 insertions(+), 17 deletions(-)
drivers/vhost/vhost.c +77 -17
@@ -871,6 +871,34 @@ static inline void __user *__vhost_get_user(struct vhost_virtqueue *vq, ret; \ }) +static inline int vhost_put_avail_event (struct vhost_virtqueue *vq) +{ +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->avail_idx), +vhost_avail_event (vq)); +} + +static inline int vhost_put_used (struct vhost_virtqueue *vq, +struct vring_used_elem *head,int idx, +int count) +{ +return vhost_copy_to_user (vq, vq->used->ring + idx, head, + count *sizeof (*head)); +} + +static inline int vhost_put_used_flags (struct vhost_virtqueue *vq) + +{ +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->used_flags), + &vq->used->flags); +} + +static inline int vhost_put_used_idx (struct vhost_virtqueue *vq) + +{ +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->last_used_idx), + &vq->used->idx); +} +#define vhost_get_user (vq, x, ptr, type) \ ({ \ int ret; \
@@ -895,6 +923,43 @@ static inline void __user *__vhost_get_user(struct vhost_virtqueue *vq,#define vhost_get_used (vq, x, ptr) \ vhost_get_user(vq, x, ptr, VHOST_ADDR_USED) +static inline int vhost_get_avail_idx (struct vhost_virtqueue *vq, +__virtio16 *idx) +{ +return vhost_get_avail (vq, *idx, &vq->avail->idx); +} + +static inline int vhost_get_avail_head (struct vhost_virtqueue *vq, +__virtio16 *head,int idx) +{ +return vhost_get_avail (vq, *head, + &vq->avail->ring[idx & (vq->num -1 )]); +} + +static inline int vhost_get_avail_flags (struct vhost_virtqueue *vq, +__virtio16 *flags) +{ +return vhost_get_avail (vq, *flags, &vq->avail->flags); +} + +static inline int vhost_get_used_event (struct vhost_virtqueue *vq, +__virtio16 *event) +{ +return vhost_get_avail (vq, *event,vhost_used_event (vq)); +} + +static inline int vhost_get_used_idx (struct vhost_virtqueue *vq, +__virtio16 *idx) +{ +return vhost_get_used (vq, *idx, &vq->used->idx); +} + +static inline int vhost_get_desc (struct vhost_virtqueue *vq, +struct vring_desc *desc,int idx) +{ +return vhost_copy_from_user (vq, desc, vq->desc + idx,sizeof (*desc)); +} +static int vhost_new_umem_range (struct vhost_umem *umem,u64 start,u64 size,u64 end,u64 userspace_addr,int perm)
@@ -1751,8 +1816,7 @@ EXPORT_SYMBOL_GPL(vhost_log_write);static int vhost_update_used_flags (struct vhost_virtqueue *vq) {void __user *used; -if (vhost_put_user (vq,cpu_to_vhost16 (vq, vq->used_flags), - &vq->used->flags) <0 ) +if (vhost_put_used_flags (vq))return -EFAULT ;if (unlikely (vq->log_used)) {/* Make sure the flag is seen before log. */
@@ -1770,8 +1834,7 @@ static int vhost_update_used_flags(struct vhost_virtqueue *vq)static int vhost_update_avail_event (struct vhost_virtqueue *vq,u16 avail_event) { -if (vhost_put_user (vq,cpu_to_vhost16 (vq, vq->avail_idx), -vhost_avail_event (vq))) +if (vhost_put_avail_event (vq))return -EFAULT ;if (unlikely (vq->log_used)) {void __user *used;
@@ -1808,7 +1871,7 @@ int vhost_vq_init_access(struct vhost_virtqueue *vq) r = -EFAULT ; goto err; } - r =vhost_get_used (vq, last_used_idx, &vq->used->idx); + r =vhost_get_used_idx (vq, &last_used_idx);if (r) {vq_err (vq,"Can't access used idx at %p\n" , &vq->used->idx);
@@ -2007,7 +2070,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq, last_avail_idx = vq->last_avail_idx;if (vq->avail_idx == vq->last_avail_idx) { -if (unlikely (vhost_get_avail (vq, avail_idx, &vq->avail->idx))) { +if (unlikely (vhost_get_avail_idx (vq, &avail_idx))) {vq_err (vq,"Failed to access avail idx at %p\n" , &vq->avail->idx);return -EFAULT ;
@@ -2034,8 +2097,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,/* Grab the next descriptor number they're advertising, and increment * the index we've seen. */ -if (unlikely (vhost_get_avail (vq, ring_head, - &vq->avail->ring[last_avail_idx & (vq->num -1 )]))) { +if (unlikely (vhost_get_avail_head (vq, &ring_head, last_avail_idx))) {vq_err (vq,"Failed to read head: idx %d address %p\n" , last_avail_idx, &vq->avail->ring[last_avail_idx % vq->num]);
@@ -2070,8 +2132,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq, i, vq->num, head);return -EINVAL ; } - ret =vhost_copy_from_user (vq, &desc, vq->desc + i, -sizeof desc); + ret =vhost_get_desc (vq, &desc, i);if (unlikely (ret)) {vq_err (vq,"Failed to get descriptor: idx %d addr %p\n" , i, vq->desc + i);
@@ -2164,7 +2225,7 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq, start = vq->last_used_idx & (vq->num -1 ); used = vq->used->ring + start; -if (vhost_copy_to_user (vq, used, heads, count *sizeof *used)) { +if (vhost_put_used (vq, heads, start, count)) {vq_err (vq,"Failed to write used" );return -EFAULT ; }
@@ -2208,8 +2269,7 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,/* Make sure buffer is written before we update index. */ smp_wmb (); -if (vhost_put_user (vq,cpu_to_vhost16 (vq, vq->last_used_idx), - &vq->used->idx)) { +if (vhost_put_used_idx (vq)) {vq_err (vq,"Failed to increment used idx" );return -EFAULT ; }
@@ -2241,7 +2301,7 @@ static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)if (!vhost_has_feature (vq,VIRTIO_RING_F_EVENT_IDX )) {__virtio16 flags; -if (vhost_get_avail (vq, flags, &vq->avail->flags)) { +if (vhost_get_avail_flags (vq, &flags)) {vq_err (vq,"Failed to get flags" );return true; }
@@ -2255,7 +2315,7 @@ static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)if (unlikely (!v))return true; -if (vhost_get_avail (vq, event,vhost_used_event (vq))) { +if (vhost_get_used_event (vq, &event)) {vq_err (vq,"Failed to get used event idx" );return true; }
@@ -2300,7 +2360,7 @@ bool vhost_vq_avail_empty(struct vhost_dev *dev, struct vhost_virtqueue *vq)if (vq->avail_idx != vq->last_avail_idx)return false; - r =vhost_get_avail (vq, avail_idx, &vq->avail->idx); + r =vhost_get_avail_idx (vq, &avail_idx);if (unlikely (r))return false; vq->avail_idx =vhost16_to_cpu (vq, avail_idx);
@@ -2336,7 +2396,7 @@ bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)/* They could have slipped one in as we were doing that: make * sure it's written, then check again. */ smp_mb (); - r =vhost_get_avail (vq, avail_idx, &vq->avail->idx); + r =vhost_get_avail_idx (vq, &avail_idx);if (r) {vq_err (vq,"Failed to check avail idx at %p: %d\n" , &vq->avail->idx, r);
Signature · 1 line
2.17.1
PATCH 2/3 vhost: fine grain userspace memory accessors
In reply to Jason WangThis is used to hide the metadata address from virtqueue helpers. This will allow to implement a vmap based fast accessing to metadata.
--- drivers/vhost/vhost.c | 94 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 77 insertions(+), 17 deletions(-)
drivers/vhost/vhost.c +77 -17
@@ -871,6 +871,34 @@ static inline void __user *__vhost_get_user(struct vhost_virtqueue *vq, ret; \ }) +static inline int vhost_put_avail_event (struct vhost_virtqueue *vq) +{ +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->avail_idx), +vhost_avail_event (vq)); +} + +static inline int vhost_put_used (struct vhost_virtqueue *vq, +struct vring_used_elem *head,int idx, +int count) +{ +return vhost_copy_to_user (vq, vq->used->ring + idx, head, + count *sizeof (*head)); +} + +static inline int vhost_put_used_flags (struct vhost_virtqueue *vq) + +{ +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->used_flags), + &vq->used->flags); +} + +static inline int vhost_put_used_idx (struct vhost_virtqueue *vq) + +{ +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->last_used_idx), + &vq->used->idx); +} +#define vhost_get_user (vq, x, ptr, type) \ ({ \ int ret; \
@@ -895,6 +923,43 @@ static inline void __user *__vhost_get_user(struct vhost_virtqueue *vq,#define vhost_get_used (vq, x, ptr) \ vhost_get_user(vq, x, ptr, VHOST_ADDR_USED) +static inline int vhost_get_avail_idx (struct vhost_virtqueue *vq, +__virtio16 *idx) +{ +return vhost_get_avail (vq, *idx, &vq->avail->idx); +} + +static inline int vhost_get_avail_head (struct vhost_virtqueue *vq, +__virtio16 *head,int idx) +{ +return vhost_get_avail (vq, *head, + &vq->avail->ring[idx & (vq->num -1 )]); +} + +static inline int vhost_get_avail_flags (struct vhost_virtqueue *vq, +__virtio16 *flags) +{ +return vhost_get_avail (vq, *flags, &vq->avail->flags); +} + +static inline int vhost_get_used_event (struct vhost_virtqueue *vq, +__virtio16 *event) +{ +return vhost_get_avail (vq, *event,vhost_used_event (vq)); +} + +static inline int vhost_get_used_idx (struct vhost_virtqueue *vq, +__virtio16 *idx) +{ +return vhost_get_used (vq, *idx, &vq->used->idx); +} + +static inline int vhost_get_desc (struct vhost_virtqueue *vq, +struct vring_desc *desc,int idx) +{ +return vhost_copy_from_user (vq, desc, vq->desc + idx,sizeof (*desc)); +} +static int vhost_new_umem_range (struct vhost_umem *umem,u64 start,u64 size,u64 end,u64 userspace_addr,int perm)
@@ -1751,8 +1816,7 @@ EXPORT_SYMBOL_GPL(vhost_log_write);static int vhost_update_used_flags (struct vhost_virtqueue *vq) {void __user *used; -if (vhost_put_user (vq,cpu_to_vhost16 (vq, vq->used_flags), - &vq->used->flags) <0 ) +if (vhost_put_used_flags (vq))return -EFAULT ;if (unlikely (vq->log_used)) {/* Make sure the flag is seen before log. */
@@ -1770,8 +1834,7 @@ static int vhost_update_used_flags(struct vhost_virtqueue *vq)static int vhost_update_avail_event (struct vhost_virtqueue *vq,u16 avail_event) { -if (vhost_put_user (vq,cpu_to_vhost16 (vq, vq->avail_idx), -vhost_avail_event (vq))) +if (vhost_put_avail_event (vq))return -EFAULT ;if (unlikely (vq->log_used)) {void __user *used;
@@ -1808,7 +1871,7 @@ int vhost_vq_init_access(struct vhost_virtqueue *vq) r = -EFAULT ; goto err; } - r =vhost_get_used (vq, last_used_idx, &vq->used->idx); + r =vhost_get_used_idx (vq, &last_used_idx);if (r) {vq_err (vq,"Can't access used idx at %p\n" , &vq->used->idx);
@@ -2007,7 +2070,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq, last_avail_idx = vq->last_avail_idx;if (vq->avail_idx == vq->last_avail_idx) { -if (unlikely (vhost_get_avail (vq, avail_idx, &vq->avail->idx))) { +if (unlikely (vhost_get_avail_idx (vq, &avail_idx))) {vq_err (vq,"Failed to access avail idx at %p\n" , &vq->avail->idx);return -EFAULT ;
@@ -2034,8 +2097,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,/* Grab the next descriptor number they're advertising, and increment * the index we've seen. */ -if (unlikely (vhost_get_avail (vq, ring_head, - &vq->avail->ring[last_avail_idx & (vq->num -1 )]))) { +if (unlikely (vhost_get_avail_head (vq, &ring_head, last_avail_idx))) {vq_err (vq,"Failed to read head: idx %d address %p\n" , last_avail_idx, &vq->avail->ring[last_avail_idx % vq->num]);
@@ -2070,8 +2132,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq, i, vq->num, head);return -EINVAL ; } - ret =vhost_copy_from_user (vq, &desc, vq->desc + i, -sizeof desc); + ret =vhost_get_desc (vq, &desc, i);if (unlikely (ret)) {vq_err (vq,"Failed to get descriptor: idx %d addr %p\n" , i, vq->desc + i);
@@ -2164,7 +2225,7 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq, start = vq->last_used_idx & (vq->num -1 ); used = vq->used->ring + start; -if (vhost_copy_to_user (vq, used, heads, count *sizeof *used)) { +if (vhost_put_used (vq, heads, start, count)) {vq_err (vq,"Failed to write used" );return -EFAULT ; }
@@ -2208,8 +2269,7 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,/* Make sure buffer is written before we update index. */ smp_wmb (); -if (vhost_put_user (vq,cpu_to_vhost16 (vq, vq->last_used_idx), - &vq->used->idx)) { +if (vhost_put_used_idx (vq)) {vq_err (vq,"Failed to increment used idx" );return -EFAULT ; }
@@ -2241,7 +2301,7 @@ static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)if (!vhost_has_feature (vq,VIRTIO_RING_F_EVENT_IDX )) {__virtio16 flags; -if (vhost_get_avail (vq, flags, &vq->avail->flags)) { +if (vhost_get_avail_flags (vq, &flags)) {vq_err (vq,"Failed to get flags" );return true; }
@@ -2255,7 +2315,7 @@ static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)if (unlikely (!v))return true; -if (vhost_get_avail (vq, event,vhost_used_event (vq))) { +if (vhost_get_used_event (vq, &event)) {vq_err (vq,"Failed to get used event idx" );return true; }
@@ -2300,7 +2360,7 @@ bool vhost_vq_avail_empty(struct vhost_dev *dev, struct vhost_virtqueue *vq)if (vq->avail_idx != vq->last_avail_idx)return false; - r =vhost_get_avail (vq, avail_idx, &vq->avail->idx); + r =vhost_get_avail_idx (vq, &avail_idx);if (unlikely (r))return false; vq->avail_idx =vhost16_to_cpu (vq, avail_idx);
@@ -2336,7 +2396,7 @@ bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)/* They could have slipped one in as we were doing that: make * sure it's written, then check again. */ smp_mb (); - r =vhost_get_avail (vq, avail_idx, &vq->avail->idx); + r =vhost_get_avail_idx (vq, &avail_idx);if (r) {vq_err (vq,"Failed to check avail idx at %p: %d\n" , &vq->avail->idx, r);
Signature · 1 line
2.17.1
PATCH 3/3 vhost: access vq metadata through kernel virtual address
In reply to Jason WangIt was noticed that the copy_user() friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.
This patch tries to eliminate those overhead by pin vq metadata pages and access them through vmap(). During SET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.
Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user + vhost_net + xdp1 on TAP (CONFIG_HARDENED_USERCOPY is not enabled):
Before: ~5.0Mpps After: ~6.1Mpps
--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)
drivers/vhost/vhost.c +178 -0
@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)
@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ; + + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; + + vaddr =vmap (pages, npages,VM_MAP ,PAGE_KERNEL ); +if (!vaddr) + goto err; + + map->pages = pages; + map->addr = vaddr + (uaddr & (PAGE_SIZE -1 )); + map->npages = npages; + +return 0 ; + +err: +if (npinned >0 ) +release_pages (pages, npinned); +kfree (pages); +return -EFAULT ; +} + +static void vhost_uninit_vmap (struct vhost_vmap *map) +{ +if (!map->addr) +return ; + +vunmap (map->addr); +release_pages (map->pages, map->npages); +kfree (map->pages); + + map->addr =NULL ; + map->pages =NULL ; + map->npages =0 ; +} + +static void vhost_clean_vmaps (struct vhost_virtqueue *vq) +{ +vhost_uninit_vmap (&vq->avail_ring); +vhost_uninit_vmap (&vq->desc_ring); +vhost_uninit_vmap (&vq->used_ring); +} + +static int vhost_setup_vmaps (struct vhost_virtqueue *vq,unsigned long avail, +unsigned long desc,unsigned long used) +{ +size_t event =vhost_has_feature (vq,VIRTIO_RING_F_EVENT_IDX ) ?2 :0 ; +size_t avail_size, desc_size, used_size; +int ret; + +vhost_clean_vmaps (vq); + + avail_size =sizeof (*vq->avail) + +sizeof (*vq->avail->ring) * vq->num + event; + ret =vhost_init_vmap (&vq->avail_ring, avail, avail_size, false); +if (ret) { +vq_err (vq,"Fail to setup vmap for avail ring!\n" ); + goto err_avail; + } + + desc_size =sizeof (*vq->desc) * vq->num; + ret =vhost_init_vmap (&vq->desc_ring, desc, desc_size, false); +if (ret) { +vq_err (vq,"Fail to setup vmap for desc ring!\n" ); + goto err_desc; + } + + used_size =sizeof (*vq->used) + +sizeof (*vq->used->ring) * vq->num + event; + ret =vhost_init_vmap (&vq->used_ring, used, used_size, true); +if (ret) { +vq_err (vq,"Fail to setup vmap for used ring!\n" ); + goto err_used; + } + +return 0 ; + +err_used: +vhost_uninit_vmap (&vq->used_ring); +err_desc: +vhost_uninit_vmap (&vq->avail_ring); +err_avail: +return -EFAULT ; +} +void vhost_dev_cleanup (struct vhost_dev *dev) {int i;
@@ -626,6 +725,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev)if (dev->vqs[i]->call_ctx)eventfd_ctx_put (dev->vqs[i]->call_ctx);vhost_vq_reset (dev, dev->vqs[i]); +vhost_clean_vmaps (dev->vqs[i]); }vhost_dev_free_iovecs (dev);if (dev->log_ctx)
@@ -873,6 +973,14 @@ static inline void __user *__vhost_get_user(struct vhost_virtqueue *vq,static inline int vhost_put_avail_event (struct vhost_virtqueue *vq) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + *((__virtio16 *)&used->ring[vq->num]) = +cpu_to_vhost16 (vq, vq->avail_idx); +return 0 ; + } +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->avail_idx),vhost_avail_event (vq)); }
@@ -881,6 +989,13 @@ static inline int vhost_put_used(struct vhost_virtqueue *vq, struct vring_used_elem *head, int idx, int count) { + if (!vq->iotlb) { + struct vring_used *used = vq->used_ring.addr; + +memcpy (used->ring + idx, head, count *sizeof (*head)); +return 0 ; + } +return vhost_copy_to_user (vq, vq->used->ring + idx, head, count *sizeof (*head)); }
@@ -888,6 +1003,13 @@ static inline int vhost_put_used(struct vhost_virtqueue *vq,static inline int vhost_put_used_flags (struct vhost_virtqueue *vq) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + used->flags =cpu_to_vhost16 (vq, vq->used_flags); +return 0 ; + } +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->used_flags), &vq->used->flags); }
@@ -895,6 +1017,13 @@ static inline int vhost_put_used_flags(struct vhost_virtqueue *vq)static inline int vhost_put_used_idx (struct vhost_virtqueue *vq) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + used->idx =cpu_to_vhost16 (vq, vq->last_used_idx); +return 0 ; + } +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->last_used_idx), &vq->used->idx); }
@@ -926,12 +1055,26 @@ static inline int vhost_put_used_idx(struct vhost_virtqueue *vq)static inline int vhost_get_avail_idx (struct vhost_virtqueue *vq,__virtio16 *idx) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *idx = avail->idx; +return 0 ; + } +return vhost_get_avail (vq, *idx, &vq->avail->idx); }static inline int vhost_get_avail_head (struct vhost_virtqueue *vq,__virtio16 *head,int idx) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *head = avail->ring[idx & (vq->num -1 )]; +return 0 ; + } +return vhost_get_avail (vq, *head, &vq->avail->ring[idx & (vq->num -1 )]); }
@@ -939,24 +1082,52 @@ static inline int vhost_get_avail_head(struct vhost_virtqueue *vq,static inline int vhost_get_avail_flags (struct vhost_virtqueue *vq,__virtio16 *flags) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *flags = avail->flags; +return 0 ; + } +return vhost_get_avail (vq, *flags, &vq->avail->flags); }static inline int vhost_get_used_event (struct vhost_virtqueue *vq,__virtio16 *event) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *event = (__virtio16 )avail->ring[vq->num]; +return 0 ; + } +return vhost_get_avail (vq, *event,vhost_used_event (vq)); }static inline int vhost_get_used_idx (struct vhost_virtqueue *vq,__virtio16 *idx) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + *idx = used->idx; +return 0 ; + } +return vhost_get_used (vq, *idx, &vq->used->idx); }static inline int vhost_get_desc (struct vhost_virtqueue *vq,struct vring_desc *desc,int idx) { +if (!vq->iotlb) { +struct vring_desc *d = vq->desc_ring.addr; + + *desc = *(d + idx); +return 0 ; + } +return vhost_copy_from_user (vq, desc, vq->desc + idx,sizeof (*desc)); }
@@ -1551,6 +1722,13 @@ long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *arg } } +if (!vq->iotlb &&vhost_setup_vmaps (vq, a.avail_user_addr, + a.desc_user_addr, + a.used_user_addr)) { + r = -EINVAL ; +break ; + } + vq->log_used = !!(a.flags & (0x1 <<VHOST_VRING_F_LOG )); vq->desc = (void __user *)(unsigned long )a.desc_user_addr; vq->avail = (void __user *)(unsigned long )a.avail_user_addr;
drivers/vhost/vhost.h +11 -0
@@ -80,6 +80,12 @@ enum vhost_uaddr_type { VHOST_NUM_ADDRS = 3, }; +struct vhost_vmap { +struct page **pages; +void *addr; +int npages; +}; +/* The virtqueue structure describes a queue attached to a device. */ struct vhost_virtqueue {struct vhost_dev *dev;
@@ -90,6 +96,11 @@ struct vhost_virtqueue {struct vring_desc __user *desc;struct vring_avail __user *avail;struct vring_used __user *used; + +struct vhost_vmap avail_ring; +struct vhost_vmap desc_ring; +struct vhost_vmap used_ring; +const struct vhost_umem_node *meta_iotlb[VHOST_NUM_ADDRS ];struct file *kick;struct eventfd_ctx *call_ctx;
Signature · 1 line
2.17.1
Michael S. Tsirkin
maintainerRe: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
Quoted 50 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang <[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +9
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned;
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 635
Quoted 10 lines
drivers/vhost/vhost.c +10
-0+void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ; + + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +
As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.
So no THP, no NUMA rebalancing, userspace-controlled amount of memory locked up and not accounted for.
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
Quoted 273 lines
drivers/vhost/vhost.c +159
-0+ vaddr =vmap (pages, npages,VM_MAP ,PAGE_KERNEL ); +if (!vaddr) + goto err; + + map->pages = pages; + map->addr = vaddr + (uaddr & (PAGE_SIZE -1 )); + map->npages = npages; + +return 0 ; + +err: +if (npinned >0 ) +release_pages (pages, npinned); +kfree (pages); +return -EFAULT ; +} + +static void vhost_uninit_vmap (struct vhost_vmap *map) +{ +if (!map->addr) +return ; + +vunmap (map->addr); +release_pages (map->pages, map->npages); +kfree (map->pages); + + map->addr =NULL ; + map->pages =NULL ; + map->npages =0 ; +} + +static void vhost_clean_vmaps (struct vhost_virtqueue *vq) +{ +vhost_uninit_vmap (&vq->avail_ring); +vhost_uninit_vmap (&vq->desc_ring); +vhost_uninit_vmap (&vq->used_ring); +} + +static int vhost_setup_vmaps (struct vhost_virtqueue *vq,unsigned long avail, +unsigned long desc,unsigned long used) +{ +size_t event =vhost_has_feature (vq,VIRTIO_RING_F_EVENT_IDX ) ?2 :0 ; +size_t avail_size, desc_size, used_size; +int ret; + +vhost_clean_vmaps (vq); + + avail_size =sizeof (*vq->avail) + +sizeof (*vq->avail->ring) * vq->num + event; + ret =vhost_init_vmap (&vq->avail_ring, avail, avail_size, false); +if (ret) { +vq_err (vq,"Fail to setup vmap for avail ring!\n" ); + goto err_avail; + } + + desc_size =sizeof (*vq->desc) * vq->num; + ret =vhost_init_vmap (&vq->desc_ring, desc, desc_size, false); +if (ret) { +vq_err (vq,"Fail to setup vmap for desc ring!\n" ); + goto err_desc; + } + + used_size =sizeof (*vq->used) + +sizeof (*vq->used->ring) * vq->num + event; + ret =vhost_init_vmap (&vq->used_ring, used, used_size, true); +if (ret) { +vq_err (vq,"Fail to setup vmap for used ring!\n" ); + goto err_used; + } + +return 0 ; + +err_used: +vhost_uninit_vmap (&vq->used_ring); +err_desc: +vhost_uninit_vmap (&vq->avail_ring); +err_avail: +return -EFAULT ; +} +void vhost_dev_cleanup (struct vhost_dev *dev) {int i;@@ -626,6 +725,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev)if (dev->vqs[i]->call_ctx)eventfd_ctx_put (dev->vqs[i]->call_ctx);vhost_vq_reset (dev, dev->vqs[i]); +vhost_clean_vmaps (dev->vqs[i]); }vhost_dev_free_iovecs (dev);if (dev->log_ctx)@@ -873,6 +973,14 @@ static inline void __user *__vhost_get_user(struct vhost_virtqueue *vq,static inline int vhost_put_avail_event (struct vhost_virtqueue *vq) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + *((__virtio16 *)&used->ring[vq->num]) = +cpu_to_vhost16 (vq, vq->avail_idx); +return 0 ; + } +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->avail_idx),vhost_avail_event (vq)); }@@ -881,6 +989,13 @@ static inline int vhost_put_used(struct vhost_virtqueue *vq, struct vring_used_elem *head, int idx, int count) { + if (!vq->iotlb) { + struct vring_used *used = vq->used_ring.addr; + +memcpy (used->ring + idx, head, count *sizeof (*head)); +return 0 ; + } +return vhost_copy_to_user (vq, vq->used->ring + idx, head, count *sizeof (*head)); }@@ -888,6 +1003,13 @@ static inline int vhost_put_used(struct vhost_virtqueue *vq,static inline int vhost_put_used_flags (struct vhost_virtqueue *vq) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + used->flags =cpu_to_vhost16 (vq, vq->used_flags); +return 0 ; + } +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->used_flags), &vq->used->flags); }@@ -895,6 +1017,13 @@ static inline int vhost_put_used_flags(struct vhost_virtqueue *vq)static inline int vhost_put_used_idx (struct vhost_virtqueue *vq) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + used->idx =cpu_to_vhost16 (vq, vq->last_used_idx); +return 0 ; + } +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->last_used_idx), &vq->used->idx); }@@ -926,12 +1055,26 @@ static inline int vhost_put_used_idx(struct vhost_virtqueue *vq)static inline int vhost_get_avail_idx (struct vhost_virtqueue *vq,__virtio16 *idx) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *idx = avail->idx; +return 0 ; + } +return vhost_get_avail (vq, *idx, &vq->avail->idx); }static inline int vhost_get_avail_head (struct vhost_virtqueue *vq,__virtio16 *head,int idx) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *head = avail->ring[idx & (vq->num -1 )]; +return 0 ; + } +return vhost_get_avail (vq, *head, &vq->avail->ring[idx & (vq->num -1 )]); }@@ -939,24 +1082,52 @@ static inline int vhost_get_avail_head(struct vhost_virtqueue *vq,static inline int vhost_get_avail_flags (struct vhost_virtqueue *vq,__virtio16 *flags) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *flags = avail->flags; +return 0 ; + } +return vhost_get_avail (vq, *flags, &vq->avail->flags); }static inline int vhost_get_used_event (struct vhost_virtqueue *vq,__virtio16 *event) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *event = (__virtio16 )avail->ring[vq->num]; +return 0 ; + } +return vhost_get_avail (vq, *event,vhost_used_event (vq)); }static inline int vhost_get_used_idx (struct vhost_virtqueue *vq,__virtio16 *idx) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + *idx = used->idx; +return 0 ; + } +return vhost_get_used (vq, *idx, &vq->used->idx); }static inline int vhost_get_desc (struct vhost_virtqueue *vq,struct vring_desc *desc,int idx) { +if (!vq->iotlb) { +struct vring_desc *d = vq->desc_ring.addr; + + *desc = *(d + idx); +return 0 ; + } +return vhost_copy_from_user (vq, desc, vq->desc + idx,sizeof (*desc)); }@@ -1551,6 +1722,13 @@ long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *arg } } +if (!vq->iotlb &&vhost_setup_vmaps (vq, a.avail_user_addr, + a.desc_user_addr, + a.used_user_addr)) { + r = -EINVAL ; +break ; + } + vq->log_used = !!(a.flags & (0x1 <<VHOST_VRING_F_LOG )); vq->desc = (void __user *)(unsigned long )a.desc_user_addr; vq->avail = (void __user *)(unsigned long )a.avail_user_addr;drivers/vhost/vhost.h +11
-0@@ -80,6 +80,12 @@ enum vhost_uaddr_type { VHOST_NUM_ADDRS = 3, }; +struct vhost_vmap { +struct page **pages; +void *addr; +int npages; +}; +/* The virtqueue structure describes a queue attached to a device. */ struct vhost_virtqueue {struct vhost_dev *dev;@@ -90,6 +96,11 @@ struct vhost_virtqueue {struct vring_desc __user *desc;struct vring_avail __user *avail;struct vring_used __user *used; + +struct vhost_vmap avail_ring; +struct vhost_vmap desc_ring; +struct vhost_vmap used_ring; +const struct vhost_umem_node *meta_iotlb[VHOST_NUM_ADDRS ];struct file *kick;struct eventfd_ctx *call_ctx;Signature · 1 line
2.17.1
Re: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
.giant snip..
Quoted 11 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 635
Quoted 4 lines
drivers/vhost/vhost.c +4
-0+ npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.
So no THP, no NUMA rebalancing, userspace-controlled amount of memory locked up and not accounted for.
Quoted 2 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
So .. suggestions on how this could be accepted? As in other ways where we still get vmap and the issues you mentioned are not troubling you?
Thanks!
Michael S. Tsirkin
maintainerRe: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
Quoted 12 lines · Konrad Rzeszutek Wilk
.giant snip..
Quoted 11 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 635
Quoted 4 lines
drivers/vhost/vhost.c +4
-0+ npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.
So no THP, no NUMA rebalancing, userspace-controlled amount of memory locked up and not accounted for.
Quoted 7 lines
Quoted 2 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
So .. suggestions on how this could be accepted? As in other ways where we still get vmap and the issues you mentioned are not troubling you?
Thanks!
I'd suggest leave vmap alone and find ways to speed up accesses that can fault.
Signature · 1 line
MST
Michael S. Tsirkin
maintainerRe: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
In reply to Konrad Rzeszutek WilkQuoted 12 lines · Konrad Rzeszutek Wilk
.giant snip..
Quoted 11 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 635
Quoted 4 lines
drivers/vhost/vhost.c +4
-0+ npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.
So no THP, no NUMA rebalancing, userspace-controlled amount of memory locked up and not accounted for.
Quoted 7 lines
Quoted 2 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
So .. suggestions on how this could be accepted? As in other ways where we still get vmap and the issues you mentioned are not troubling you?
Thanks!
I'd suggest leave vmap alone and find ways to speed up accesses that can fault.
Signature · 1 line
MST
Re: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
In reply to Michael S. Tsirkin.giant snip..
Quoted 11 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 635
Quoted 4 lines
drivers/vhost/vhost.c +4
-0+ npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.
So no THP, no NUMA rebalancing, userspace-controlled amount of memory locked up and not accounted for.
Quoted 2 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
So .. suggestions on how this could be accepted? As in other ways where we still get vmap and the issues you mentioned are not troubling you?
Thanks!
Re: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
In reply to Michael S. TsirkinQuoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +15
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ; +
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 635
Quoted 4 lines
drivers/vhost/vhost.c +4
-0+ npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.
So no THP, no NUMA rebalancing,
This is the price of all GUP users not only vhost itself. What's more important, the goal is not to be left too much behind for other backends like DPDK or AF_XDP (all of which are using GUP).
Quoted 2 lines
userspace-controlled
amount of memory locked up and not accounted for.
It's pretty easy to add this since the slow path was still kept. If we exceeds the limitation, we can switch back to slow path.
Quoted 3 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
Again, this is only for metadata accessing not the data which has been used for years for real use cases.
For SMAP, it makes senses for the address that kernel can not forcast. But it's not the case for the vhost metadata since we know the address will be accessed very frequently. For speculation barrier, it helps nothing for the data path of vhost which is a kthread. Packet or AF_XDP benefit from accessing metadata directly, we should do it as well.
Thanks
Michael S. Tsirkin
maintainerRe: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
Quoted 68 lines · Jason Wang
Quoted 56 lines · Michael S. Tsirkin
Quoted 55 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +15
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ; +Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 635
Quoted 4 lines
drivers/vhost/vhost.c +4
-0+ npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.
So no THP, no NUMA rebalancing,
Quoted 1 line
This is the price of all GUP users not only vhost itself.
Yes. GUP is just not a great interface for vhost to use.
Quoted 3 lines
What's more
important, the goal is not to be left too much behind for other backends like DPDK orAF_XDP(all of which are using GUP).
So these guys assume userspace knows what it's doing. We can't assume that.
Quoted 13 lines
Quoted 3 lines
userspace-controlled
amount of memory locked up and not accounted for.It's pretty easy to add this since the slow path was still kept. If we exceeds the limitation, we can switch back to slow path.
Quoted 3 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
Quoted 7 lines
Again, this is only for metadata accessing not the data which has been used for years for real use cases.
For SMAP, it makes senses for the address that kernel can not forcast. But it's not the case for the vhost metadata since we know the address will be accessed very frequently. For speculation barrier, it helps nothing for the data path of vhost which is a kthread.
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
Quoted 4 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
Re: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
Quoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
Quoted 55 lines · Michael S. Tsirkin
Quoted 54 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +14
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ;
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 635
Quoted 5 lines
drivers/vhost/vhost.c +5
-0+ + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.
The pages wil be released during set features.
Quoted 1 line
Quoted 1 line
Quoted 1 line
So no THP, no NUMA rebalancing,
For THP, we will probably miss 2 or 4 pages, but does this really matter consider the gain we have? For NUMA rebalancing, I'm even not quite sure if it can helps for the case of IPC (vhost). It looks to me the worst case it may cause page to be thrash between nodes if vhost and userspace are running in two nodes.
Quoted 3 lines
Quoted 2 lines
This is the price of all GUP users not only vhost itself.
Yes. GUP is just not a great interface for vhost to use.
Zerocopy codes (enabled by defualt) use them for years.
Quoted 7 lines
Quoted 4 lines
What's more
important, the goal is not to be left too much behind for other backends like DPDK orAF_XDP(all of which are using GUP).So these guys assume userspace knows what it's doing. We can't assume that.
What kind of assumption do you they have?
Quoted 13 lines
Quoted 13 lines
Quoted 3 lines
userspace-controlled
amount of memory locked up and not accounted for.It's pretty easy to add this since the slow path was still kept. If we exceeds the limitation, we can switch back to slow path.
Quoted 2 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
Again, this is only for metadata accessing not the data which has been used for years for real use cases.
Quoted 6 lines
Quoted 4 lines
For SMAP, it makes senses for the address that kernel can not forcast. But it's not the case for the vhost metadata since we know the address will be accessed very frequently. For speculation barrier, it helps nothing for the data path of vhost which is a kthread.
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
The problem is not kthread but the address of userspace address. The addresses of vq metadata tends to be consistent for a while, and vhost knows they will be frequently. SMAP doesn't help too much in this case.
Thanks.
Quoted 5 lines
Quoted 5 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
Michael S. Tsirkin
maintainerRe: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
Quoted 69 lines · Jason Wang
Quoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
Quoted 55 lines · Michael S. Tsirkin
Quoted 54 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +14
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ;Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 635
Quoted 5 lines
drivers/vhost/vhost.c +5
-0+ + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.
Quoted 8 lines
The pages wil be released during set features.
Quoted 1 line
Quoted 1 line
Quoted 1 line
So no THP, no NUMA rebalancing,
For THP, we will probably miss 2 or 4 pages, but does this really matter consider the gain we have?
We as in vhost? networking isn't the only thing guest does. We don't even know if this guest does a lot of networking. You don't
know what else is in this huge page. Can be something very important that guest touches all the time.
Quoted 4 lines
For NUMA rebalancing, I'm even not quite sure if
it can helps for the case of IPC (vhost). It looks to me the worst case it may cause page to be thrash between nodes if vhost and userspace are running in two nodes.
So again it's a gain for vhost but has a completely unpredictable effect on other functionality of the guest.
That's what bothers me with this approach.
Quoted 7 lines
Quoted 4 lines
Quoted 3 lines
This is the price of all GUP users not only vhost itself.
Yes. GUP is just not a great interface for vhost to use.
Zerocopy codes (enabled by defualt) use them for years.
But only for TX and temporarily. We pin, read, unpin.
Your patch is different
- it writes into memory and GUP has known issues with file backed memory
- it keeps pages pinned forever
Quoted 34 lines
Quoted 8 lines
Quoted 5 lines
What's more
important, the goal is not to be left too much behind for other backends like DPDK orAF_XDP(all of which are using GUP).So these guys assume userspace knows what it's doing. We can't assume that.
What kind of assumption do you they have?
Quoted 13 lines
Quoted 13 lines
Quoted 3 lines
userspace-controlled
amount of memory locked up and not accounted for.It's pretty easy to add this since the slow path was still kept. If we exceeds the limitation, we can switch back to slow path.
Quoted 2 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
Again, this is only for metadata accessing not the data which has been used for years for real use cases.
Quoted 6 lines
Quoted 4 lines
For SMAP, it makes senses for the address that kernel can not forcast. But it's not the case for the vhost metadata since we know the address will be accessed very frequently. For speculation barrier, it helps nothing for the data path of vhost which is a kthread.
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
Quoted 5 lines
The problem is not kthread but the address of userspace address. The addresses of vq metadata tends to be consistent for a while, and vhost knows they will be frequently. SMAP doesn't help too much in this case.
Thanks.
It's true for a real life applications but a malicious one can call the setup ioctls any number of times. And SMAP is all about malcious applications.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
Re: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
Quoted 73 lines · Michael S. Tsirkin
Quoted 72 lines · Jason Wang
Quoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
Quoted 55 lines · Michael S. Tsirkin
Quoted 54 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +14
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ;Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 635
Quoted 5 lines
drivers/vhost/vhost.c +5
-0+ + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.The pages wil be released during set features.
Quoted 1 line
Quoted 1 line
Quoted 1 line
So no THP, no NUMA rebalancing,
Quoted 7 lines
Quoted 2 lines
For THP, we will probably miss 2 or 4 pages, but does this really matter consider the gain we have?
We as in vhost? networking isn't the only thing guest does. We don't even know if this guest does a lot of networking. You don't
know what else is in this huge page. Can be something very important that guest touches all the time.
Well, the probability should be very small consider we usually give several gigabytes to guest. The rest of the pages that doesn't sit in the same hugepage with metadata can still be merged by THP. Anyway, I can test the differences.
Quoted 10 lines
Quoted 5 lines
For NUMA rebalancing, I'm even not quite sure if
it can helps for the case of IPC (vhost). It looks to me the worst case it may cause page to be thrash between nodes if vhost and userspace are running in two nodes.So again it's a gain for vhost but has a completely unpredictable effect on other functionality of the guest.
That's what bothers me with this approach.
So:
- The rest of the pages could still be balanced to other nodes, no?
- try to balance metadata pages (belongs to co-operate processes) itself is still questionable
Quoted 9 lines
Quoted 8 lines
Quoted 6 lines
Quoted 5 lines
This is the price of all GUP users not only vhost itself.
Yes. GUP is just not a great interface for vhost to use.
Zerocopy codes (enabled by defualt) use them for years.
But only for TX and temporarily. We pin, read, unpin.
Probably not. For several reasons that the page will be not be released soon or held for a very long period of time or even forever.
Quoted 5 lines
Your patch is different
- it writes into memory and GUP has known issues with file backed memory
The ordinary user for vhost is anonymous pages I think?
Quoted 30 lines
- it keeps pages pinned forever
Quoted 26 lines
Quoted 5 lines
Quoted 3 lines
What's more
important, the goal is not to be left too much behind for other backends like DPDK orAF_XDP(all of which are using GUP).So these guys assume userspace knows what it's doing. We can't assume that.
What kind of assumption do you they have?
Quoted 16 lines
Quoted 7 lines
Quoted 2 lines
userspace-controlled
amount of memory locked up and not accounted for.It's pretty easy to add this since the slow path was still kept. If we exceeds the limitation, we can switch back to slow path.
Quoted 2 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
Quoted 7 lines
Again, this is only for metadata accessing not the data which has been used for years for real use cases.
For SMAP, it makes senses for the address that kernel can not forcast. But it's not the case for the vhost metadata since we know the address will be accessed very frequently. For speculation barrier, it helps nothing for the data path of vhost which is a kthread.
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
Quoted 8 lines
Quoted 5 lines
The problem is not kthread but the address of userspace address. The addresses of vq metadata tends to be consistent for a while, and vhost knows they will be frequently. SMAP doesn't help too much in this case.
Thanks.
It's true for a real life applications but a malicious one can call the setup ioctls any number of times. And SMAP is all about malcious applications.
We don't do this in the path of ioctl, there's no context switch between userspace and kernel in the worker thread. SMAP is used to prevent kernel from accessing userspace pages unexpectedly which is not the case for metadata access.
Thanks
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Michael S. Tsirkin
maintainerRe: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
Quoted 84 lines · Jason Wang
Quoted 73 lines · Michael S. Tsirkin
Quoted 72 lines · Jason Wang
Quoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
Quoted 55 lines · Michael S. Tsirkin
Quoted 54 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +14
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ;Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 634
Quoted 5 lines
drivers/vhost/vhost.c +5
-0+ + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.The pages wil be released during set features.
Quoted 1 line
Quoted 1 line
Quoted 1 line
So no THP, no NUMA rebalancing,
Quoted 7 lines
Quoted 2 lines
For THP, we will probably miss 2 or 4 pages, but does this really matter consider the gain we have?
We as in vhost? networking isn't the only thing guest does. We don't even know if this guest does a lot of networking. You don't
know what else is in this huge page. Can be something very important that guest touches all the time.
Quoted 4 lines
Well, the probability should be very small consider we usually give several gigabytes to guest. The rest of the pages that doesn't sit in the same hugepage with metadata can still be merged by THP. Anyway, I can test the differences.
Thanks!
Quoted 13 lines
Quoted 11 lines
Quoted 6 lines
For NUMA rebalancing, I'm even not quite sure if
it can helps for the case of IPC (vhost). It looks to me the worst case it may cause page to be thrash between nodes if vhost and userspace are running in two nodes.So again it's a gain for vhost but has a completely unpredictable effect on other functionality of the guest.
That's what bothers me with this approach.
Quoted 6 lines
So:
- The rest of the pages could still be balanced to other nodes, no?
- try to balance metadata pages (belongs to co-operate processes) itself is still questionable
I am not sure why. It should be easy enough to force the VCPU and vhost to move (e.g. start them pinned to 1 cpu, then pin them to another one). Clearly sometimes this would be necessary for load balancing reasons. With autonuma after a while (could take seconds but it will happen) the memory will migrate.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
This is the price of all GUP users not only vhost itself.
Quoted 8 lines
Quoted 4 lines
Quoted 3 lines
Quoted 1 line
Yes. GUP is just not a great interface for vhost to use.
Zerocopy codes (enabled by defualt) use them for years.
But only for TX and temporarily. We pin, read, unpin.
Probably not. For several reasons that the page will be not be released soon or held for a very long period of time or even forever.
With zero copy? Well it's pinned until transmit. Takes a while but could be enough for autocopy to work esp since its the packet memory so not reused immediately.
Quoted 9 lines
Quoted 6 lines
Your patch is different
- it writes into memory and GUP has known issues with file backed memory
The ordinary user for vhost is anonymous pages I think?
It's not the most common scenario and not the fastest one (e.g. THP does not work) but file backed is useful sometimes. It would not be nice at all to corrupt guest memory in that case.
Quoted 41 lines
Quoted 31 lines
- it keeps pages pinned forever
Quoted 26 lines
Quoted 5 lines
Quoted 3 lines
What's more
important, the goal is not to be left too much behind for other backends like DPDK orAF_XDP(all of which are using GUP).So these guys assume userspace knows what it's doing. We can't assume that.
What kind of assumption do you they have?
Quoted 16 lines
Quoted 7 lines
Quoted 2 lines
userspace-controlled
amount of memory locked up and not accounted for.It's pretty easy to add this since the slow path was still kept. If we exceeds the limitation, we can switch back to slow path.
Quoted 2 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
Quoted 7 lines
Again, this is only for metadata accessing not the data which has been used for years for real use cases.
For SMAP, it makes senses for the address that kernel can not forcast. But it's not the case for the vhost metadata since we know the address will be accessed very frequently. For speculation barrier, it helps nothing for the data path of vhost which is a kthread.
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
Quoted 8 lines
Quoted 5 lines
The problem is not kthread but the address of userspace address. The addresses of vq metadata tends to be consistent for a while, and vhost knows they will be frequently. SMAP doesn't help too much in this case.
Thanks.
It's true for a real life applications but a malicious one can call the setup ioctls any number of times. And SMAP is all about malcious applications.
Quoted 6 lines
We don't do this in the path of ioctl, there's no context switch between userspace and kernel in the worker thread. SMAP is used to prevent kernel from accessing userspace pages unexpectedly which is not the case for metadata access.
Thanks
OK let's forget smap for now.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
Quoted 98 lines · Michael S. Tsirkin
Quoted 80 lines · Jason Wang
Quoted 70 lines · Michael S. Tsirkin
Quoted 69 lines · Jason Wang
Quoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
Quoted 55 lines · Michael S. Tsirkin
Quoted 54 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +14
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ;Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 634
Quoted 5 lines
drivers/vhost/vhost.c +5
-0+ + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.The pages wil be released during set features.
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
So no THP, no NUMA rebalancing,
For THP, we will probably miss 2 or 4 pages, but does this really matter consider the gain we have?
We as in vhost? networking isn't the only thing guest does. We don't even know if this guest does a lot of networking. You don't
know what else is in this huge page. Can be something very important that guest touches all the time.Quoted 4 lines
Well, the probability should be very small consider we usually give several gigabytes to guest. The rest of the pages that doesn't sit in the same hugepage with metadata can still be merged by THP. Anyway, I can test the differences.
Thanks!
Quoted 11 lines
Quoted 8 lines
Quoted 4 lines
For NUMA rebalancing, I'm even not quite sure if
it can helps for the case of IPC (vhost). It looks to me the worst case it may cause page to be thrash between nodes if vhost and userspace are running in two nodes.So again it's a gain for vhost but has a completely unpredictable effect on other functionality of the guest.
That's what bothers me with this approach.
So:
Quoted 7 lines
Quoted 4 lines
- The rest of the pages could still be balanced to other nodes, no?
- try to balance metadata pages (belongs to co-operate processes) itself is still questionable
I am not sure why. It should be easy enough to force the VCPU and vhost to move (e.g. start them pinned to 1 cpu, then pin them to another one). Clearly sometimes this would be necessary for load balancing reasons.
Yes, but it looks to me the part of motivation of auto NUMA is to avoid manual pinning.
Quoted 3 lines
With autonuma after a while (could take seconds but it will happen) the memory will migrate.
Yes. As you mentioned during the discuss, I wonder we could do it similarly through mmu notifier like APIC access page in commit c24ae0dcd3e ("kvm: x86: Unpin and remove kvm_arch->apic_access_page")
Quoted 19 lines
Quoted 5 lines
Quoted 5 lines
Quoted 7 lines
Quoted 4 lines
Quoted 3 lines
Quoted 2 lines
Quoted 1 line
This is the price of all GUP users not only vhost itself.
Yes. GUP is just not a great interface for vhost to use.
Zerocopy codes (enabled by defualt) use them for years.
But only for TX and temporarily. We pin, read, unpin.
Probably not. For several reasons that the page will be not be released soon or held for a very long period of time or even forever.
With zero copy? Well it's pinned until transmit. Takes a while but could be enough for autocopy to work esp since its the packet memory so not reused immediately.
Quoted 2 lines
Quoted 2 lines
Your patch is different
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
- it writes into memory and GUP has known issues with file backed memory
The ordinary user for vhost is anonymous pages I think?
It's not the most common scenario and not the fastest one (e.g. THP does not work) but file backed is useful sometimes. It would not be nice at all to corrupt guest memory in that case.
Ok.
Quoted 38 lines
Quoted 38 lines
Quoted 37 lines
- it keeps pages pinned forever
Quoted 22 lines
Quoted 5 lines
Quoted 3 lines
What's more
important, the goal is not to be left too much behind for other backends like DPDK orAF_XDP(all of which are using GUP).So these guys assume userspace knows what it's doing. We can't assume that.
What kind of assumption do you they have?
Quoted 14 lines
Quoted 14 lines
Quoted 2 lines
userspace-controlled
amount of memory locked up and not accounted for.It's pretty easy to add this since the slow path was still kept. If we exceeds the limitation, we can switch back to slow path.
Quoted 2 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
Again, this is only for metadata accessing not the data which has been used for years for real use cases.
For SMAP, it makes senses for the address that kernel can not forcast. But it's not the case for the vhost metadata since we know the address will be accessed very frequently. For speculation barrier, it helps nothing for the data path of vhost which is a kthread.
Quoted 7 lines
Quoted 2 lines
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
The problem is not kthread but the address of userspace address. The addresses of vq metadata tends to be consistent for a while, and vhost knows they will be frequently. SMAP doesn't help too much in this case.
Thanks.
It's true for a real life applications but a malicious one can call the setup ioctls any number of times. And SMAP is all about malcious applications.
Quoted 7 lines
Quoted 6 lines
We don't do this in the path of ioctl, there's no context switch between userspace and kernel in the worker thread. SMAP is used to prevent kernel from accessing userspace pages unexpectedly which is not the case for metadata access.
Thanks
OK let's forget smap for now.
Some numbers I measured:
On an old Sandy bridge machine without SMAP support. Remove speculation barrier boost the performance from 4.6Mpps to 5.1Mpps
On a newer Broadwell machine with SMAP support. Remove speculation barrier only gives 2%-5% improvement, disable SMAP completely through Kconfig boost 57% performance from 4.8Mpps to 7.5Mpps. (Vmap gives 6Mpps - 6.1Mpps, it only bypass SMAP for metadata).
So it looks like for recent machine, SMAP becomes pain point when the copy is short (e.g 64B) for high PPS.
Thanks
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
Michael S. Tsirkin
maintainerRe: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
Quoted 104 lines · Jason Wang
Quoted 102 lines · Michael S. Tsirkin
Quoted 80 lines · Jason Wang
Quoted 70 lines · Michael S. Tsirkin
Quoted 69 lines · Jason Wang
Quoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
Quoted 55 lines · Michael S. Tsirkin
Quoted 54 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +14
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ;Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 634
Quoted 5 lines
drivers/vhost/vhost.c +5
-0+ + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.The pages wil be released during set features.
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
So no THP, no NUMA rebalancing,
For THP, we will probably miss 2 or 4 pages, but does this really matter consider the gain we have?
We as in vhost? networking isn't the only thing guest does. We don't even know if this guest does a lot of networking. You don't
know what else is in this huge page. Can be something very important that guest touches all the time.Quoted 4 lines
Well, the probability should be very small consider we usually give several gigabytes to guest. The rest of the pages that doesn't sit in the same hugepage with metadata can still be merged by THP. Anyway, I can test the differences.
Thanks!
Quoted 15 lines
Quoted 8 lines
Quoted 4 lines
For NUMA rebalancing, I'm even not quite sure if
it can helps for the case of IPC (vhost). It looks to me the worst case it may cause page to be thrash between nodes if vhost and userspace are running in two nodes.So again it's a gain for vhost but has a completely unpredictable effect on other functionality of the guest.
That's what bothers me with this approach.
So:
- The rest of the pages could still be balanced to other nodes, no?
- try to balance metadata pages (belongs to co-operate processes) itself is still questionable
Quoted 7 lines
Quoted 3 lines
I am not sure why. It should be easy enough to force the VCPU and vhost to move (e.g. start them pinned to 1 cpu, then pin them to another one). Clearly sometimes this would be necessary for load balancing reasons.
Yes, but it looks to me the part of motivation of auto NUMA is to avoid manual pinning.
... of memory. Yes.
Quoted 8 lines
Quoted 4 lines
With autonuma after a while (could take seconds but it will happen) the memory will migrate.
Yes. As you mentioned during the discuss, I wonder we could do it similarly through mmu notifier like APIC access page in commit
c24ae0dcd3e("kvm: x86:
Unpin and removekvm_arch->apic_access_page")
That would be a possible approach.
Quoted 90 lines
Quoted 20 lines
Quoted 6 lines
Quoted 6 lines
Quoted 7 lines
Quoted 4 lines
Quoted 3 lines
Quoted 2 lines
Quoted 1 line
This is the price of all GUP users not only vhost itself.
Yes. GUP is just not a great interface for vhost to use.
Zerocopy codes (enabled by defualt) use them for years.
But only for TX and temporarily. We pin, read, unpin.
Probably not. For several reasons that the page will be not be released soon or held for a very long period of time or even forever.
With zero copy? Well it's pinned until transmit. Takes a while but could be enough for autocopy to work esp since its the packet memory so not reused immediately.
Quoted 2 lines
Quoted 2 lines
Your patch is different
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
- it writes into memory and GUP has known issues with file backed memory
The ordinary user for vhost is anonymous pages I think?
It's not the most common scenario and not the fastest one (e.g. THP does not work) but file backed is useful sometimes. It would not be nice at all to corrupt guest memory in that case.
Ok.
Quoted 38 lines
Quoted 38 lines
Quoted 37 lines
- it keeps pages pinned forever
Quoted 22 lines
Quoted 5 lines
Quoted 3 lines
What's more
important, the goal is not to be left too much behind for other backends like DPDK orAF_XDP(all of which are using GUP).So these guys assume userspace knows what it's doing. We can't assume that.
What kind of assumption do you they have?
Quoted 14 lines
Quoted 14 lines
Quoted 2 lines
userspace-controlled
amount of memory locked up and not accounted for.It's pretty easy to add this since the slow path was still kept. If we exceeds the limitation, we can switch back to slow path.
Quoted 2 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
Again, this is only for metadata accessing not the data which has been used for years for real use cases.
For SMAP, it makes senses for the address that kernel can not forcast. But it's not the case for the vhost metadata since we know the address will be accessed very frequently. For speculation barrier, it helps nothing for the data path of vhost which is a kthread.
Quoted 7 lines
Quoted 2 lines
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
The problem is not kthread but the address of userspace address. The addresses of vq metadata tends to be consistent for a while, and vhost knows they will be frequently. SMAP doesn't help too much in this case.
Thanks.
It's true for a real life applications but a malicious one can call the setup ioctls any number of times. And SMAP is all about malcious applications.
Quoted 7 lines
Quoted 6 lines
We don't do this in the path of ioctl, there's no context switch between userspace and kernel in the worker thread. SMAP is used to prevent kernel from accessing userspace pages unexpectedly which is not the case for metadata access.
Thanks
OK let's forget smap for now.
Some numbers I measured:
On an old Sandy bridge machine without SMAP support. Remove speculation barrier boost the performance from 4.6Mpps to 5.1Mpps
On a newer Broadwell machine with SMAP support. Remove speculation barrier only gives 2%-5% improvement, disable SMAP completely through
Kconfigboost 57% performance from 4.8Mpps to 7.5Mpps. (Vmap gives 6Mpps - 6.1Mpps, it only bypass SMAP for metadata).
Quoted 4 lines
So it looks like for recent machine, SMAP becomes pain point when the copy is short (e.g 64B) for high PPS.
Thanks
Thanks a lot for looking into this!
So first of all users can just boot with nosmap, right? What's wrong with that? Yes it's not fine-grained but OTOH it's easy to understand.
And I guess this confirms that if we are going to worry about smap enabled, we need to look into packet copies too, not just meta-data.
Vaguely could see a module option (off by default) where vhost basically does user_access_begin when it starts running, then uses unsafe accesses in vhost and tun and then user_access_end.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
Quoted 111 lines · Michael S. Tsirkin
Quoted 99 lines · Jason Wang
Quoted 98 lines · Michael S. Tsirkin
Quoted 79 lines · Jason Wang
Quoted 70 lines · Michael S. Tsirkin
Quoted 69 lines · Jason Wang
Quoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
Quoted 55 lines · Michael S. Tsirkin
Quoted 54 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +14
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ;Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 634
Quoted 5 lines
drivers/vhost/vhost.c +5
-0+ + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.The pages wil be released during set features.
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
So no THP, no NUMA rebalancing,
For THP, we will probably miss 2 or 4 pages, but does this really matter consider the gain we have?
We as in vhost? networking isn't the only thing guest does. We don't even know if this guest does a lot of networking. You don't
know what else is in this huge page. Can be something very important that guest touches all the time.Quoted 4 lines
Well, the probability should be very small consider we usually give several gigabytes to guest. The rest of the pages that doesn't sit in the same hugepage with metadata can still be merged by THP. Anyway, I can test the differences.
Thanks!
Quoted 12 lines
Quoted 8 lines
Quoted 4 lines
For NUMA rebalancing, I'm even not quite sure if
it can helps for the case of IPC (vhost). It looks to me the worst case it may cause page to be thrash between nodes if vhost and userspace are running in two nodes.So again it's a gain for vhost but has a completely unpredictable effect on other functionality of the guest.
That's what bothers me with this approach.
So:
- The rest of the pages could still be balanced to other nodes, no?
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
- try to balance metadata pages (belongs to co-operate processes) itself is still questionable
I am not sure why. It should be easy enough to force the VCPU and vhost to move (e.g. start them pinned to 1 cpu, then pin them to another one). Clearly sometimes this would be necessary for load balancing reasons.
Yes, but it looks to me the part of motivation of auto NUMA is to avoid manual pinning.
... of memory. Yes.
Quoted 7 lines
Quoted 6 lines
Quoted 3 lines
With autonuma after a while (could take seconds but it will happen) the memory will migrate.
Yes. As you mentioned during the discuss, I wonder we could do it similarly through mmu notifier like APIC access page in commit
c24ae0dcd3e("kvm: x86:
Unpin and removekvm_arch->apic_access_page")That would be a possible approach.
Yes, this looks possible, and the conversion seems not hard. Let me have a try with this.
[...]
Quoted 28 lines
Quoted 28 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 7 lines
Quoted 2 lines
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
The problem is not kthread but the address of userspace address. The addresses of vq metadata tends to be consistent for a while, and vhost knows they will be frequently. SMAP doesn't help too much in this case.
Thanks.
It's true for a real life applications but a malicious one can call the setup ioctls any number of times. And SMAP is all about malcious applications.
Quoted 7 lines
Quoted 6 lines
We don't do this in the path of ioctl, there's no context switch between userspace and kernel in the worker thread. SMAP is used to prevent kernel from accessing userspace pages unexpectedly which is not the case for metadata access.
Thanks
OK let's forget smap for now.
Some numbers I measured:
On an old Sandy bridge machine without SMAP support. Remove speculation barrier boost the performance from 4.6Mpps to 5.1Mpps
On a newer Broadwell machine with SMAP support. Remove speculation barrier only gives 2%-5% improvement, disable SMAP completely through
Kconfigboost 57% performance from 4.8Mpps to 7.5Mpps. (Vmap gives 6Mpps - 6.1Mpps, it only bypass SMAP for metadata).
Quoted 8 lines
Quoted 4 lines
So it looks like for recent machine, SMAP becomes pain point when the copy is short (e.g 64B) for high PPS.
Thanks
Thanks a lot for looking into this!
So first of all users can just boot with nosmap, right? What's wrong with that?
Nothing wrong, just realize we had this kernel parameter.
Quoted 6 lines
Yes it's not fine-grained but OTOH
it's easy to understand.And I guess this confirms that if we are going to worry about smap enabled, we need to look into packet copies too, not just meta-data.
For packet copies, we can do batch copy which is pretty simple for the case of XDP. I've already had patches for this.
Quoted 5 lines
Vaguely could see a module option (off by default) where vhost basically does
user_access_beginwhen it starts running, then uses unsafe accesses in vhost and tun and thenuser_access_end.
Using user_access_begin() is more tricky than imaged. E.g it requires:
- userspace address to be validated before through access_ok() [1]
- It doesn't support calling a function that does explicit schedule since SMAP/PAN state is not maintained through schedule() [2]
[1] https://lwn.net/Articles/736348/
[2] https://lkml.org/lkml/2018/11/23/430
So calling user_access_begin() all the time when vhost is running seems pretty dangerous.
For a better batched datacopy, I tend to build not only XDP but also skb in vhost in the future.
Thanks
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
Michael S. Tsirkin
maintainerRe: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
Quoted 189 lines · Jason Wang
Quoted 111 lines · Michael S. Tsirkin
Quoted 99 lines · Jason Wang
Quoted 98 lines · Michael S. Tsirkin
Quoted 79 lines · Jason Wang
Quoted 70 lines · Michael S. Tsirkin
Quoted 69 lines · Jason Wang
Quoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
Quoted 55 lines · Michael S. Tsirkin
Quoted 54 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +14
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ;Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 634
Quoted 5 lines
drivers/vhost/vhost.c +5
-0+ + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.The pages wil be released during set features.
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
So no THP, no NUMA rebalancing,
For THP, we will probably miss 2 or 4 pages, but does this really matter consider the gain we have?
We as in vhost? networking isn't the only thing guest does. We don't even know if this guest does a lot of networking. You don't
know what else is in this huge page. Can be something very important that guest touches all the time.Quoted 4 lines
Well, the probability should be very small consider we usually give several gigabytes to guest. The rest of the pages that doesn't sit in the same hugepage with metadata can still be merged by THP. Anyway, I can test the differences.
Thanks!
Quoted 12 lines
Quoted 8 lines
Quoted 4 lines
For NUMA rebalancing, I'm even not quite sure if
it can helps for the case of IPC (vhost). It looks to me the worst case it may cause page to be thrash between nodes if vhost and userspace are running in two nodes.So again it's a gain for vhost but has a completely unpredictable effect on other functionality of the guest.
That's what bothers me with this approach.
So:
- The rest of the pages could still be balanced to other nodes, no?
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
- try to balance metadata pages (belongs to co-operate processes) itself is still questionable
I am not sure why. It should be easy enough to force the VCPU and vhost to move (e.g. start them pinned to 1 cpu, then pin them to another one). Clearly sometimes this would be necessary for load balancing reasons.
Yes, but it looks to me the part of motivation of auto NUMA is to avoid manual pinning.
... of memory. Yes.
Quoted 7 lines
Quoted 6 lines
Quoted 3 lines
With autonuma after a while (could take seconds but it will happen) the memory will migrate.
Yes. As you mentioned during the discuss, I wonder we could do it similarly through mmu notifier like APIC access page in commit
c24ae0dcd3e("kvm: x86:
Unpin and removekvm_arch->apic_access_page")That would be a possible approach.
Yes, this looks possible, and the conversion seems not hard. Let me have a try with this.
[...]
Quoted 28 lines
Quoted 28 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 7 lines
Quoted 2 lines
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
The problem is not kthread but the address of userspace address. The addresses of vq metadata tends to be consistent for a while, and vhost knows they will be frequently. SMAP doesn't help too much in this case.
Thanks.
It's true for a real life applications but a malicious one can call the setup ioctls any number of times. And SMAP is all about malcious applications.
Quoted 7 lines
Quoted 6 lines
We don't do this in the path of ioctl, there's no context switch between userspace and kernel in the worker thread. SMAP is used to prevent kernel from accessing userspace pages unexpectedly which is not the case for metadata access.
Thanks
OK let's forget smap for now.
Some numbers I measured:
On an old Sandy bridge machine without SMAP support. Remove speculation barrier boost the performance from 4.6Mpps to 5.1Mpps
On a newer Broadwell machine with SMAP support. Remove speculation barrier only gives 2%-5% improvement, disable SMAP completely through
Kconfigboost 57% performance from 4.8Mpps to 7.5Mpps. (Vmap gives 6Mpps - 6.1Mpps, it only bypass SMAP for metadata).Quoted 8 lines
Quoted 4 lines
So it looks like for recent machine, SMAP becomes pain point when the copy is short (e.g 64B) for high PPS.
Thanks
Thanks a lot for looking into this!
So first of all users can just boot with nosmap, right? What's wrong with that?
Nothing wrong, just realize we had this kernel parameter.
Quoted 6 lines
Yes it's not fine-grained but OTOH
it's easy to understand.And I guess this confirms that if we are going to worry about smap enabled, we need to look into packet copies too, not just meta-data.
For packet copies, we can do batch copy which is pretty simple for the case of XDP. I've already had patches for this.
Quoted 5 lines
Vaguely could see a module option (off by default) where vhost basically does
user_access_beginwhen it starts running, then uses unsafe accesses in vhost and tun and thenuser_access_end.
Quoted 3 lines
Using
user_access_begin()is more tricky than imaged. E.g it requires:- userspace address to be validated before through
access_ok()[1]
This part is fine I think - addresses come from the memory map and when userspace supplies the memory map
we validate everything with access_ok.
Well do we validate with the iotlb too? Don't see it right now so maybe not but it's easy to add.
Quoted 9 lines
- It doesn't support calling a function that does explicit schedule since SMAP/PAN state is not maintained through
schedule()[2][1] https://lwn.net/Articles/736348/
[2] https://lkml.org/lkml/2018/11/23/430
So calling
user_access_begin()all the time when vhost is running seems pretty dangerous.
Yes it requires some rework e.g. to try getting memory with GFP_ATOMIC. We could then do a slow path with GFP_KERNEL if that fails.
Quoted 4 lines
For a better batched datacopy, I tend to build not only XDP but also skb in vhost in the future.
Thanks
Sure, why not.
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
Quoted 182 lines · Michael S. Tsirkin
Quoted 181 lines · Jason Wang
Quoted 110 lines · Michael S. Tsirkin
Quoted 99 lines · Jason Wang
Quoted 98 lines · Michael S. Tsirkin
Quoted 79 lines · Jason Wang
Quoted 70 lines · Michael S. Tsirkin
Quoted 69 lines · Jason Wang
Quoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
Quoted 55 lines · Michael S. Tsirkin
Quoted 54 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +14
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ;Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 634
Quoted 5 lines
drivers/vhost/vhost.c +5
-0+ + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.The pages wil be released during set features.
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
So no THP, no NUMA rebalancing,
For THP, we will probably miss 2 or 4 pages, but does this really matter consider the gain we have?
We as in vhost? networking isn't the only thing guest does. We don't even know if this guest does a lot of networking. You don't
know what else is in this huge page. Can be something very important that guest touches all the time.Quoted 4 lines
Well, the probability should be very small consider we usually give several gigabytes to guest. The rest of the pages that doesn't sit in the same hugepage with metadata can still be merged by THP. Anyway, I can test the differences.
Thanks!
Quoted 12 lines
Quoted 8 lines
Quoted 4 lines
For NUMA rebalancing, I'm even not quite sure if
it can helps for the case of IPC (vhost). It looks to me the worst case it may cause page to be thrash between nodes if vhost and userspace are running in two nodes.So again it's a gain for vhost but has a completely unpredictable effect on other functionality of the guest.
That's what bothers me with this approach.
So:
- The rest of the pages could still be balanced to other nodes, no?
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
- try to balance metadata pages (belongs to co-operate processes) itself is still questionable
I am not sure why. It should be easy enough to force the VCPU and vhost to move (e.g. start them pinned to 1 cpu, then pin them to another one). Clearly sometimes this would be necessary for load balancing reasons.
Yes, but it looks to me the part of motivation of auto NUMA is to avoid manual pinning.
... of memory. Yes.
Quoted 7 lines
Quoted 6 lines
Quoted 3 lines
With autonuma after a while (could take seconds but it will happen) the memory will migrate.
Yes. As you mentioned during the discuss, I wonder we could do it similarly through mmu notifier like APIC access page in commit
c24ae0dcd3e("kvm: x86:
Unpin and removekvm_arch->apic_access_page")That would be a possible approach.
Yes, this looks possible, and the conversion seems not hard. Let me have a try with this.
[...]
Quoted 27 lines
Quoted 27 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 7 lines
Quoted 2 lines
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
The problem is not kthread but the address of userspace address. The addresses of vq metadata tends to be consistent for a while, and vhost knows they will be frequently. SMAP doesn't help too much in this case.
Thanks.
It's true for a real life applications but a malicious one can call the setup ioctls any number of times. And SMAP is all about malcious applications.
Quoted 7 lines
Quoted 6 lines
We don't do this in the path of ioctl, there's no context switch between userspace and kernel in the worker thread. SMAP is used to prevent kernel from accessing userspace pages unexpectedly which is not the case for metadata access.
Thanks
OK let's forget smap for now.
Some numbers I measured:
On an old Sandy bridge machine without SMAP support. Remove speculation barrier boost the performance from 4.6Mpps to 5.1Mpps
On a newer Broadwell machine with SMAP support. Remove speculation barrier only gives 2%-5% improvement, disable SMAP completely through
Kconfigboost 57% performance from 4.8Mpps to 7.5Mpps. (Vmap gives 6Mpps - 6.1Mpps, it only bypass SMAP for metadata).Quoted 8 lines
Quoted 4 lines
So it looks like for recent machine, SMAP becomes pain point when the copy is short (e.g 64B) for high PPS.
Thanks
Thanks a lot for looking into this!
So first of all users can just boot with nosmap, right? What's wrong with that?
Nothing wrong, just realize we had this kernel parameter.
Quoted 6 lines
Yes it's not fine-grained but OTOH
it's easy to understand.And I guess this confirms that if we are going to worry about smap enabled, we need to look into packet copies too, not just meta-data.
For packet copies, we can do batch copy which is pretty simple for the case of XDP. I've already had patches for this.
Quoted 4 lines
Vaguely could see a module option (off by default) where vhost basically does
user_access_beginwhen it starts running, then uses unsafe accesses in vhost and tun and thenuser_access_end.
Quoted 8 lines
Quoted 3 lines
Using
user_access_begin()is more tricky than imaged. E.g it requires:- userspace address to be validated before through
access_ok()[1]This part is fine I think - addresses come from the memory map and when userspace supplies the memory map
we validate everything withaccess_ok.
Well do we validate with the iotlb too? Don't see it right now so maybe not but it's easy to add.
Yes, it's not hard.
Quoted 6 lines
Quoted 6 lines
- It doesn't support calling a function that does explicit schedule since SMAP/PAN state is not maintained through
schedule()[2]
Quoted 7 lines
Quoted 4 lines
[2] https://lkml.org/lkml/2018/11/23/430
So calling
user_access_begin()all the time when vhost is running seems pretty dangerous.Yes it requires some rework e.g. to try getting memory with
GFP_ATOMIC. We could then do a slow path withGFP_KERNELif that fails.
I'm not sure this is the only part that needs care. Consider all the under layer network or block codes assumes a process context, it's not easy to figure out all I'm afraid. And even if we could, it's hard to prevent it from being added in the future.
Thanks
Quoted 12 lines
Quoted 5 lines
For a better batched datacopy, I tend to build not only XDP but also skb in vhost in the future.
Thanks
Sure, why not.
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
Re: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
In reply to Michael S. TsirkinQuoted 182 lines · Michael S. Tsirkin
Quoted 181 lines · Jason Wang
Quoted 110 lines · Michael S. Tsirkin
Quoted 99 lines · Jason Wang
Quoted 98 lines · Michael S. Tsirkin
Quoted 79 lines · Jason Wang
Quoted 70 lines · Michael S. Tsirkin
Quoted 69 lines · Jason Wang
Quoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
Quoted 55 lines · Michael S. Tsirkin
Quoted 54 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +14
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ;Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 634
Quoted 5 lines
drivers/vhost/vhost.c +5
-0+ + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.The pages wil be released during set features.
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
So no THP, no NUMA rebalancing,
For THP, we will probably miss 2 or 4 pages, but does this really matter consider the gain we have?
We as in vhost? networking isn't the only thing guest does. We don't even know if this guest does a lot of networking. You don't
know what else is in this huge page. Can be something very important that guest touches all the time.Quoted 4 lines
Well, the probability should be very small consider we usually give several gigabytes to guest. The rest of the pages that doesn't sit in the same hugepage with metadata can still be merged by THP. Anyway, I can test the differences.
Thanks!
Quoted 12 lines
Quoted 8 lines
Quoted 4 lines
For NUMA rebalancing, I'm even not quite sure if
it can helps for the case of IPC (vhost). It looks to me the worst case it may cause page to be thrash between nodes if vhost and userspace are running in two nodes.So again it's a gain for vhost but has a completely unpredictable effect on other functionality of the guest.
That's what bothers me with this approach.
So:
- The rest of the pages could still be balanced to other nodes, no?
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
- try to balance metadata pages (belongs to co-operate processes) itself is still questionable
I am not sure why. It should be easy enough to force the VCPU and vhost to move (e.g. start them pinned to 1 cpu, then pin them to another one). Clearly sometimes this would be necessary for load balancing reasons.
Yes, but it looks to me the part of motivation of auto NUMA is to avoid manual pinning.
... of memory. Yes.
Quoted 7 lines
Quoted 6 lines
Quoted 3 lines
With autonuma after a while (could take seconds but it will happen) the memory will migrate.
Yes. As you mentioned during the discuss, I wonder we could do it similarly through mmu notifier like APIC access page in commit
c24ae0dcd3e("kvm: x86:
Unpin and removekvm_arch->apic_access_page")That would be a possible approach.
Yes, this looks possible, and the conversion seems not hard. Let me have a try with this.
[...]
Quoted 27 lines
Quoted 27 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 7 lines
Quoted 2 lines
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
The problem is not kthread but the address of userspace address. The addresses of vq metadata tends to be consistent for a while, and vhost knows they will be frequently. SMAP doesn't help too much in this case.
Thanks.
It's true for a real life applications but a malicious one can call the setup ioctls any number of times. And SMAP is all about malcious applications.
Quoted 7 lines
Quoted 6 lines
We don't do this in the path of ioctl, there's no context switch between userspace and kernel in the worker thread. SMAP is used to prevent kernel from accessing userspace pages unexpectedly which is not the case for metadata access.
Thanks
OK let's forget smap for now.
Some numbers I measured:
On an old Sandy bridge machine without SMAP support. Remove speculation barrier boost the performance from 4.6Mpps to 5.1Mpps
On a newer Broadwell machine with SMAP support. Remove speculation barrier only gives 2%-5% improvement, disable SMAP completely through
Kconfigboost 57% performance from 4.8Mpps to 7.5Mpps. (Vmap gives 6Mpps - 6.1Mpps, it only bypass SMAP for metadata).Quoted 8 lines
Quoted 4 lines
So it looks like for recent machine, SMAP becomes pain point when the copy is short (e.g 64B) for high PPS.
Thanks
Thanks a lot for looking into this!
So first of all users can just boot with nosmap, right? What's wrong with that?
Nothing wrong, just realize we had this kernel parameter.
Quoted 6 lines
Yes it's not fine-grained but OTOH
it's easy to understand.And I guess this confirms that if we are going to worry about smap enabled, we need to look into packet copies too, not just meta-data.
For packet copies, we can do batch copy which is pretty simple for the case of XDP. I've already had patches for this.
Quoted 4 lines
Vaguely could see a module option (off by default) where vhost basically does
user_access_beginwhen it starts running, then uses unsafe accesses in vhost and tun and thenuser_access_end.
Quoted 8 lines
Quoted 3 lines
Using
user_access_begin()is more tricky than imaged. E.g it requires:- userspace address to be validated before through
access_ok()[1]This part is fine I think - addresses come from the memory map and when userspace supplies the memory map
we validate everything withaccess_ok.
Well do we validate with the iotlb too? Don't see it right now so maybe not but it's easy to add.
Yes, it's not hard.
Quoted 6 lines
Quoted 6 lines
- It doesn't support calling a function that does explicit schedule since SMAP/PAN state is not maintained through
schedule()[2]
Quoted 7 lines
Quoted 4 lines
[2] https://lkml.org/lkml/2018/11/23/430
So calling
user_access_begin()all the time when vhost is running seems pretty dangerous.Yes it requires some rework e.g. to try getting memory with
GFP_ATOMIC. We could then do a slow path withGFP_KERNELif that fails.
I'm not sure this is the only part that needs care. Consider all the under layer network or block codes assumes a process context, it's not easy to figure out all I'm afraid. And even if we could, it's hard to prevent it from being added in the future.
Thanks
Quoted 12 lines
Quoted 5 lines
For a better batched datacopy, I tend to build not only XDP but also skb in vhost in the future.
Thanks
Sure, why not.
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
In reply to Michael S. TsirkinQuoted 111 lines · Michael S. Tsirkin
Quoted 99 lines · Jason Wang
Quoted 98 lines · Michael S. Tsirkin
Quoted 79 lines · Jason Wang
Quoted 70 lines · Michael S. Tsirkin
Quoted 69 lines · Jason Wang
Quoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
Quoted 55 lines · Michael S. Tsirkin
Quoted 54 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +14
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ;Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 634
Quoted 5 lines
drivers/vhost/vhost.c +5
-0+ + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.The pages wil be released during set features.
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
So no THP, no NUMA rebalancing,
For THP, we will probably miss 2 or 4 pages, but does this really matter consider the gain we have?
We as in vhost? networking isn't the only thing guest does. We don't even know if this guest does a lot of networking. You don't
know what else is in this huge page. Can be something very important that guest touches all the time.Quoted 4 lines
Well, the probability should be very small consider we usually give several gigabytes to guest. The rest of the pages that doesn't sit in the same hugepage with metadata can still be merged by THP. Anyway, I can test the differences.
Thanks!
Quoted 12 lines
Quoted 8 lines
Quoted 4 lines
For NUMA rebalancing, I'm even not quite sure if
it can helps for the case of IPC (vhost). It looks to me the worst case it may cause page to be thrash between nodes if vhost and userspace are running in two nodes.So again it's a gain for vhost but has a completely unpredictable effect on other functionality of the guest.
That's what bothers me with this approach.
So:
- The rest of the pages could still be balanced to other nodes, no?
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
- try to balance metadata pages (belongs to co-operate processes) itself is still questionable
I am not sure why. It should be easy enough to force the VCPU and vhost to move (e.g. start them pinned to 1 cpu, then pin them to another one). Clearly sometimes this would be necessary for load balancing reasons.
Yes, but it looks to me the part of motivation of auto NUMA is to avoid manual pinning.
... of memory. Yes.
Quoted 7 lines
Quoted 6 lines
Quoted 3 lines
With autonuma after a while (could take seconds but it will happen) the memory will migrate.
Yes. As you mentioned during the discuss, I wonder we could do it similarly through mmu notifier like APIC access page in commit
c24ae0dcd3e("kvm: x86:
Unpin and removekvm_arch->apic_access_page")That would be a possible approach.
Yes, this looks possible, and the conversion seems not hard. Let me have a try with this.
[...]
Quoted 28 lines
Quoted 28 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 7 lines
Quoted 2 lines
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
The problem is not kthread but the address of userspace address. The addresses of vq metadata tends to be consistent for a while, and vhost knows they will be frequently. SMAP doesn't help too much in this case.
Thanks.
It's true for a real life applications but a malicious one can call the setup ioctls any number of times. And SMAP is all about malcious applications.
Quoted 7 lines
Quoted 6 lines
We don't do this in the path of ioctl, there's no context switch between userspace and kernel in the worker thread. SMAP is used to prevent kernel from accessing userspace pages unexpectedly which is not the case for metadata access.
Thanks
OK let's forget smap for now.
Some numbers I measured:
On an old Sandy bridge machine without SMAP support. Remove speculation barrier boost the performance from 4.6Mpps to 5.1Mpps
On a newer Broadwell machine with SMAP support. Remove speculation barrier only gives 2%-5% improvement, disable SMAP completely through
Kconfigboost 57% performance from 4.8Mpps to 7.5Mpps. (Vmap gives 6Mpps - 6.1Mpps, it only bypass SMAP for metadata).
Quoted 8 lines
Quoted 4 lines
So it looks like for recent machine, SMAP becomes pain point when the copy is short (e.g 64B) for high PPS.
Thanks
Thanks a lot for looking into this!
So first of all users can just boot with nosmap, right? What's wrong with that?
Nothing wrong, just realize we had this kernel parameter.
Quoted 6 lines
Yes it's not fine-grained but OTOH
it's easy to understand.And I guess this confirms that if we are going to worry about smap enabled, we need to look into packet copies too, not just meta-data.
For packet copies, we can do batch copy which is pretty simple for the case of XDP. I've already had patches for this.
Quoted 5 lines
Vaguely could see a module option (off by default) where vhost basically does
user_access_beginwhen it starts running, then uses unsafe accesses in vhost and tun and thenuser_access_end.
Using user_access_begin() is more tricky than imaged. E.g it requires:
- userspace address to be validated before through access_ok() [1]
- It doesn't support calling a function that does explicit schedule since SMAP/PAN state is not maintained through schedule() [2]
[1] https://lwn.net/Articles/736348/
[2] https://lkml.org/lkml/2018/11/23/430
So calling user_access_begin() all the time when vhost is running seems pretty dangerous.
For a better batched datacopy, I tend to build not only XDP but also skb in vhost in the future.
Thanks
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
In reply to Michael S. TsirkinQuoted 98 lines · Michael S. Tsirkin
Quoted 80 lines · Jason Wang
Quoted 70 lines · Michael S. Tsirkin
Quoted 69 lines · Jason Wang
Quoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
Quoted 55 lines · Michael S. Tsirkin
Quoted 54 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +14
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ;Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 634
Quoted 5 lines
drivers/vhost/vhost.c +5
-0+ + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.The pages wil be released during set features.
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
So no THP, no NUMA rebalancing,
For THP, we will probably miss 2 or 4 pages, but does this really matter consider the gain we have?
We as in vhost? networking isn't the only thing guest does. We don't even know if this guest does a lot of networking. You don't
know what else is in this huge page. Can be something very important that guest touches all the time.Quoted 4 lines
Well, the probability should be very small consider we usually give several gigabytes to guest. The rest of the pages that doesn't sit in the same hugepage with metadata can still be merged by THP. Anyway, I can test the differences.
Thanks!
Quoted 11 lines
Quoted 8 lines
Quoted 4 lines
For NUMA rebalancing, I'm even not quite sure if
it can helps for the case of IPC (vhost). It looks to me the worst case it may cause page to be thrash between nodes if vhost and userspace are running in two nodes.So again it's a gain for vhost but has a completely unpredictable effect on other functionality of the guest.
That's what bothers me with this approach.
So:
Quoted 7 lines
Quoted 4 lines
- The rest of the pages could still be balanced to other nodes, no?
- try to balance metadata pages (belongs to co-operate processes) itself is still questionable
I am not sure why. It should be easy enough to force the VCPU and vhost to move (e.g. start them pinned to 1 cpu, then pin them to another one). Clearly sometimes this would be necessary for load balancing reasons.
Yes, but it looks to me the part of motivation of auto NUMA is to avoid manual pinning.
Quoted 3 lines
With autonuma after a while (could take seconds but it will happen) the memory will migrate.
Yes. As you mentioned during the discuss, I wonder we could do it similarly through mmu notifier like APIC access page in commit c24ae0dcd3e ("kvm: x86: Unpin and remove kvm_arch->apic_access_page")
Quoted 19 lines
Quoted 5 lines
Quoted 5 lines
Quoted 7 lines
Quoted 4 lines
Quoted 3 lines
Quoted 2 lines
Quoted 1 line
This is the price of all GUP users not only vhost itself.
Yes. GUP is just not a great interface for vhost to use.
Zerocopy codes (enabled by defualt) use them for years.
But only for TX and temporarily. We pin, read, unpin.
Probably not. For several reasons that the page will be not be released soon or held for a very long period of time or even forever.
With zero copy? Well it's pinned until transmit. Takes a while but could be enough for autocopy to work esp since its the packet memory so not reused immediately.
Quoted 2 lines
Quoted 2 lines
Your patch is different
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
- it writes into memory and GUP has known issues with file backed memory
The ordinary user for vhost is anonymous pages I think?
It's not the most common scenario and not the fastest one (e.g. THP does not work) but file backed is useful sometimes. It would not be nice at all to corrupt guest memory in that case.
Ok.
Quoted 38 lines
Quoted 38 lines
Quoted 37 lines
- it keeps pages pinned forever
Quoted 22 lines
Quoted 5 lines
Quoted 3 lines
What's more
important, the goal is not to be left too much behind for other backends like DPDK orAF_XDP(all of which are using GUP).So these guys assume userspace knows what it's doing. We can't assume that.
What kind of assumption do you they have?
Quoted 14 lines
Quoted 14 lines
Quoted 2 lines
userspace-controlled
amount of memory locked up and not accounted for.It's pretty easy to add this since the slow path was still kept. If we exceeds the limitation, we can switch back to slow path.
Quoted 2 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
Again, this is only for metadata accessing not the data which has been used for years for real use cases.
For SMAP, it makes senses for the address that kernel can not forcast. But it's not the case for the vhost metadata since we know the address will be accessed very frequently. For speculation barrier, it helps nothing for the data path of vhost which is a kthread.
Quoted 7 lines
Quoted 2 lines
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
The problem is not kthread but the address of userspace address. The addresses of vq metadata tends to be consistent for a while, and vhost knows they will be frequently. SMAP doesn't help too much in this case.
Thanks.
It's true for a real life applications but a malicious one can call the setup ioctls any number of times. And SMAP is all about malcious applications.
Quoted 7 lines
Quoted 6 lines
We don't do this in the path of ioctl, there's no context switch between userspace and kernel in the worker thread. SMAP is used to prevent kernel from accessing userspace pages unexpectedly which is not the case for metadata access.
Thanks
OK let's forget smap for now.
Some numbers I measured:
On an old Sandy bridge machine without SMAP support. Remove speculation barrier boost the performance from 4.6Mpps to 5.1Mpps
On a newer Broadwell machine with SMAP support. Remove speculation barrier only gives 2%-5% improvement, disable SMAP completely through Kconfig boost 57% performance from 4.8Mpps to 7.5Mpps. (Vmap gives 6Mpps - 6.1Mpps, it only bypass SMAP for metadata).
So it looks like for recent machine, SMAP becomes pain point when the copy is short (e.g 64B) for high PPS.
Thanks
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Michael S. Tsirkin
maintainerRe: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
In reply to Jason WangQuoted 69 lines · Jason Wang
Quoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
Quoted 55 lines · Michael S. Tsirkin
Quoted 54 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +14
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ;Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 635
Quoted 5 lines
drivers/vhost/vhost.c +5
-0+ + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.
Quoted 8 lines
The pages wil be released during set features.
Quoted 1 line
Quoted 1 line
Quoted 1 line
So no THP, no NUMA rebalancing,
For THP, we will probably miss 2 or 4 pages, but does this really matter consider the gain we have?
We as in vhost? networking isn't the only thing guest does. We don't even know if this guest does a lot of networking. You don't
know what else is in this huge page. Can be something very important that guest touches all the time.
Quoted 4 lines
For NUMA rebalancing, I'm even not quite sure if
it can helps for the case of IPC (vhost). It looks to me the worst case it may cause page to be thrash between nodes if vhost and userspace are running in two nodes.
So again it's a gain for vhost but has a completely unpredictable effect on other functionality of the guest.
That's what bothers me with this approach.
Quoted 7 lines
Quoted 4 lines
Quoted 3 lines
This is the price of all GUP users not only vhost itself.
Yes. GUP is just not a great interface for vhost to use.
Zerocopy codes (enabled by defualt) use them for years.
But only for TX and temporarily. We pin, read, unpin.
Your patch is different
- it writes into memory and GUP has known issues with file backed memory
- it keeps pages pinned forever
Quoted 34 lines
Quoted 8 lines
Quoted 5 lines
What's more
important, the goal is not to be left too much behind for other backends like DPDK orAF_XDP(all of which are using GUP).So these guys assume userspace knows what it's doing. We can't assume that.
What kind of assumption do you they have?
Quoted 13 lines
Quoted 13 lines
Quoted 3 lines
userspace-controlled
amount of memory locked up and not accounted for.It's pretty easy to add this since the slow path was still kept. If we exceeds the limitation, we can switch back to slow path.
Quoted 2 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
Again, this is only for metadata accessing not the data which has been used for years for real use cases.
Quoted 6 lines
Quoted 4 lines
For SMAP, it makes senses for the address that kernel can not forcast. But it's not the case for the vhost metadata since we know the address will be accessed very frequently. For speculation barrier, it helps nothing for the data path of vhost which is a kthread.
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
Quoted 5 lines
The problem is not kthread but the address of userspace address. The addresses of vq metadata tends to be consistent for a while, and vhost knows they will be frequently. SMAP doesn't help too much in this case.
Thanks.
It's true for a real life applications but a malicious one can call the setup ioctls any number of times. And SMAP is all about malcious applications.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Re: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
In reply to Michael S. TsirkinQuoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
Quoted 55 lines · Michael S. Tsirkin
Quoted 54 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +14
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ;
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 635
Quoted 5 lines
drivers/vhost/vhost.c +5
-0+ + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.
The pages wil be released during set features.
Quoted 1 line
Quoted 1 line
Quoted 1 line
So no THP, no NUMA rebalancing,
For THP, we will probably miss 2 or 4 pages, but does this really matter consider the gain we have? For NUMA rebalancing, I'm even not quite sure if it can helps for the case of IPC (vhost). It looks to me the worst case it may cause page to be thrash between nodes if vhost and userspace are running in two nodes.
Quoted 3 lines
Quoted 2 lines
This is the price of all GUP users not only vhost itself.
Yes. GUP is just not a great interface for vhost to use.
Zerocopy codes (enabled by defualt) use them for years.
Quoted 7 lines
Quoted 4 lines
What's more
important, the goal is not to be left too much behind for other backends like DPDK orAF_XDP(all of which are using GUP).So these guys assume userspace knows what it's doing. We can't assume that.
What kind of assumption do you they have?
Quoted 13 lines
Quoted 13 lines
Quoted 3 lines
userspace-controlled
amount of memory locked up and not accounted for.It's pretty easy to add this since the slow path was still kept. If we exceeds the limitation, we can switch back to slow path.
Quoted 2 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
Again, this is only for metadata accessing not the data which has been used for years for real use cases.
Quoted 6 lines
Quoted 4 lines
For SMAP, it makes senses for the address that kernel can not forcast. But it's not the case for the vhost metadata since we know the address will be accessed very frequently. For speculation barrier, it helps nothing for the data path of vhost which is a kthread.
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
The problem is not kthread but the address of userspace address. The addresses of vq metadata tends to be consistent for a while, and vhost knows they will be frequently. SMAP doesn't help too much in this case.
Thanks.
Quoted 5 lines
Quoted 5 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Michael S. Tsirkin
maintainerRe: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
In reply to Jason WangQuoted 68 lines · Jason Wang
Quoted 56 lines · Michael S. Tsirkin
Quoted 55 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +15
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ; +Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 635
Quoted 4 lines
drivers/vhost/vhost.c +4
-0+ npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.
So no THP, no NUMA rebalancing,
Quoted 1 line
This is the price of all GUP users not only vhost itself.
Yes. GUP is just not a great interface for vhost to use.
Quoted 3 lines
What's more
important, the goal is not to be left too much behind for other backends like DPDK orAF_XDP(all of which are using GUP).
So these guys assume userspace knows what it's doing. We can't assume that.
Quoted 13 lines
Quoted 3 lines
userspace-controlled
amount of memory locked up and not accounted for.It's pretty easy to add this since the slow path was still kept. If we exceeds the limitation, we can switch back to slow path.
Quoted 3 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
Quoted 7 lines
Again, this is only for metadata accessing not the data which has been used for years for real use cases.
For SMAP, it makes senses for the address that kernel can not forcast. But it's not the case for the vhost metadata since we know the address will be accessed very frequently. For speculation barrier, it helps nothing for the data path of vhost which is a kthread.
I don't see how a kthread makes any difference. We do have a validation step which makes some difference.
Quoted 4 lines
Packet or
AF_XDPbenefit from
accessing metadata directly, we should do it as well.Thanks
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
David Miller
maintainerRe: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
In reply to Jason WangFrom: Jason Wang <[email protected]>
Date: Fri, 14 Dec 2018 11:57:35 +0800
Quoted 3 lines
This is the price of all GUP users not only vhost itself. What's more important, the goal is not to be left too much behind for other backends like DPDK or
AF_XDP(all of which are using GUP).
+1
Re: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
In reply to Michael S. TsirkinQuoted 57 lines · Michael S. Tsirkin
Quoted 56 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang<[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +15
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ; +
Quoted 8 lines
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 635
Quoted 4 lines
drivers/vhost/vhost.c +4
-0+ npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.
So no THP, no NUMA rebalancing,
This is the price of all GUP users not only vhost itself. What's more important, the goal is not to be left too much behind for other backends like DPDK or AF_XDP (all of which are using GUP).
Quoted 2 lines
userspace-controlled
amount of memory locked up and not accounted for.
It's pretty easy to add this since the slow path was still kept. If we exceeds the limitation, we can switch back to slow path.
Quoted 3 lines
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
Again, this is only for metadata accessing not the data which has been used for years for real use cases.
For SMAP, it makes senses for the address that kernel can not forcast. But it's not the case for the vhost metadata since we know the address will be accessed very frequently. For speculation barrier, it helps nothing for the data path of vhost which is a kthread. Packet or AF_XDP benefit from accessing metadata directly, we should do it as well.
Thanks
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Michael S. Tsirkin
maintainerRe: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
In reply to Jason WangQuoted 50 lines · Jason Wang
It was noticed that the
copy_user()friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.This patch tries to eliminate those overhead by pin vq metadata pages and access them through
vmap(). DuringSET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user +
vhost_net+ xdp1 on TAP (CONFIG_HARDENED_USERCOPYis not enabled):Before: ~5.0Mpps After: ~6.1MppsSigned-off-by Jason Wang <[email protected]>--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)drivers/vhost/vhost.c +9
-0@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned;
drivers/vhost/vhost.c static void vhost_clear_msg(struct vhost_dev *dev) · line 635
Quoted 10 lines
drivers/vhost/vhost.c +10
-0+void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ; + + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; +
As I said I have doubts about the whole approach, but this implementation in particular isn't a good idea
as it keeps the page around forever.
So no THP, no NUMA rebalancing, userspace-controlled amount of memory locked up and not accounted for.
Don't get me wrong it's a great patch in an ideal world. But then in an ideal world no barriers smap etc are necessary at all.
Quoted 273 lines
drivers/vhost/vhost.c +159
-0+ vaddr =vmap (pages, npages,VM_MAP ,PAGE_KERNEL ); +if (!vaddr) + goto err; + + map->pages = pages; + map->addr = vaddr + (uaddr & (PAGE_SIZE -1 )); + map->npages = npages; + +return 0 ; + +err: +if (npinned >0 ) +release_pages (pages, npinned); +kfree (pages); +return -EFAULT ; +} + +static void vhost_uninit_vmap (struct vhost_vmap *map) +{ +if (!map->addr) +return ; + +vunmap (map->addr); +release_pages (map->pages, map->npages); +kfree (map->pages); + + map->addr =NULL ; + map->pages =NULL ; + map->npages =0 ; +} + +static void vhost_clean_vmaps (struct vhost_virtqueue *vq) +{ +vhost_uninit_vmap (&vq->avail_ring); +vhost_uninit_vmap (&vq->desc_ring); +vhost_uninit_vmap (&vq->used_ring); +} + +static int vhost_setup_vmaps (struct vhost_virtqueue *vq,unsigned long avail, +unsigned long desc,unsigned long used) +{ +size_t event =vhost_has_feature (vq,VIRTIO_RING_F_EVENT_IDX ) ?2 :0 ; +size_t avail_size, desc_size, used_size; +int ret; + +vhost_clean_vmaps (vq); + + avail_size =sizeof (*vq->avail) + +sizeof (*vq->avail->ring) * vq->num + event; + ret =vhost_init_vmap (&vq->avail_ring, avail, avail_size, false); +if (ret) { +vq_err (vq,"Fail to setup vmap for avail ring!\n" ); + goto err_avail; + } + + desc_size =sizeof (*vq->desc) * vq->num; + ret =vhost_init_vmap (&vq->desc_ring, desc, desc_size, false); +if (ret) { +vq_err (vq,"Fail to setup vmap for desc ring!\n" ); + goto err_desc; + } + + used_size =sizeof (*vq->used) + +sizeof (*vq->used->ring) * vq->num + event; + ret =vhost_init_vmap (&vq->used_ring, used, used_size, true); +if (ret) { +vq_err (vq,"Fail to setup vmap for used ring!\n" ); + goto err_used; + } + +return 0 ; + +err_used: +vhost_uninit_vmap (&vq->used_ring); +err_desc: +vhost_uninit_vmap (&vq->avail_ring); +err_avail: +return -EFAULT ; +} +void vhost_dev_cleanup (struct vhost_dev *dev) {int i;@@ -626,6 +725,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev)if (dev->vqs[i]->call_ctx)eventfd_ctx_put (dev->vqs[i]->call_ctx);vhost_vq_reset (dev, dev->vqs[i]); +vhost_clean_vmaps (dev->vqs[i]); }vhost_dev_free_iovecs (dev);if (dev->log_ctx)@@ -873,6 +973,14 @@ static inline void __user *__vhost_get_user(struct vhost_virtqueue *vq,static inline int vhost_put_avail_event (struct vhost_virtqueue *vq) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + *((__virtio16 *)&used->ring[vq->num]) = +cpu_to_vhost16 (vq, vq->avail_idx); +return 0 ; + } +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->avail_idx),vhost_avail_event (vq)); }@@ -881,6 +989,13 @@ static inline int vhost_put_used(struct vhost_virtqueue *vq, struct vring_used_elem *head, int idx, int count) { + if (!vq->iotlb) { + struct vring_used *used = vq->used_ring.addr; + +memcpy (used->ring + idx, head, count *sizeof (*head)); +return 0 ; + } +return vhost_copy_to_user (vq, vq->used->ring + idx, head, count *sizeof (*head)); }@@ -888,6 +1003,13 @@ static inline int vhost_put_used(struct vhost_virtqueue *vq,static inline int vhost_put_used_flags (struct vhost_virtqueue *vq) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + used->flags =cpu_to_vhost16 (vq, vq->used_flags); +return 0 ; + } +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->used_flags), &vq->used->flags); }@@ -895,6 +1017,13 @@ static inline int vhost_put_used_flags(struct vhost_virtqueue *vq)static inline int vhost_put_used_idx (struct vhost_virtqueue *vq) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + used->idx =cpu_to_vhost16 (vq, vq->last_used_idx); +return 0 ; + } +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->last_used_idx), &vq->used->idx); }@@ -926,12 +1055,26 @@ static inline int vhost_put_used_idx(struct vhost_virtqueue *vq)static inline int vhost_get_avail_idx (struct vhost_virtqueue *vq,__virtio16 *idx) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *idx = avail->idx; +return 0 ; + } +return vhost_get_avail (vq, *idx, &vq->avail->idx); }static inline int vhost_get_avail_head (struct vhost_virtqueue *vq,__virtio16 *head,int idx) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *head = avail->ring[idx & (vq->num -1 )]; +return 0 ; + } +return vhost_get_avail (vq, *head, &vq->avail->ring[idx & (vq->num -1 )]); }@@ -939,24 +1082,52 @@ static inline int vhost_get_avail_head(struct vhost_virtqueue *vq,static inline int vhost_get_avail_flags (struct vhost_virtqueue *vq,__virtio16 *flags) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *flags = avail->flags; +return 0 ; + } +return vhost_get_avail (vq, *flags, &vq->avail->flags); }static inline int vhost_get_used_event (struct vhost_virtqueue *vq,__virtio16 *event) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *event = (__virtio16 )avail->ring[vq->num]; +return 0 ; + } +return vhost_get_avail (vq, *event,vhost_used_event (vq)); }static inline int vhost_get_used_idx (struct vhost_virtqueue *vq,__virtio16 *idx) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + *idx = used->idx; +return 0 ; + } +return vhost_get_used (vq, *idx, &vq->used->idx); }static inline int vhost_get_desc (struct vhost_virtqueue *vq,struct vring_desc *desc,int idx) { +if (!vq->iotlb) { +struct vring_desc *d = vq->desc_ring.addr; + + *desc = *(d + idx); +return 0 ; + } +return vhost_copy_from_user (vq, desc, vq->desc + idx,sizeof (*desc)); }@@ -1551,6 +1722,13 @@ long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *arg } } +if (!vq->iotlb &&vhost_setup_vmaps (vq, a.avail_user_addr, + a.desc_user_addr, + a.used_user_addr)) { + r = -EINVAL ; +break ; + } + vq->log_used = !!(a.flags & (0x1 <<VHOST_VRING_F_LOG )); vq->desc = (void __user *)(unsigned long )a.desc_user_addr; vq->avail = (void __user *)(unsigned long )a.avail_user_addr;drivers/vhost/vhost.h +11
-0@@ -80,6 +80,12 @@ enum vhost_uaddr_type { VHOST_NUM_ADDRS = 3, }; +struct vhost_vmap { +struct page **pages; +void *addr; +int npages; +}; +/* The virtqueue structure describes a queue attached to a device. */ struct vhost_virtqueue {struct vhost_dev *dev;@@ -90,6 +96,11 @@ struct vhost_virtqueue {struct vring_desc __user *desc;struct vring_avail __user *avail;struct vring_used __user *used; + +struct vhost_vmap avail_ring; +struct vhost_vmap desc_ring; +struct vhost_vmap used_ring; +const struct vhost_umem_node *meta_iotlb[VHOST_NUM_ADDRS ];struct file *kick;struct eventfd_ctx *call_ctx;Signature · 1 line
2.17.1
kbuild test robot
build botRe: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
In reply to Jason WangI love your patch! Yet something to improve:
Hi Jason,
I love your patch! Yet something to improve:
[auto build test ERROR on net-next/master]
url: https://github.com/0day-ci/linux/commits/Jason-Wang/vhost-accelerate-metadata-access-through-vmap/20181214-200417
config: mips-malta_kvm_defconfig (attached as .config)
compiler: mipsel-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.2.0 make.cross ARCH=mips
All errors (new ones prefixed by >>):
drivers//vhost/vhost.c: In function 'vhost_init_vmap':
>> drivers//vhost/vhost.c:648:3: error: implicit declaration of function 'release_pages'; did you mean 'release_task'? [-Werror=implicit-function-declaration]
release_pages(pages, npinned);
^~~~~~~~~~~~~
release_taskcc1: some warnings being treated as errors
vim +648 drivers//vhost/vhost.c
619
620 static int vhost_init_vmap(struct vhost_vmap *map, unsigned long uaddr,
621 size_t size, int write)
622 {
623 struct page **pages;
624 int npages = DIV_ROUND_UP(size, PAGE_SIZE);
625 int npinned;
626 void *vaddr;
627
628 pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
629 if (!pages)
630 return -ENOMEM;
631
632 npinned = get_user_pages_fast(uaddr, npages, write, pages);
633 if (npinned != npages)
634 goto err;
635
636 vaddr = vmap(pages, npages, VM_MAP, PAGE_KERNEL);
637 if (!vaddr)
638 goto err;
639
640 map->pages = pages;
641 map->addr = vaddr + (uaddr & (PAGE_SIZE - 1));
642 map->npages = npages;
643
644 return 0;
645
646 err:
647 if (npinned > 0)
> 648 release_pages(pages, npinned);
649 kfree(pages);
650 return -EFAULT;
651 }
652
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
kbuild test robot
build botRe: [PATCH net-next 3/3] vhost: access vq metadata through kernel virtual address
In reply to Jason WangI love your patch! Yet something to improve:
Hi Jason,
I love your patch! Yet something to improve:
[auto build test ERROR on net-next/master]
url: https://github.com/0day-ci/linux/commits/Jason-Wang/vhost-accelerate-metadata-access-through-vmap/20181214-200417
config: mips-malta_kvm_defconfig (attached as .config)
compiler: mipsel-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.2.0 make.cross ARCH=mips
All errors (new ones prefixed by >>):
drivers//vhost/vhost.c: In function 'vhost_init_vmap':
>> drivers//vhost/vhost.c:648:3: error: implicit declaration of function 'release_pages'; did you mean 'release_task'? [-Werror=implicit-function-declaration]
release_pages(pages, npinned);
^~~~~~~~~~~~~
release_taskcc1: some warnings being treated as errors
vim +648 drivers//vhost/vhost.c
619
620 static int vhost_init_vmap(struct vhost_vmap *map, unsigned long uaddr,
621 size_t size, int write)
622 {
623 struct page **pages;
624 int npages = DIV_ROUND_UP(size, PAGE_SIZE);
625 int npinned;
626 void *vaddr;
627
628 pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
629 if (!pages)
630 return -ENOMEM;
631
632 npinned = get_user_pages_fast(uaddr, npages, write, pages);
633 if (npinned != npages)
634 goto err;
635
636 vaddr = vmap(pages, npages, VM_MAP, PAGE_KERNEL);
637 if (!vaddr)
638 goto err;
639
640 map->pages = pages;
641 map->addr = vaddr + (uaddr & (PAGE_SIZE - 1));
642 map->npages = npages;
643
644 return 0;
645
646 err:
647 if (npinned > 0)
> 648 release_pages(pages, npinned);
649 kfree(pages);
650 return -EFAULT;
651 }
652
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
PATCH 3/3 vhost: access vq metadata through kernel virtual address
In reply to Jason WangIt was noticed that the copy_user() friends that was used to access virtqueue metdata tends to be very expensive for dataplane implementation like vhost since it involves lots of software check, speculation barrier, hardware feature toggling (e.g SMAP). The extra cost will be more obvious when transferring small packets.
This patch tries to eliminate those overhead by pin vq metadata pages and access them through vmap(). During SET_VRING_ADDR, we will setup those mappings and memory accessors are modified to use pointers to access the metadata directly.
Note, this was only done when device IOTLB is not enabled. We could use similar method to optimize it in the future.
Tests shows about ~24% improvement on TX PPS when using virtio-user + vhost_net + xdp1 on TAP (CONFIG_HARDENED_USERCOPY is not enabled):
Before: ~5.0Mpps After: ~6.1Mpps
--- drivers/vhost/vhost.c | 178 ++++++++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost.h | 11 +++ 2 files changed, 189 insertions(+)
drivers/vhost/vhost.c +178 -0
@@ -443,6 +443,9 @@ void vhost_dev_init(struct vhost_dev *dev, vq->indirect =NULL ; vq->heads =NULL ; vq->dev = dev; +memset (&vq->avail_ring,0 ,sizeof (vq->avail_ring)); +memset (&vq->used_ring,0 ,sizeof (vq->used_ring)); +memset (&vq->desc_ring,0 ,sizeof (vq->desc_ring));mutex_init (&vq->mutex);vhost_vq_reset (dev, vq);if (vq->handle_kick)
@@ -614,6 +617,102 @@ static void vhost_clear_msg(struct vhost_dev *dev)spin_unlock (&dev->iotlb_lock); } +static int vhost_init_vmap (struct vhost_vmap *map,unsigned long uaddr, +size_t size,int write) +{ +struct page **pages; +int npages =DIV_ROUND_UP (size,PAGE_SIZE ); +int npinned; +void *vaddr; + + pages =kmalloc_array (npages,sizeof (struct page *),GFP_KERNEL ); +if (!pages) +return -ENOMEM ; + + npinned =get_user_pages_fast (uaddr, npages, write, pages); +if (npinned != npages) + goto err; + + vaddr =vmap (pages, npages,VM_MAP ,PAGE_KERNEL ); +if (!vaddr) + goto err; + + map->pages = pages; + map->addr = vaddr + (uaddr & (PAGE_SIZE -1 )); + map->npages = npages; + +return 0 ; + +err: +if (npinned >0 ) +release_pages (pages, npinned); +kfree (pages); +return -EFAULT ; +} + +static void vhost_uninit_vmap (struct vhost_vmap *map) +{ +if (!map->addr) +return ; + +vunmap (map->addr); +release_pages (map->pages, map->npages); +kfree (map->pages); + + map->addr =NULL ; + map->pages =NULL ; + map->npages =0 ; +} + +static void vhost_clean_vmaps (struct vhost_virtqueue *vq) +{ +vhost_uninit_vmap (&vq->avail_ring); +vhost_uninit_vmap (&vq->desc_ring); +vhost_uninit_vmap (&vq->used_ring); +} + +static int vhost_setup_vmaps (struct vhost_virtqueue *vq,unsigned long avail, +unsigned long desc,unsigned long used) +{ +size_t event =vhost_has_feature (vq,VIRTIO_RING_F_EVENT_IDX ) ?2 :0 ; +size_t avail_size, desc_size, used_size; +int ret; + +vhost_clean_vmaps (vq); + + avail_size =sizeof (*vq->avail) + +sizeof (*vq->avail->ring) * vq->num + event; + ret =vhost_init_vmap (&vq->avail_ring, avail, avail_size, false); +if (ret) { +vq_err (vq,"Fail to setup vmap for avail ring!\n" ); + goto err_avail; + } + + desc_size =sizeof (*vq->desc) * vq->num; + ret =vhost_init_vmap (&vq->desc_ring, desc, desc_size, false); +if (ret) { +vq_err (vq,"Fail to setup vmap for desc ring!\n" ); + goto err_desc; + } + + used_size =sizeof (*vq->used) + +sizeof (*vq->used->ring) * vq->num + event; + ret =vhost_init_vmap (&vq->used_ring, used, used_size, true); +if (ret) { +vq_err (vq,"Fail to setup vmap for used ring!\n" ); + goto err_used; + } + +return 0 ; + +err_used: +vhost_uninit_vmap (&vq->used_ring); +err_desc: +vhost_uninit_vmap (&vq->avail_ring); +err_avail: +return -EFAULT ; +} +void vhost_dev_cleanup (struct vhost_dev *dev) {int i;
@@ -626,6 +725,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev)if (dev->vqs[i]->call_ctx)eventfd_ctx_put (dev->vqs[i]->call_ctx);vhost_vq_reset (dev, dev->vqs[i]); +vhost_clean_vmaps (dev->vqs[i]); }vhost_dev_free_iovecs (dev);if (dev->log_ctx)
@@ -873,6 +973,14 @@ static inline void __user *__vhost_get_user(struct vhost_virtqueue *vq,static inline int vhost_put_avail_event (struct vhost_virtqueue *vq) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + *((__virtio16 *)&used->ring[vq->num]) = +cpu_to_vhost16 (vq, vq->avail_idx); +return 0 ; + } +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->avail_idx),vhost_avail_event (vq)); }
@@ -881,6 +989,13 @@ static inline int vhost_put_used(struct vhost_virtqueue *vq, struct vring_used_elem *head, int idx, int count) { + if (!vq->iotlb) { + struct vring_used *used = vq->used_ring.addr; + +memcpy (used->ring + idx, head, count *sizeof (*head)); +return 0 ; + } +return vhost_copy_to_user (vq, vq->used->ring + idx, head, count *sizeof (*head)); }
@@ -888,6 +1003,13 @@ static inline int vhost_put_used(struct vhost_virtqueue *vq,static inline int vhost_put_used_flags (struct vhost_virtqueue *vq) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + used->flags =cpu_to_vhost16 (vq, vq->used_flags); +return 0 ; + } +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->used_flags), &vq->used->flags); }
@@ -895,6 +1017,13 @@ static inline int vhost_put_used_flags(struct vhost_virtqueue *vq)static inline int vhost_put_used_idx (struct vhost_virtqueue *vq) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + used->idx =cpu_to_vhost16 (vq, vq->last_used_idx); +return 0 ; + } +return vhost_put_user (vq,cpu_to_vhost16 (vq, vq->last_used_idx), &vq->used->idx); }
@@ -926,12 +1055,26 @@ static inline int vhost_put_used_idx(struct vhost_virtqueue *vq)static inline int vhost_get_avail_idx (struct vhost_virtqueue *vq,__virtio16 *idx) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *idx = avail->idx; +return 0 ; + } +return vhost_get_avail (vq, *idx, &vq->avail->idx); }static inline int vhost_get_avail_head (struct vhost_virtqueue *vq,__virtio16 *head,int idx) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *head = avail->ring[idx & (vq->num -1 )]; +return 0 ; + } +return vhost_get_avail (vq, *head, &vq->avail->ring[idx & (vq->num -1 )]); }
@@ -939,24 +1082,52 @@ static inline int vhost_get_avail_head(struct vhost_virtqueue *vq,static inline int vhost_get_avail_flags (struct vhost_virtqueue *vq,__virtio16 *flags) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *flags = avail->flags; +return 0 ; + } +return vhost_get_avail (vq, *flags, &vq->avail->flags); }static inline int vhost_get_used_event (struct vhost_virtqueue *vq,__virtio16 *event) { +if (!vq->iotlb) { +struct vring_avail *avail = vq->avail_ring.addr; + + *event = (__virtio16 )avail->ring[vq->num]; +return 0 ; + } +return vhost_get_avail (vq, *event,vhost_used_event (vq)); }static inline int vhost_get_used_idx (struct vhost_virtqueue *vq,__virtio16 *idx) { +if (!vq->iotlb) { +struct vring_used *used = vq->used_ring.addr; + + *idx = used->idx; +return 0 ; + } +return vhost_get_used (vq, *idx, &vq->used->idx); }static inline int vhost_get_desc (struct vhost_virtqueue *vq,struct vring_desc *desc,int idx) { +if (!vq->iotlb) { +struct vring_desc *d = vq->desc_ring.addr; + + *desc = *(d + idx); +return 0 ; + } +return vhost_copy_from_user (vq, desc, vq->desc + idx,sizeof (*desc)); }
@@ -1551,6 +1722,13 @@ long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *arg } } +if (!vq->iotlb &&vhost_setup_vmaps (vq, a.avail_user_addr, + a.desc_user_addr, + a.used_user_addr)) { + r = -EINVAL ; +break ; + } + vq->log_used = !!(a.flags & (0x1 <<VHOST_VRING_F_LOG )); vq->desc = (void __user *)(unsigned long )a.desc_user_addr; vq->avail = (void __user *)(unsigned long )a.avail_user_addr;
drivers/vhost/vhost.h +11 -0
@@ -80,6 +80,12 @@ enum vhost_uaddr_type { VHOST_NUM_ADDRS = 3, }; +struct vhost_vmap { +struct page **pages; +void *addr; +int npages; +}; +/* The virtqueue structure describes a queue attached to a device. */ struct vhost_virtqueue {struct vhost_dev *dev;
@@ -90,6 +96,11 @@ struct vhost_virtqueue {struct vring_desc __user *desc;struct vring_avail __user *avail;struct vring_used __user *used; + +struct vhost_vmap avail_ring; +struct vhost_vmap desc_ring; +struct vhost_vmap used_ring; +const struct vhost_umem_node *meta_iotlb[VHOST_NUM_ADDRS ];struct file *kick;struct eventfd_ctx *call_ctx;
Signature · 1 line
2.17.1
Michael S. Tsirkin
maintainerQuoted 6 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.
Userspace accesses through remapping tricks and next time there's a need for a new barrier we are left to figure it out by ourselves. I don't like the idea I have to say. As a first step, why don't we switch to unsafe_put_user/unsafe_get_user etc?
That would be more of an apples to apples comparison, would it not?
Quoted 16 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual addressdrivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1
Quoted 9 lines · Michael S. Tsirkin
Quoted 6 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Userspace accesses through remapping tricks and next time there's a need for a new barrier we are left to figure it out by ourselves.
I don't get here, do you mean spec barriers? It's completely unnecessary for vhost which is kernel thread. And even if you're right, vhost is not the only place, there's lots of vmap() based accessing in kernel. Think in another direction, this means we won't suffer form unnecessary barriers for kthread like vhost in the future, we will manually pick the one we really need (but it should have little possibility).
Please notice we only access metdata through remapping not the data itself. This idea has been used for high speed userspace backend for years, e.g packet socket or recent AF_XDP. The only difference is the page was remap to from kernel to userspace.
Quoted 3 lines
I don't
like the idea I have to say. As a first step, why don't we switch to unsafe_put_user/unsafe_get_user etc?
Several reasons:
- They only have x86 variant, it won't have any difference for the rest of architecture.
- unsafe_put_user/unsafe_get_user is not sufficient for accessing structures (e.g accessing descriptor) or arrays (batching).
- Unless we can batch at least the accessing of two places in three of avail, used and descriptor in one run. There will be no difference. E.g we can batch updating used ring, but it won't make any difference in this case.
Quoted 1 line
That would be more of an apples to apples comparison, would it not?
Apples to apples comparison only help if we are the No.1. But the fact is we are not. If we want to compete with e.g dpdk or AF_XDP, vmap() is the fastest method AFAIK.
Thanks
Quoted 18 lines
Quoted 18 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual addressdrivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1
Michael S. Tsirkin
maintainerQuoted 9 lines · Jason Wang
Quoted 7 lines · Michael S. Tsirkin
Quoted 6 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.
Quoted 5 lines
Quoted 2 lines
Userspace accesses through remapping tricks and next time there's a need for a new barrier we are left to figure it out by ourselves.
I don't get here, do you mean spec barriers?
I mean the next barrier people decide to put into userspace memory accesses.
Quoted 2 lines
It's completely unnecessary for
vhost which is kernel thread.
It's defence in depth. Take a look at the commit that added them. And yes quite possibly in most cases we actually have a spec barrier in the validation phase. If we do let's use the unsafe variants so they can be found.
Quoted 2 lines
And even if you're right, vhost is not the
only place, there's lots ofvmap()based accessing in kernel.
For sure. But if one can get by without get user pages, one really should. Witness recently uncovered mess with file backed storage.
Quoted 4 lines
Think in
another direction, this means we won't suffer form unnecessary barriers for kthread like vhost in the future, we will manually pick the one we really need
I personally think we should err on the side of caution not on the side of performance.
Quoted 1 line
(but it should have little possibility).
History seems to teach otherwise.
Quoted 3 lines
Please notice we only access metdata through remapping not the data itself. This idea has been used for high speed userspace backend for years, e.g packet socket or recent
AF_XDP.
I think their justification for the higher risk is that they are mostly designed for priveledged userspace.
Quoted 2 lines
The only difference is the page was remap to
from kernel to userspace.
At least that avoids the g.u.p mess.
Quoted 10 lines
Quoted 4 lines
I don't
like the idea I have to say. As a first step, why don't we switch to unsafe_put_user/unsafe_get_user etc?Several reasons:
- They only have x86 variant, it won't have any difference for the rest of architecture.
Is there an issue on other architectures? If yes they can be extended there.
Quoted 2 lines
- unsafe_put_user/unsafe_get_user is not sufficient for accessing structures (e.g accessing descriptor) or arrays (batching).
So you want unsafe_copy_xxx_user? I can do this. Hang on will post.
Quoted 4 lines
- Unless we can batch at least the accessing of two places in three of avail, used and descriptor in one run. There will be no difference. E.g we can batch updating used ring, but it won't make any difference in this case.
So let's batch them all?
Quoted 9 lines
Quoted 1 line
That would be more of an apples to apples comparison, would it not?
Apples to apples comparison only help if we are the No.1. But the fact is we are not. If we want to compete with e.g dpdk or
AF_XDP,vmap()is the fastest method AFAIK.Thanks
We need to speed up the packet access itself too though. You can't vmap all of guest memory.
Quoted 19 lines
Quoted 19 lines
Quoted 19 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual addressdrivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1
Michael S. Tsirkin
maintainerQuoted 4 lines · Michael S. Tsirkin
Quoted 2 lines
- unsafe_put_user/unsafe_get_user is not sufficient for accessing structures (e.g accessing descriptor) or arrays (batching).
So you want
unsafe_copy_xxx_user? I can do this. Hang on will post.
Like this basically? Warning: completely untested.
arch/x86/include/asm/uaccess.h +5 -0
@@ -728,5 +728,10 @@ do { \if (unlikely (__gu_err)) goto err_label; \ } while (0) +#define unsafe_copy_from_user (to, from, n) \ + __copy_user_ll(to, (__force const void *)from, n) +#define unsafe_copy_to_user (to, from, n) \ + __copy_user_ll((__force void *)to, from, n) +#endif /* _ASM_X86_UACCESS_H */
include/linux/uaccess.h +2 -0
@@ -271,6 +271,8 @@ extern long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count);#define user_access_end () do { } while (0)#define unsafe_get_user (x, ptr, err) do { if (unlikely(__get_user(x, ptr))) goto err; } while (0)#define unsafe_put_user (x, ptr, err) do { if (unlikely(__put_user(x, ptr))) goto err; } while (0) +#define unsafe_copy_to_user (from, to, n) copy_to_user(from, to, n) +#define unsafe_copy_from_user (from, to, n) copy_from_user(from, to, n)#endif #ifdef CONFIG_HARDENED_USERCOPY
Michael S. Tsirkin
maintainerQuoted 4 lines · Michael S. Tsirkin
Quoted 2 lines
- unsafe_put_user/unsafe_get_user is not sufficient for accessing structures (e.g accessing descriptor) or arrays (batching).
So you want
unsafe_copy_xxx_user? I can do this. Hang on will post.
Like this basically? Warning: completely untested.
arch/x86/include/asm/uaccess.h +5 -0
@@ -728,5 +728,10 @@ do { \if (unlikely (__gu_err)) goto err_label; \ } while (0) +#define unsafe_copy_from_user (to, from, n) \ + __copy_user_ll(to, (__force const void *)from, n) +#define unsafe_copy_to_user (to, from, n) \ + __copy_user_ll((__force void *)to, from, n) +#endif /* _ASM_X86_UACCESS_H */
include/linux/uaccess.h +2 -0
@@ -271,6 +271,8 @@ extern long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count);#define user_access_end () do { } while (0)#define unsafe_get_user (x, ptr, err) do { if (unlikely(__get_user(x, ptr))) goto err; } while (0)#define unsafe_put_user (x, ptr, err) do { if (unlikely(__put_user(x, ptr))) goto err; } while (0) +#define unsafe_copy_to_user (from, to, n) copy_to_user(from, to, n) +#define unsafe_copy_from_user (from, to, n) copy_from_user(from, to, n)#endif #ifdef CONFIG_HARDENED_USERCOPY
Quoted 16 lines · Michael S. Tsirkin
Quoted 4 lines · Jason Wang
Quoted 3 lines · Michael S. Tsirkin
Quoted 2 lines · Jason Wang
Hi:
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Userspace accesses through remapping tricks and next time there's a need for a new barrier we are left to figure it out by ourselves.
I don't get here, do you mean spec barriers?
I mean the next barrier people decide to put into userspace memory accesses.
Quoted 6 lines
Quoted 2 lines
It's completely unnecessary for
vhost which is kernel thread.It's defence in depth. Take a look at the commit that added them. And yes quite possibly in most cases we actually have a spec barrier in the validation phase. If we do let's use the unsafe variants so they can be found.
unsafe variants can only work if you can batch userspace access. This is not necessarily the case for light load.
Quoted 6 lines
Quoted 3 lines
And even if you're right, vhost is not the
only place, there's lots ofvmap()based accessing in kernel.For sure. But if one can get by without get user pages, one really should. Witness recently uncovered mess with file backed storage.
We only pin metadata pages, I don't believe they will be used by any DMA.
Quoted 7 lines
Quoted 5 lines
Think in
another direction, this means we won't suffer form unnecessary barriers for kthread like vhost in the future, we will manually pick the one we really needI personally think we should err on the side of caution not on the side of performance.
So what you suggest may lead unnecessary performance regression (10%-20%) which is part of the goal of this series. We should audit and only use the one we really need instead of depending on copy_user() friends().
If we do it our own, it could be slow for for security fix but it's no less safe than before with performance kept.
Quoted 3 lines
Quoted 2 lines
(but it should have little possibility).
History seems to teach otherwise.
What case did you mean here?
Quoted 6 lines
Quoted 4 lines
Please notice we only access metdata through remapping not the data itself. This idea has been used for high speed userspace backend for years, e.g packet socket or recent
AF_XDP.I think their justification for the higher risk is that they are mostly designed for priveledged userspace.
I think it's the same with TUN/TAP, privileged process can pass them to unprivileged ones.
Quoted 4 lines
Quoted 3 lines
The only difference is the page was remap to
from kernel to userspace.At least that avoids the g.u.p mess.
I'm still not very clear at the point. We only pin 2 or 4 pages, they're several other cases that will pin much more.
Quoted 11 lines
Quoted 9 lines
Quoted 4 lines
I don't
like the idea I have to say. As a first step, why don't we switch to unsafe_put_user/unsafe_get_user etc?Several reasons:
- They only have x86 variant, it won't have any difference for the rest of architecture.
Is there an issue on other architectures? If yes they can be extended there.
Consider the unexpected amount of work and in the best case it can give the same performance to vmap(). I'm not sure it's worth.
Quoted 10 lines
Quoted 3 lines
- unsafe_put_user/unsafe_get_user is not sufficient for accessing structures (e.g accessing descriptor) or arrays (batching).
So you want
unsafe_copy_xxx_user? I can do this. Hang on will post.Quoted 4 lines
- Unless we can batch at least the accessing of two places in three of avail, used and descriptor in one run. There will be no difference. E.g we can batch updating used ring, but it won't make any difference in this case.
So let's batch them all?
Batching might not help for the case of light load. And we need to measure the gain/cost of batching itself.
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
That would be more of an apples to apples comparison, would it not?
Quoted 8 lines
Quoted 6 lines
Apples to apples comparison only help if we are the No.1. But the fact is we are not. If we want to compete with e.g dpdk or
AF_XDP,vmap()is the fastest method AFAIK.Thanks
We need to speed up the packet access itself too though. You can't vmap all of guest memory.
This series only pin and vmap very few pages (metadata).
Thanks
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual address
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
drivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Michael S. Tsirkin
maintainerQuoted 20 lines · Jason Wang
Quoted 18 lines · Michael S. Tsirkin
Quoted 4 lines · Jason Wang
Quoted 3 lines · Michael S. Tsirkin
Quoted 2 lines · Jason Wang
Hi:
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Userspace accesses through remapping tricks and next time there's a need for a new barrier we are left to figure it out by ourselves.
I don't get here, do you mean spec barriers?
I mean the next barrier people decide to put into userspace memory accesses.
Quoted 2 lines
It's completely unnecessary for
vhost which is kernel thread.
Quoted 8 lines
Quoted 4 lines
It's defence in depth. Take a look at the commit that added them. And yes quite possibly in most cases we actually have a spec barrier in the validation phase. If we do let's use the unsafe variants so they can be found.
unsafe variants can only work if you can batch userspace access. This is not necessarily the case for light load.
Do we care a lot about the light load? How would you benchmark it?
Quoted 10 lines
Quoted 7 lines
Quoted 4 lines
And even if you're right, vhost is not the
only place, there's lots ofvmap()based accessing in kernel.For sure. But if one can get by without get user pages, one really should. Witness recently uncovered mess with file backed storage.
We only pin metadata pages, I don't believe they will be used by any DMA.
It doesn't matter really, if you dirty pages behind the MM back the problem is there.
Quoted 90 lines
Quoted 8 lines
Quoted 6 lines
Think in
another direction, this means we won't suffer form unnecessary barriers for kthread like vhost in the future, we will manually pick the one we really needI personally think we should err on the side of caution not on the side of performance.
So what you suggest may lead unnecessary performance regression (10%-20%) which is part of the goal of this series. We should audit and only use the one we really need instead of depending on
copy_user()friends().If we do it our own, it could be slow for for security fix but it's no less safe than before with performance kept.
Quoted 3 lines
Quoted 2 lines
(but it should have little possibility).
History seems to teach otherwise.
What case did you mean here?
Quoted 6 lines
Quoted 4 lines
Please notice we only access metdata through remapping not the data itself. This idea has been used for high speed userspace backend for years, e.g packet socket or recent
AF_XDP.I think their justification for the higher risk is that they are mostly designed for priveledged userspace.
I think it's the same with TUN/TAP, privileged process can pass them to unprivileged ones.
Quoted 4 lines
Quoted 3 lines
The only difference is the page was remap to
from kernel to userspace.At least that avoids the g.u.p mess.
I'm still not very clear at the point. We only pin 2 or 4 pages, they're several other cases that will pin much more.
Quoted 11 lines
Quoted 9 lines
Quoted 4 lines
I don't
like the idea I have to say. As a first step, why don't we switch to unsafe_put_user/unsafe_get_user etc?Several reasons:
- They only have x86 variant, it won't have any difference for the rest of architecture.
Is there an issue on other architectures? If yes they can be extended there.
Consider the unexpected amount of work and in the best case it can give the same performance to
vmap(). I'm not sure it's worth.Quoted 10 lines
Quoted 3 lines
- unsafe_put_user/unsafe_get_user is not sufficient for accessing structures (e.g accessing descriptor) or arrays (batching).
So you want
unsafe_copy_xxx_user? I can do this. Hang on will post.Quoted 4 lines
- Unless we can batch at least the accessing of two places in three of avail, used and descriptor in one run. There will be no difference. E.g we can batch updating used ring, but it won't make any difference in this case.
So let's batch them all?
Batching might not help for the case of light load. And we need to measure the gain/cost of batching itself.
Quoted 9 lines
Quoted 9 lines
Quoted 3 lines
That would be more of an apples to apples comparison, would it not?
Apples to apples comparison only help if we are the No.1. But the fact is we are not. If we want to compete with e.g dpdk or
AF_XDP,vmap()is the fastest method AFAIK.
Quoted 29 lines
Quoted 3 lines
Quoted 1 line
Thanks
We need to speed up the packet access itself too though. You can't vmap all of guest memory.
This series only pin and vmap very few pages (metadata).
Thanks
Quoted 19 lines
Quoted 19 lines
Quoted 19 lines
Quoted 19 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual addressdrivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Quoted 24 lines · Michael S. Tsirkin
Quoted 23 lines · Jason Wang
Quoted 21 lines · Michael S. Tsirkin
Quoted 11 lines · Jason Wang
Quoted 9 lines · Michael S. Tsirkin
Quoted 6 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Userspace accesses through remapping tricks and next time there's a need for a new barrier we are left to figure it out by ourselves.
I don't get here, do you mean spec barriers?
I mean the next barrier people decide to put into userspace memory accesses.
Quoted 2 lines
It's completely unnecessary for
vhost which is kernel thread.It's defence in depth. Take a look at the commit that added them. And yes quite possibly in most cases we actually have a spec barrier in the validation phase. If we do let's use the unsafe variants so they can be found.
Quoted 5 lines
Quoted 2 lines
unsafe variants can only work if you can batch userspace access. This is not necessarily the case for light load.
Do we care a lot about the light load? How would you benchmark it?
If we can reduce the latency that's will be more than what we expect.
1 byte TCP_RR shows 1.5%-2% improvement.
Quoted 9 lines
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
And even if you're right, vhost is not the
only place, there's lots ofvmap()based accessing in kernel.For sure. But if one can get by without get user pages, one really should. Witness recently uncovered mess with file backed storage.
We only pin metadata pages, I don't believe they will be used by any DMA.
It doesn't matter really, if you dirty pages behind the MM back the problem is there.
Ok, but the usual case is anonymous pages, do we use file backed pages for user of vhost? And even if we use sometime, according to the pointer it's not something that can fix, RFC has been posted to solve this issue.
Thanks
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Michael S. Tsirkin
maintainerQuoted 29 lines · Jason Wang
Quoted 27 lines · Michael S. Tsirkin
Quoted 25 lines · Jason Wang
Quoted 15 lines · Michael S. Tsirkin
Quoted 11 lines · Jason Wang
Quoted 9 lines · Michael S. Tsirkin
Quoted 6 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Userspace accesses through remapping tricks and next time there's a need for a new barrier we are left to figure it out by ourselves.
I don't get here, do you mean spec barriers?
I mean the next barrier people decide to put into userspace memory accesses.
Quoted 6 lines
Quoted 2 lines
It's completely unnecessary for
vhost which is kernel thread.It's defence in depth. Take a look at the commit that added them. And yes quite possibly in most cases we actually have a spec barrier in the validation phase. If we do let's use the unsafe variants so they can be found.
unsafe variants can only work if you can batch userspace access. This is not necessarily the case for light load.
Quoted 6 lines
Quoted 2 lines
Do we care a lot about the light load? How would you benchmark it?
If we can reduce the latency that's will be more than what we expect.
1 byte
TCP_RRshows 1.5%-2% improvement.
It's nice but not great. E.g. adaptive polling would be a better approach to work on latency imho.
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
Quoted 3 lines
And even if you're right, vhost is not the
only place, there's lots ofvmap()based accessing in kernel.For sure. But if one can get by without get user pages, one really should. Witness recently uncovered mess with file backed storage.
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
We only pin metadata pages, I don't believe they will be used by any DMA.
It doesn't matter really, if you dirty pages behind the MM back the problem is there.
Ok, but the usual case is anonymous pages, do we use file backed pages for user of vhost?
Some people use file backed pages for vms. Nothing prevents them from using vhost as well.
Quoted 4 lines
And even if we use sometime, according to the pointer it's not something that can fix, RFC has been posted to solve this issue.
Thanks
Except it's not broken if we don't to gup + write. So yea, wait for rfc to be merged.
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Quoted 27 lines · Michael S. Tsirkin
Quoted 26 lines · Jason Wang
Quoted 25 lines · Michael S. Tsirkin
Quoted 24 lines · Jason Wang
Quoted 15 lines · Michael S. Tsirkin
Quoted 11 lines · Jason Wang
Quoted 9 lines · Michael S. Tsirkin
Quoted 6 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Userspace accesses through remapping tricks and next time there's a need for a new barrier we are left to figure it out by ourselves.
I don't get here, do you mean spec barriers?
I mean the next barrier people decide to put into userspace memory accesses.
Quoted 6 lines
Quoted 2 lines
It's completely unnecessary for
vhost which is kernel thread.It's defence in depth. Take a look at the commit that added them. And yes quite possibly in most cases we actually have a spec barrier in the validation phase. If we do let's use the unsafe variants so they can be found.
unsafe variants can only work if you can batch userspace access. This is not necessarily the case for light load.
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
Do we care a lot about the light load? How would you benchmark it?
If we can reduce the latency that's will be more than what we expect.
1 byte
TCP_RRshows 1.5%-2% improvement.It's nice but not great. E.g. adaptive polling would be a better approach to work on latency imho.
Actually this is another advantages of vmap():
For split ring, we will poll avail idx
For packed ring, we will poll wrap counter
Either of which can not be batched.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 3 lines
And even if you're right, vhost is not the
only place, there's lots ofvmap()based accessing in kernel.For sure. But if one can get by without get user pages, one really should. Witness recently uncovered mess with file backed storage.
Quoted 8 lines
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
We only pin metadata pages, I don't believe they will be used by any DMA.
It doesn't matter really, if you dirty pages behind the MM back the problem is there.
Ok, but the usual case is anonymous pages, do we use file backed pages for user of vhost?
Some people use file backed pages for vms. Nothing prevents them from using vhost as well.
Ok.
Quoted 8 lines
Quoted 5 lines
And even if we use sometime, according to the pointer it's not something that can fix, RFC has been posted to solve this issue.
Thanks
Except it's not broken if we don't to gup + write. So yea, wait for rfc to be merged.
Yes.
Thanks
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Michael S. Tsirkin
maintainerQuoted 9 lines · Jason Wang
Quoted 7 lines · Michael S. Tsirkin
Quoted 6 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.
Quoted 5 lines
Quoted 2 lines
Userspace accesses through remapping tricks and next time there's a need for a new barrier we are left to figure it out by ourselves.
I don't get here, do you mean spec barriers?
I mean the next barrier people decide to put into userspace memory accesses.
Quoted 2 lines
It's completely unnecessary for
vhost which is kernel thread.
It's defence in depth. Take a look at the commit that added them. And yes quite possibly in most cases we actually have a spec barrier in the validation phase. If we do let's use the unsafe variants so they can be found.
Quoted 2 lines
And even if you're right, vhost is not the
only place, there's lots ofvmap()based accessing in kernel.
For sure. But if one can get by without get user pages, one really should. Witness recently uncovered mess with file backed storage.
Quoted 4 lines
Think in
another direction, this means we won't suffer form unnecessary barriers for kthread like vhost in the future, we will manually pick the one we really need
I personally think we should err on the side of caution not on the side of performance.
Quoted 1 line
(but it should have little possibility).
History seems to teach otherwise.
Quoted 3 lines
Please notice we only access metdata through remapping not the data itself. This idea has been used for high speed userspace backend for years, e.g packet socket or recent
AF_XDP.
I think their justification for the higher risk is that they are mostly designed for priveledged userspace.
Quoted 2 lines
The only difference is the page was remap to
from kernel to userspace.
At least that avoids the g.u.p mess.
Quoted 10 lines
Quoted 4 lines
I don't
like the idea I have to say. As a first step, why don't we switch to unsafe_put_user/unsafe_get_user etc?Several reasons:
- They only have x86 variant, it won't have any difference for the rest of architecture.
Is there an issue on other architectures? If yes they can be extended there.
Quoted 2 lines
- unsafe_put_user/unsafe_get_user is not sufficient for accessing structures (e.g accessing descriptor) or arrays (batching).
So you want unsafe_copy_xxx_user? I can do this. Hang on will post.
Quoted 4 lines
- Unless we can batch at least the accessing of two places in three of avail, used and descriptor in one run. There will be no difference. E.g we can batch updating used ring, but it won't make any difference in this case.
So let's batch them all?
Quoted 9 lines
Quoted 1 line
That would be more of an apples to apples comparison, would it not?
Apples to apples comparison only help if we are the No.1. But the fact is we are not. If we want to compete with e.g dpdk or
AF_XDP,vmap()is the fastest method AFAIK.Thanks
We need to speed up the packet access itself too though. You can't vmap all of guest memory.
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual address
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
drivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Quoted 9 lines · Michael S. Tsirkin
Quoted 6 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Userspace accesses through remapping tricks and next time there's a need for a new barrier we are left to figure it out by ourselves.
I don't get here, do you mean spec barriers? It's completely unnecessary for vhost which is kernel thread. And even if you're right, vhost is not the only place, there's lots of vmap() based accessing in kernel. Think in another direction, this means we won't suffer form unnecessary barriers for kthread like vhost in the future, we will manually pick the one we really need (but it should have little possibility).
Please notice we only access metdata through remapping not the data itself. This idea has been used for high speed userspace backend for years, e.g packet socket or recent AF_XDP. The only difference is the page was remap to from kernel to userspace.
Quoted 3 lines
I don't
like the idea I have to say. As a first step, why don't we switch to unsafe_put_user/unsafe_get_user etc?
Several reasons:
- They only have x86 variant, it won't have any difference for the rest of architecture.
- unsafe_put_user/unsafe_get_user is not sufficient for accessing structures (e.g accessing descriptor) or arrays (batching).
- Unless we can batch at least the accessing of two places in three of avail, used and descriptor in one run. There will be no difference. E.g we can batch updating used ring, but it won't make any difference in this case.
Quoted 1 line
That would be more of an apples to apples comparison, would it not?
Apples to apples comparison only help if we are the No.1. But the fact is we are not. If we want to compete with e.g dpdk or AF_XDP, vmap() is the fastest method AFAIK.
Thanks
Quoted 12 lines
Quoted 12 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual address
Quoted 6 lines
Quoted 6 lines
drivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Michael S. Tsirkin
maintainerQuoted 6 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.
Userspace accesses through remapping tricks and next time there's a need for a new barrier we are left to figure it out by ourselves. I don't like the idea I have to say. As a first step, why don't we switch to unsafe_put_user/unsafe_get_user etc?
That would be more of an apples to apples comparison, would it not?
Quoted 16 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual addressdrivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1
Michael S. Tsirkin
maintainerQuoted 11 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
I think the idea of speeding up userspace access is a good one. However I think that moving all checks to start is way too aggressive. Instead, let's batch things up but let's not keep them around forever.
Here are some ideas:
1. Disable preemption, process a small number of small packets directly in an atomic context. This should cut latency down significantly, the tricky part is to only do it on a light load and disable this
for the streaming case otherwise it's unfair. This might fail, if it does just bounce things out to a thread.
2. Switch to unsafe_put_user/unsafe_get_user,
and batch up multiple accesses.
3. Allow adding a fixup point manually,
such that multiple independent get_user accesses can get a single fixup (will allow better compiler optimizations).
Quoted 11 lines
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual addressdrivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1
Quoted 8 lines · Michael S. Tsirkin
Quoted 7 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.
Quoted 6 lines
Quoted 4 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
I think the idea of speeding up userspace access is a good one. However I think that moving all checks to start is way too aggressive.
So did packet and AF_XDP. Anyway, sharing address space and access them directly is the fastest way. Performance is the major consideration for people to choose backend. Compare to userspace implementation, vhost does not have security advantages at any level. If vhost is still slow, people will start to develop backends based on e.g AF_XDP.
Quoted 5 lines
Instead, let's batch things up but let's not keep them around forever.
Here are some ideas:
Quoted 7 lines
1. Disable preemption, process a small number of small packets directly in an atomic context. This should cut latency down significantly, the tricky part is to only do it on a light load and disable this
for the streaming case otherwise it's unfair. This might fail, if it does just bounce things out to a thread.
I'm not sure what context you meant here. Is this for TX path of TUN? But a fundamental difference is my series is targeted for extreme heavy load not light one, 100% cpu for vhost is expected.
Quoted 3 lines
2. Switch to unsafe_put_user/unsafe_get_user,
and batch up multiple accesses.
As I said, unless we can batch accessing of two difference places of three of avail, descriptor and used. It won't help for batching the accessing of a single place like used. I'm even not sure this can be done consider the case of packed virtqueue, we have a single descriptor ring. Batching through unsafe helpers may not help in this case since it's equivalent to safe ones . And This requires non trivial refactoring of vhost. And such refactoring itself make give us noticeable impact (e.g it may lead regression).
Quoted 6 lines
3. Allow adding a fixup point manually,
such that multiple independentget_useraccesses can get a single fixup (will allow better compiler optimizations).
So for metadata access, I don't see how you suggest here can help in the case of heavy workload.
For data access, this may help but I've played to batch the data copy to reduce SMAP/spec barriers in vhost-net but I don't see performance improvement.
Thanks
Quoted 14 lines
Quoted 14 lines
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual addressdrivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1
Michael S. Tsirkin
maintainerQuoted 18 lines · Jason Wang
Quoted 8 lines · Michael S. Tsirkin
Quoted 7 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Quoted 6 lines
Quoted 4 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
I think the idea of speeding up userspace access is a good one. However I think that moving all checks to start is way too aggressive.
Quoted 6 lines
So did packet and
AF_XDP. Anyway, sharing address space and access them directly is the fastest way. Performance is the major consideration for people to choose backend. Compare to userspace implementation, vhost does not have security advantages at any level. If vhost is still slow, people will start to develop backends based on e.gAF_XDP.
Let them what's wrong with that?
Quoted 14 lines
Quoted 5 lines
Instead, let's batch things up but let's not keep them around forever.
Here are some ideas:Quoted 7 lines
1. Disable preemption, process a small number of small packets directly in an atomic context. This should cut latency down significantly, the tricky part is to only do it on a light load and disable this
for the streaming case otherwise it's unfair. This might fail, if it does just bounce things out to a thread.
Quoted 3 lines
I'm not sure what context you meant here. Is this for TX path of TUN? But a fundamental difference is my series is targeted for extreme heavy load not light one, 100% cpu for vhost is expected.
Interesting. You only shared a TCP RR result though. What's the performance gain in a heavy load case?
Quoted 10 lines
Quoted 4 lines
2. Switch to unsafe_put_user/unsafe_get_user,
and batch up multiple accesses.As I said, unless we can batch accessing of two difference places of three of avail, descriptor and used. It won't help for batching the accessing of a single place like used. I'm even not sure this can be done consider the case of packed virtqueue, we have a single descriptor ring.
So that's one of the reasons packed should be faster. Single access and you get the descriptor no messy redirects. Somehow your benchmarking so far didn't show a gain with vhost and packed though - do you know what's wrong?
Quoted 13 lines
Batching through
unsafe helpers may not help in this case since it's equivalent to safe ones . And This requires non trivial refactoring of vhost. And such refactoring itself make give us noticeable impact (e.g it may lead regression).Quoted 6 lines
3. Allow adding a fixup point manually,
such that multiple independentget_useraccesses can get a single fixup (will allow better compiler optimizations).
Quoted 8 lines
So for metadata access, I don't see how you suggest here can help in the case of heavy workload.
For data access, this may help but I've played to batch the data copy to reduce SMAP/spec barriers in vhost-net but I don't see performance improvement.
Thanks
So how about we try to figure what's going on actually? Can you drop the barriers and show the same gain? E.g. vmap does not use a huge page IIRC so in fact it can be slower than direct access. It's not a magic faster way.
Quoted 15 lines
Quoted 15 lines
Quoted 15 lines
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual addressdrivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1
Michael S. Tsirkin
maintainerQuoted 18 lines · Jason Wang
Quoted 8 lines · Michael S. Tsirkin
Quoted 7 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Quoted 6 lines
Quoted 4 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
I think the idea of speeding up userspace access is a good one. However I think that moving all checks to start is way too aggressive.
Quoted 6 lines
So did packet and
AF_XDP. Anyway, sharing address space and access them directly is the fastest way. Performance is the major consideration for people to choose backend. Compare to userspace implementation, vhost does not have security advantages at any level. If vhost is still slow, people will start to develop backends based on e.gAF_XDP.
Let them what's wrong with that?
Quoted 14 lines
Quoted 5 lines
Instead, let's batch things up but let's not keep them around forever.
Here are some ideas:Quoted 7 lines
1. Disable preemption, process a small number of small packets directly in an atomic context. This should cut latency down significantly, the tricky part is to only do it on a light load and disable this
for the streaming case otherwise it's unfair. This might fail, if it does just bounce things out to a thread.
Quoted 3 lines
I'm not sure what context you meant here. Is this for TX path of TUN? But a fundamental difference is my series is targeted for extreme heavy load not light one, 100% cpu for vhost is expected.
Interesting. You only shared a TCP RR result though. What's the performance gain in a heavy load case?
Quoted 10 lines
Quoted 4 lines
2. Switch to unsafe_put_user/unsafe_get_user,
and batch up multiple accesses.As I said, unless we can batch accessing of two difference places of three of avail, descriptor and used. It won't help for batching the accessing of a single place like used. I'm even not sure this can be done consider the case of packed virtqueue, we have a single descriptor ring.
So that's one of the reasons packed should be faster. Single access and you get the descriptor no messy redirects. Somehow your benchmarking so far didn't show a gain with vhost and packed though - do you know what's wrong?
Quoted 13 lines
Batching through
unsafe helpers may not help in this case since it's equivalent to safe ones . And This requires non trivial refactoring of vhost. And such refactoring itself make give us noticeable impact (e.g it may lead regression).Quoted 6 lines
3. Allow adding a fixup point manually,
such that multiple independentget_useraccesses can get a single fixup (will allow better compiler optimizations).
Quoted 8 lines
So for metadata access, I don't see how you suggest here can help in the case of heavy workload.
For data access, this may help but I've played to batch the data copy to reduce SMAP/spec barriers in vhost-net but I don't see performance improvement.
Thanks
So how about we try to figure what's going on actually? Can you drop the barriers and show the same gain? E.g. vmap does not use a huge page IIRC so in fact it can be slower than direct access. It's not a magic faster way.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual address
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
drivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
David Miller
maintainerFrom: Jason Wang <[email protected]>
Date: Fri, 14 Dec 2018 12:29:54 +0800
Quoted 18 lines · Michael S. Tsirkin
Quoted 8 lines · Jason Wang
Quoted 7 lines
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Quoted 6 lines
Quoted 4 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
I think the idea of speeding up userspace access is a good one. However I think that moving all checks to start is way too aggressive.
Quoted 6 lines
So did packet and
AF_XDP. Anyway, sharing address space and access them directly is the fastest way. Performance is the major consideration for people to choose backend. Compare to userspace implementation, vhost does not have security advantages at any level. If vhost is still slow, people will start to develop backends based on e.gAF_XDP.
Exactly, this is precisely how this kind of problem should be solved.
Michael, I strongly support the approach Jason is taking here, and I would like to ask you to seriously reconsider your objections.
Thank you.
Michael S. Tsirkin
maintainerQuoted 28 lines · David Miller
From: Jason Wang <[email protected]>
Date: Fri, 14 Dec 2018 12:29:54 +0800Quoted 18 lines · Michael S. Tsirkin
Quoted 8 lines · Jason Wang
Quoted 7 lines
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Quoted 6 lines
Quoted 4 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
I think the idea of speeding up userspace access is a good one. However I think that moving all checks to start is way too aggressive.
Quoted 6 lines
So did packet and
AF_XDP. Anyway, sharing address space and access them directly is the fastest way. Performance is the major consideration for people to choose backend. Compare to userspace implementation, vhost does not have security advantages at any level. If vhost is still slow, people will start to develop backends based on e.gAF_XDP.
Quoted 6 lines
Exactly, this is precisely how this kind of problem should be solved.
Michael, I strongly support the approach Jason is taking here, and I would like to ask you to seriously reconsider your objections.
Thank you.
Okay. Won't be the first time I'm wrong.
Let's say we ignore security aspects, but we need to make sure the following all keep working (broken with this revision):
- file backed memory (I didn't see where we mark memory dirty - if we don't we get guest memory corruption on close, if we do then host crash as https://lwn.net/Articles/774411/ seems to apply here?)
- THP
- auto-NUMA
Because vhost isn't like AF_XDP where you can just tell people "use hugetlbfs" and "data is removed on close" - people are using it in lots of configurations with guest memory shared between rings and unrelated data.
Jason, thoughts on these?
Signature · 1 line
MST
Quoted 31 lines · Michael S. Tsirkin
Quoted 30 lines · David Miller
From: Jason Wang <[email protected]>
Date: Fri, 14 Dec 2018 12:29:54 +0800Quoted 16 lines · Michael S. Tsirkin
Quoted 8 lines · Jason Wang
Quoted 7 lines
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Quoted 6 lines
Quoted 4 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
I think the idea of speeding up userspace access is a good one. However I think that moving all checks to start is way too aggressive.
Quoted 6 lines
So did packet and
AF_XDP. Anyway, sharing address space and access them directly is the fastest way. Performance is the major consideration for people to choose backend. Compare to userspace implementation, vhost does not have security advantages at any level. If vhost is still slow, people will start to develop backends based on e.gAF_XDP.Exactly, this is precisely how this kind of problem should be solved.
Michael, I strongly support the approach Jason is taking here, and I would like to ask you to seriously reconsider your objections.
Quoted 8 lines
Quoted 1 line
Thank you.
Okay. Won't be the first time I'm wrong.
Let's say we ignore security aspects, but we need to make sure the following all keep working (broken with this revision):
- file backed memory (I didn't see where we mark memory dirty - if we don't we get guest memory corruption on close, if we do then host crash as https://lwn.net/Articles/774411/ seems to apply here?)
We only pin metadata pages, so I don't think they can be used for DMA. So it was probably not an issue. The real issue is zerocopy codes, maybe it's time to disable it by default?
Quoted 1 line
- THP
We will miss 2 or 4 pages for THP, I wonder whether or not it's measurable.
Quoted 1 line
- auto-NUMA
I'm not sure auto-NUMA will help for the case of IPC. It can damage the performance in the worst case if vhost and userspace are running in two different nodes. Anyway I can measure.
Quoted 5 lines
Because vhost isn't like
AF_XDPwhere you can just tell people "use hugetlbfs" and "data is removed on close" - people are using it in lots of configurations with guest memory shared between rings and unrelated data.
This series doesn't share data, only metadata is shared.
Quoted 3 lines
Jason, thoughts on these?
Based on the above, I can measure the impact of THP to see how it impacts.
For unsafe variants, it can only work for when we can batch the access and it needs non trivial rework on the vhost codes with unexpected amount of work for archs other than x86. I'm not sure it's worth to try.
Thanks
Michael S. Tsirkin
maintainerQuoted 63 lines · Jason Wang
Quoted 31 lines · Michael S. Tsirkin
Quoted 30 lines · David Miller
From: Jason Wang <[email protected]>
Date: Fri, 14 Dec 2018 12:29:54 +0800Quoted 16 lines · Michael S. Tsirkin
Quoted 8 lines · Jason Wang
Quoted 7 lines
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Quoted 6 lines
Quoted 4 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
I think the idea of speeding up userspace access is a good one. However I think that moving all checks to start is way too aggressive.
Quoted 6 lines
So did packet and
AF_XDP. Anyway, sharing address space and access them directly is the fastest way. Performance is the major consideration for people to choose backend. Compare to userspace implementation, vhost does not have security advantages at any level. If vhost is still slow, people will start to develop backends based on e.gAF_XDP.Exactly, this is precisely how this kind of problem should be solved.
Michael, I strongly support the approach Jason is taking here, and I would like to ask you to seriously reconsider your objections.
Quoted 8 lines
Quoted 1 line
Thank you.
Okay. Won't be the first time I'm wrong.
Let's say we ignore security aspects, but we need to make sure the following all keep working (broken with this revision):
- file backed memory (I didn't see where we mark memory dirty - if we don't we get guest memory corruption on close, if we do then host crash as https://lwn.net/Articles/774411/ seems to apply here?)We only pin metadata pages, so I don't think they can be used for DMA. So it was probably not an issue. The real issue is zerocopy codes, maybe it's time to disable it by default?
Quoted 1 line
- THP
We will miss 2 or 4 pages for THP, I wonder whether or not it's measurable.
Quoted 1 line
- auto-NUMA
I'm not sure auto-NUMA will help for the case of IPC. It can damage the performance in the worst case if vhost and userspace are running in two different nodes. Anyway I can measure.
Quoted 1 line
Quoted 7 lines
Quoted 4 lines
Because vhost isn't like
AF_XDPwhere you can just tell people "use hugetlbfs" and "data is removed on close" - people are using it in lots of configurations with guest memory shared between rings and unrelated data.This series doesn't share data, only metadata is shared.
Let me clarify - I mean that metadata is in same huge page with unrelated guest data.
Quoted 5 lines
Quoted 4 lines
Jason, thoughts on these?
Quoted 7 lines
Based on the above, I can measure the impact of THP to see how it impacts.
For unsafe variants, it can only work for when we can batch the access and it needs non trivial rework on the vhost codes with unexpected amount of work for archs other than x86. I'm not sure it's worth to try.
Thanks
Yes I think we need better APIs in vhost. Right now we have an API to get and translate a single buffer. We should have one that gets a batch of descriptors and stores it, then one that translates this batch.
IMHO this will benefit everyone even if we do vmap due to better code locality.
Signature · 5 lines
MST _______________________________________________ Virtualization mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Quoted 31 lines · Michael S. Tsirkin
Quoted 30 lines · David Miller
From: Jason Wang <[email protected]>
Date: Fri, 14 Dec 2018 12:29:54 +0800Quoted 16 lines · Michael S. Tsirkin
Quoted 8 lines · Jason Wang
Quoted 7 lines
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Quoted 6 lines
Quoted 4 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
I think the idea of speeding up userspace access is a good one. However I think that moving all checks to start is way too aggressive.
Quoted 6 lines
So did packet and
AF_XDP. Anyway, sharing address space and access them directly is the fastest way. Performance is the major consideration for people to choose backend. Compare to userspace implementation, vhost does not have security advantages at any level. If vhost is still slow, people will start to develop backends based on e.gAF_XDP.Exactly, this is precisely how this kind of problem should be solved.
Michael, I strongly support the approach Jason is taking here, and I would like to ask you to seriously reconsider your objections.
Quoted 8 lines
Quoted 1 line
Thank you.
Okay. Won't be the first time I'm wrong.
Let's say we ignore security aspects, but we need to make sure the following all keep working (broken with this revision):
- file backed memory (I didn't see where we mark memory dirty - if we don't we get guest memory corruption on close, if we do then host crash as https://lwn.net/Articles/774411/ seems to apply here?)
We only pin metadata pages, so I don't think they can be used for DMA. So it was probably not an issue. The real issue is zerocopy codes, maybe it's time to disable it by default?
Quoted 1 line
- THP
We will miss 2 or 4 pages for THP, I wonder whether or not it's measurable.
Quoted 1 line
- auto-NUMA
I'm not sure auto-NUMA will help for the case of IPC. It can damage the performance in the worst case if vhost and userspace are running in two different nodes. Anyway I can measure.
Quoted 5 lines
Because vhost isn't like
AF_XDPwhere you can just tell people "use hugetlbfs" and "data is removed on close" - people are using it in lots of configurations with guest memory shared between rings and unrelated data.
This series doesn't share data, only metadata is shared.
Quoted 3 lines
Jason, thoughts on these?
Based on the above, I can measure the impact of THP to see how it impacts.
For unsafe variants, it can only work for when we can batch the access and it needs non trivial rework on the vhost codes with unexpected amount of work for archs other than x86. I'm not sure it's worth to try.
Thanks
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Michael S. Tsirkin
maintainerQuoted 28 lines · David Miller
From: Jason Wang <[email protected]>
Date: Fri, 14 Dec 2018 12:29:54 +0800Quoted 18 lines · Michael S. Tsirkin
Quoted 8 lines · Jason Wang
Quoted 7 lines
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Quoted 6 lines
Quoted 4 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
I think the idea of speeding up userspace access is a good one. However I think that moving all checks to start is way too aggressive.
Quoted 6 lines
So did packet and
AF_XDP. Anyway, sharing address space and access them directly is the fastest way. Performance is the major consideration for people to choose backend. Compare to userspace implementation, vhost does not have security advantages at any level. If vhost is still slow, people will start to develop backends based on e.gAF_XDP.
Quoted 6 lines
Exactly, this is precisely how this kind of problem should be solved.
Michael, I strongly support the approach Jason is taking here, and I would like to ask you to seriously reconsider your objections.
Thank you.
Okay. Won't be the first time I'm wrong.
Let's say we ignore security aspects, but we need to make sure the following all keep working (broken with this revision):
- file backed memory (I didn't see where we mark memory dirty - if we don't we get guest memory corruption on close, if we do then host crash as https://lwn.net/Articles/774411/ seems to apply here?)
- THP
- auto-NUMA
Because vhost isn't like AF_XDP where you can just tell people "use hugetlbfs" and "data is removed on close" - people are using it in lots of configurations with guest memory shared between rings and unrelated data.
Jason, thoughts on these?
Signature · 5 lines
MST _______________________________________________ Virtualization mailing list [email protected] https://lists.linuxfoundation.org/mailman/listinfo/virtualization
David Miller
maintainerFrom: Jason Wang <[email protected]>
Date: Fri, 14 Dec 2018 12:29:54 +0800
Quoted 18 lines · Michael S. Tsirkin
Quoted 8 lines · Jason Wang
Quoted 7 lines
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Quoted 6 lines
Quoted 4 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
I think the idea of speeding up userspace access is a good one. However I think that moving all checks to start is way too aggressive.
Quoted 6 lines
So did packet and
AF_XDP. Anyway, sharing address space and access them directly is the fastest way. Performance is the major consideration for people to choose backend. Compare to userspace implementation, vhost does not have security advantages at any level. If vhost is still slow, people will start to develop backends based on e.gAF_XDP.
Exactly, this is precisely how this kind of problem should be solved.
Michael, I strongly support the approach Jason is taking here, and I would like to ask you to seriously reconsider your objections.
Thank you.
Quoted 8 lines · Michael S. Tsirkin
Quoted 7 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.
Quoted 6 lines
Quoted 4 lines
Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
I think the idea of speeding up userspace access is a good one. However I think that moving all checks to start is way too aggressive.
So did packet and AF_XDP. Anyway, sharing address space and access them directly is the fastest way. Performance is the major consideration for people to choose backend. Compare to userspace implementation, vhost does not have security advantages at any level. If vhost is still slow, people will start to develop backends based on e.g AF_XDP.
Quoted 5 lines
Instead, let's batch things up but let's not keep them around forever.
Here are some ideas:
Quoted 7 lines
1. Disable preemption, process a small number of small packets directly in an atomic context. This should cut latency down significantly, the tricky part is to only do it on a light load and disable this
for the streaming case otherwise it's unfair. This might fail, if it does just bounce things out to a thread.
I'm not sure what context you meant here. Is this for TX path of TUN? But a fundamental difference is my series is targeted for extreme heavy load not light one, 100% cpu for vhost is expected.
Quoted 3 lines
2. Switch to unsafe_put_user/unsafe_get_user,
and batch up multiple accesses.
As I said, unless we can batch accessing of two difference places of three of avail, descriptor and used. It won't help for batching the accessing of a single place like used. I'm even not sure this can be done consider the case of packed virtqueue, we have a single descriptor ring. Batching through unsafe helpers may not help in this case since it's equivalent to safe ones . And This requires non trivial refactoring of vhost. And such refactoring itself make give us noticeable impact (e.g it may lead regression).
Quoted 6 lines
3. Allow adding a fixup point manually,
such that multiple independentget_useraccesses can get a single fixup (will allow better compiler optimizations).
So for metadata access, I don't see how you suggest here can help in the case of heavy workload.
For data access, this may help but I've played to batch the data copy to reduce SMAP/spec barriers in vhost-net but I don't see performance improvement.
Thanks
Quoted 8 lines
Quoted 8 lines
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual address
Quoted 6 lines
Quoted 6 lines
drivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Michael S. Tsirkin
maintainerQuoted 11 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
Please review
I think the idea of speeding up userspace access is a good one. However I think that moving all checks to start is way too aggressive. Instead, let's batch things up but let's not keep them around forever.
Here are some ideas:
1. Disable preemption, process a small number of small packets directly in an atomic context. This should cut latency down significantly, the tricky part is to only do it on a light load and disable this
for the streaming case otherwise it's unfair. This might fail, if it does just bounce things out to a thread.
2. Switch to unsafe_put_user/unsafe_get_user,
and batch up multiple accesses.
3. Allow adding a fixup point manually,
such that multiple independent get_user accesses can get a single fixup (will allow better compiler optimizations).
Quoted 11 lines
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual addressdrivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1
Michael S. Tsirkin
maintainerQuoted 9 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
BTW if the issue is all the error checking, maybe we should consider using something like uaccess_catch and check in a single place.
Quoted 13 lines
Please review
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual addressdrivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1
Michael S. Tsirkin
maintainerQuoted 9 lines · Jason Wang
Hi:
This series tries to access virtqueue metadata through kernel virtual address instead of
copy_user()friends since they had too much overheads like checks, spec barriers or even hardware feature toggling.Test shows about 24% improvement on TX PPS. It should benefit other cases as well.
BTW if the issue is all the error checking, maybe we should consider using something like uaccess_catch and check in a single place.
Quoted 13 lines
Please review
Jason Wang (3):
vhost: generalize adding used elem
vhost: fine grain userspace memory accessors
vhost: access vq metadata through kernel virtual addressdrivers/vhost/vhost.c | 281 ++++++++++++++++++++++++++++++++++++++---- drivers/vhost/vhost.h | 11 ++ 2 files changed, 266 insertions(+), 26 deletions(-)Signature · 1 line
2.17.1