Skip to content

Commit dbfa18c

Browse files
committed
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
Pull virtio bug fixes from Michael Tsirkin: "A bunch of fixes all over the place" * tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: tools/virtio: use canonical ftrace path vhost_vdpa: support PACKED when setting-getting vring_base vhost: support PACKED when setting-getting vring_base vhost: Fix worker hangs due to missed wake up calls vhost: Fix crash during early vhost_transport_send_pkt calls vhost_net: revert upend_idx only on retriable error vhost_vdpa: tell vqs about the negotiated vdpa/mlx5: Fix hang when cvq commands are triggered during device unregister tools/virtio: Add .gitignore for ringtest tools/virtio: Fix arm64 ringtest compilation error vduse: avoid empty string for dev name vhost: use kzalloc() instead of kmalloc() followed by memset()
2 parents 7e8c948 + 07496ee commit dbfa18c

File tree

11 files changed

+119
-64
lines changed

11 files changed

+119
-64
lines changed

drivers/vdpa/mlx5/net/mlx5_vnet.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3349,10 +3349,10 @@ static void mlx5_vdpa_dev_del(struct vdpa_mgmt_dev *v_mdev, struct vdpa_device *
33493349
mlx5_vdpa_remove_debugfs(ndev->debugfs);
33503350
ndev->debugfs = NULL;
33513351
unregister_link_notifier(ndev);
3352+
_vdpa_unregister_device(dev);
33523353
wq = mvdev->wq;
33533354
mvdev->wq = NULL;
33543355
destroy_workqueue(wq);
3355-
_vdpa_unregister_device(dev);
33563356
mgtdev->ndev = NULL;
33573357
}
33583358

drivers/vdpa/vdpa_user/vduse_dev.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,6 +1685,9 @@ static bool vduse_validate_config(struct vduse_dev_config *config)
16851685
if (config->vq_num > 0xffff)
16861686
return false;
16871687

1688+
if (!config->name[0])
1689+
return false;
1690+
16881691
if (!device_is_allowed(config->device_id))
16891692
return false;
16901693

drivers/vhost/net.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -935,13 +935,18 @@ static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock)
935935

936936
err = sock->ops->sendmsg(sock, &msg, len);
937937
if (unlikely(err < 0)) {
938+
bool retry = err == -EAGAIN || err == -ENOMEM || err == -ENOBUFS;
939+
938940
if (zcopy_used) {
939941
if (vq->heads[ubuf->desc].len == VHOST_DMA_IN_PROGRESS)
940942
vhost_net_ubuf_put(ubufs);
941-
nvq->upend_idx = ((unsigned)nvq->upend_idx - 1)
942-
% UIO_MAXIOV;
943+
if (retry)
944+
nvq->upend_idx = ((unsigned)nvq->upend_idx - 1)
945+
% UIO_MAXIOV;
946+
else
947+
vq->heads[ubuf->desc].len = VHOST_DMA_DONE_LEN;
943948
}
944-
if (err == -EAGAIN || err == -ENOMEM || err == -ENOBUFS) {
949+
if (retry) {
945950
vhost_discard_vq_desc(vq, 1);
946951
vhost_net_enable_vq(net, vq);
947952
break;

drivers/vhost/vdpa.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,10 @@ static long vhost_vdpa_set_features(struct vhost_vdpa *v, u64 __user *featurep)
407407
{
408408
struct vdpa_device *vdpa = v->vdpa;
409409
const struct vdpa_config_ops *ops = vdpa->config;
410+
struct vhost_dev *d = &v->vdev;
411+
u64 actual_features;
410412
u64 features;
413+
int i;
411414

412415
/*
413416
* It's not allowed to change the features after they have
@@ -422,6 +425,16 @@ static long vhost_vdpa_set_features(struct vhost_vdpa *v, u64 __user *featurep)
422425
if (vdpa_set_features(vdpa, features))
423426
return -EINVAL;
424427

428+
/* let the vqs know what has been configured */
429+
actual_features = ops->get_driver_features(vdpa);
430+
for (i = 0; i < d->nvqs; ++i) {
431+
struct vhost_virtqueue *vq = d->vqs[i];
432+
433+
mutex_lock(&vq->mutex);
434+
vq->acked_features = actual_features;
435+
mutex_unlock(&vq->mutex);
436+
}
437+
425438
return 0;
426439
}
427440

@@ -594,7 +607,14 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
594607
if (r)
595608
return r;
596609

597-
vq->last_avail_idx = vq_state.split.avail_index;
610+
if (vhost_has_feature(vq, VIRTIO_F_RING_PACKED)) {
611+
vq->last_avail_idx = vq_state.packed.last_avail_idx |
612+
(vq_state.packed.last_avail_counter << 15);
613+
vq->last_used_idx = vq_state.packed.last_used_idx |
614+
(vq_state.packed.last_used_counter << 15);
615+
} else {
616+
vq->last_avail_idx = vq_state.split.avail_index;
617+
}
598618
break;
599619
}
600620

@@ -612,9 +632,15 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
612632
break;
613633

614634
case VHOST_SET_VRING_BASE:
615-
vq_state.split.avail_index = vq->last_avail_idx;
616-
if (ops->set_vq_state(vdpa, idx, &vq_state))
617-
r = -EINVAL;
635+
if (vhost_has_feature(vq, VIRTIO_F_RING_PACKED)) {
636+
vq_state.packed.last_avail_idx = vq->last_avail_idx & 0x7fff;
637+
vq_state.packed.last_avail_counter = !!(vq->last_avail_idx & 0x8000);
638+
vq_state.packed.last_used_idx = vq->last_used_idx & 0x7fff;
639+
vq_state.packed.last_used_counter = !!(vq->last_used_idx & 0x8000);
640+
} else {
641+
vq_state.split.avail_index = vq->last_avail_idx;
642+
}
643+
r = ops->set_vq_state(vdpa, idx, &vq_state);
618644
break;
619645

620646
case VHOST_SET_VRING_CALL:

drivers/vhost/vhost.c

Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ void vhost_dev_flush(struct vhost_dev *dev)
235235
{
236236
struct vhost_flush_struct flush;
237237

238-
if (dev->worker) {
238+
if (dev->worker.vtsk) {
239239
init_completion(&flush.wait_event);
240240
vhost_work_init(&flush.work, vhost_flush_work);
241241

@@ -247,24 +247,24 @@ EXPORT_SYMBOL_GPL(vhost_dev_flush);
247247

248248
void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work)
249249
{
250-
if (!dev->worker)
250+
if (!dev->worker.vtsk)
251251
return;
252252

253253
if (!test_and_set_bit(VHOST_WORK_QUEUED, &work->flags)) {
254254
/* We can only add the work to the list after we're
255255
* sure it was not in the list.
256256
* test_and_set_bit() implies a memory barrier.
257257
*/
258-
llist_add(&work->node, &dev->worker->work_list);
259-
vhost_task_wake(dev->worker->vtsk);
258+
llist_add(&work->node, &dev->worker.work_list);
259+
vhost_task_wake(dev->worker.vtsk);
260260
}
261261
}
262262
EXPORT_SYMBOL_GPL(vhost_work_queue);
263263

264264
/* A lockless hint for busy polling code to exit the loop */
265265
bool vhost_has_work(struct vhost_dev *dev)
266266
{
267-
return dev->worker && !llist_empty(&dev->worker->work_list);
267+
return !llist_empty(&dev->worker.work_list);
268268
}
269269
EXPORT_SYMBOL_GPL(vhost_has_work);
270270

@@ -341,6 +341,8 @@ static bool vhost_worker(void *data)
341341

342342
node = llist_del_all(&worker->work_list);
343343
if (node) {
344+
__set_current_state(TASK_RUNNING);
345+
344346
node = llist_reverse_order(node);
345347
/* make sure flag is seen after deletion */
346348
smp_wmb();
@@ -456,7 +458,8 @@ void vhost_dev_init(struct vhost_dev *dev,
456458
dev->umem = NULL;
457459
dev->iotlb = NULL;
458460
dev->mm = NULL;
459-
dev->worker = NULL;
461+
memset(&dev->worker, 0, sizeof(dev->worker));
462+
init_llist_head(&dev->worker.work_list);
460463
dev->iov_limit = iov_limit;
461464
dev->weight = weight;
462465
dev->byte_weight = byte_weight;
@@ -530,47 +533,30 @@ static void vhost_detach_mm(struct vhost_dev *dev)
530533

531534
static void vhost_worker_free(struct vhost_dev *dev)
532535
{
533-
struct vhost_worker *worker = dev->worker;
534-
535-
if (!worker)
536+
if (!dev->worker.vtsk)
536537
return;
537538

538-
dev->worker = NULL;
539-
WARN_ON(!llist_empty(&worker->work_list));
540-
vhost_task_stop(worker->vtsk);
541-
kfree(worker);
539+
WARN_ON(!llist_empty(&dev->worker.work_list));
540+
vhost_task_stop(dev->worker.vtsk);
541+
dev->worker.kcov_handle = 0;
542+
dev->worker.vtsk = NULL;
542543
}
543544

544545
static int vhost_worker_create(struct vhost_dev *dev)
545546
{
546-
struct vhost_worker *worker;
547547
struct vhost_task *vtsk;
548548
char name[TASK_COMM_LEN];
549-
int ret;
550-
551-
worker = kzalloc(sizeof(*worker), GFP_KERNEL_ACCOUNT);
552-
if (!worker)
553-
return -ENOMEM;
554549

555-
dev->worker = worker;
556-
worker->kcov_handle = kcov_common_handle();
557-
init_llist_head(&worker->work_list);
558550
snprintf(name, sizeof(name), "vhost-%d", current->pid);
559551

560-
vtsk = vhost_task_create(vhost_worker, worker, name);
561-
if (!vtsk) {
562-
ret = -ENOMEM;
563-
goto free_worker;
564-
}
552+
vtsk = vhost_task_create(vhost_worker, &dev->worker, name);
553+
if (!vtsk)
554+
return -ENOMEM;
565555

566-
worker->vtsk = vtsk;
556+
dev->worker.kcov_handle = kcov_common_handle();
557+
dev->worker.vtsk = vtsk;
567558
vhost_task_start(vtsk);
568559
return 0;
569-
570-
free_worker:
571-
kfree(worker);
572-
dev->worker = NULL;
573-
return ret;
574560
}
575561

576562
/* Caller should have device mutex */
@@ -1614,17 +1600,25 @@ long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *arg
16141600
r = -EFAULT;
16151601
break;
16161602
}
1617-
if (s.num > 0xffff) {
1618-
r = -EINVAL;
1619-
break;
1603+
if (vhost_has_feature(vq, VIRTIO_F_RING_PACKED)) {
1604+
vq->last_avail_idx = s.num & 0xffff;
1605+
vq->last_used_idx = (s.num >> 16) & 0xffff;
1606+
} else {
1607+
if (s.num > 0xffff) {
1608+
r = -EINVAL;
1609+
break;
1610+
}
1611+
vq->last_avail_idx = s.num;
16201612
}
1621-
vq->last_avail_idx = s.num;
16221613
/* Forget the cached index value. */
16231614
vq->avail_idx = vq->last_avail_idx;
16241615
break;
16251616
case VHOST_GET_VRING_BASE:
16261617
s.index = idx;
1627-
s.num = vq->last_avail_idx;
1618+
if (vhost_has_feature(vq, VIRTIO_F_RING_PACKED))
1619+
s.num = (u32)vq->last_avail_idx | ((u32)vq->last_used_idx << 16);
1620+
else
1621+
s.num = vq->last_avail_idx;
16281622
if (copy_to_user(argp, &s, sizeof s))
16291623
r = -EFAULT;
16301624
break;
@@ -2563,12 +2557,11 @@ EXPORT_SYMBOL_GPL(vhost_disable_notify);
25632557
/* Create a new message. */
25642558
struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type)
25652559
{
2566-
struct vhost_msg_node *node = kmalloc(sizeof *node, GFP_KERNEL);
2560+
/* Make sure all padding within the structure is initialized. */
2561+
struct vhost_msg_node *node = kzalloc(sizeof(*node), GFP_KERNEL);
25672562
if (!node)
25682563
return NULL;
25692564

2570-
/* Make sure all padding within the structure is initialized. */
2571-
memset(&node->msg, 0, sizeof node->msg);
25722565
node->vq = vq;
25732566
node->msg.type = type;
25742567
return node;

drivers/vhost/vhost.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,17 @@ struct vhost_virtqueue {
9292
/* The routine to call when the Guest pings us, or timeout. */
9393
vhost_work_fn_t handle_kick;
9494

95-
/* Last available index we saw. */
95+
/* Last available index we saw.
96+
* Values are limited to 0x7fff, and the high bit is used as
97+
* a wrap counter when using VIRTIO_F_RING_PACKED. */
9698
u16 last_avail_idx;
9799

98100
/* Caches available index value from user. */
99101
u16 avail_idx;
100102

101-
/* Last index we used. */
103+
/* Last index we used.
104+
* Values are limited to 0x7fff, and the high bit is used as
105+
* a wrap counter when using VIRTIO_F_RING_PACKED. */
102106
u16 last_used_idx;
103107

104108
/* Used flags */
@@ -154,7 +158,7 @@ struct vhost_dev {
154158
struct vhost_virtqueue **vqs;
155159
int nvqs;
156160
struct eventfd_ctx *log_ctx;
157-
struct vhost_worker *worker;
161+
struct vhost_worker worker;
158162
struct vhost_iotlb *umem;
159163
struct vhost_iotlb *iotlb;
160164
spinlock_t iotlb_lock;

kernel/vhost_task.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@ static int vhost_task_fn(void *data)
2828
for (;;) {
2929
bool did_work;
3030

31-
/* mb paired w/ vhost_task_stop */
32-
if (test_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags))
33-
break;
34-
3531
if (!dead && signal_pending(current)) {
3632
struct ksignal ksig;
3733
/*
@@ -48,11 +44,17 @@ static int vhost_task_fn(void *data)
4844
clear_thread_flag(TIF_SIGPENDING);
4945
}
5046

47+
/* mb paired w/ vhost_task_stop */
48+
set_current_state(TASK_INTERRUPTIBLE);
49+
50+
if (test_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags)) {
51+
__set_current_state(TASK_RUNNING);
52+
break;
53+
}
54+
5155
did_work = vtsk->fn(vtsk->data);
52-
if (!did_work) {
53-
set_current_state(TASK_INTERRUPTIBLE);
56+
if (!did_work)
5457
schedule();
55-
}
5658
}
5759

5860
complete(&vtsk->exited);

tools/virtio/ringtest/.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-License-Identifier: GPL-2.0-only
2+
/noring
3+
/ptr_ring
4+
/ring
5+
/virtio_ring_0_9
6+
/virtio_ring_inorder
7+
/virtio_ring_poll

tools/virtio/ringtest/main.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#ifndef MAIN_H
99
#define MAIN_H
1010

11+
#include <assert.h>
1112
#include <stdbool.h>
1213

1314
extern int param;
@@ -95,6 +96,8 @@ extern unsigned ring_size;
9596
#define cpu_relax() asm ("rep; nop" ::: "memory")
9697
#elif defined(__s390x__)
9798
#define cpu_relax() barrier()
99+
#elif defined(__aarch64__)
100+
#define cpu_relax() asm ("yield" ::: "memory")
98101
#else
99102
#define cpu_relax() assert(0)
100103
#endif
@@ -112,6 +115,8 @@ static inline void busy_wait(void)
112115

113116
#if defined(__x86_64__) || defined(__i386__)
114117
#define smp_mb() asm volatile("lock; addl $0,-132(%%rsp)" ::: "memory", "cc")
118+
#elif defined(__aarch64__)
119+
#define smp_mb() asm volatile("dmb ish" ::: "memory")
115120
#else
116121
/*
117122
* Not using __ATOMIC_SEQ_CST since gcc docs say they are only synchronized
@@ -136,10 +141,16 @@ static inline void busy_wait(void)
136141

137142
#if defined(__i386__) || defined(__x86_64__) || defined(__s390x__)
138143
#define smp_wmb() barrier()
144+
#elif defined(__aarch64__)
145+
#define smp_wmb() asm volatile("dmb ishst" ::: "memory")
139146
#else
140147
#define smp_wmb() smp_release()
141148
#endif
142149

150+
#ifndef __always_inline
151+
#define __always_inline inline __attribute__((always_inline))
152+
#endif
153+
143154
static __always_inline
144155
void __read_once_size(const volatile void *p, void *res, int size)
145156
{

tools/virtio/virtio-trace/README

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ Run
9595

9696
1) Enable ftrace in the guest
9797
<Example>
98-
# echo 1 > /sys/kernel/debug/tracing/events/sched/enable
98+
# echo 1 > /sys/kernel/tracing/events/sched/enable
9999

100100
2) Run trace agent in the guest
101101
This agent must be operated as root.

0 commit comments

Comments
 (0)