net/ice: clean input set macro definition
[dpdk.git] / lib / librte_vhost / vhost.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2017 Intel Corporation
3  */
4
5 #include <linux/vhost.h>
6 #include <linux/virtio_net.h>
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <stdlib.h>
10 #ifdef RTE_LIBRTE_VHOST_NUMA
11 #include <numa.h>
12 #include <numaif.h>
13 #endif
14
15 #include <rte_errno.h>
16 #include <rte_ethdev.h>
17 #include <rte_log.h>
18 #include <rte_string_fns.h>
19 #include <rte_memory.h>
20 #include <rte_malloc.h>
21 #include <rte_vhost.h>
22 #include <rte_rwlock.h>
23
24 #include "iotlb.h"
25 #include "vhost.h"
26 #include "vhost_user.h"
27
28 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
29 pthread_mutex_t vhost_dev_lock = PTHREAD_MUTEX_INITIALIZER;
30
31 /* Called with iotlb_lock read-locked */
32 uint64_t
33 __vhost_iova_to_vva(struct virtio_net *dev, struct vhost_virtqueue *vq,
34                     uint64_t iova, uint64_t *size, uint8_t perm)
35 {
36         uint64_t vva, tmp_size;
37
38         if (unlikely(!*size))
39                 return 0;
40
41         tmp_size = *size;
42
43         vva = vhost_user_iotlb_cache_find(vq, iova, &tmp_size, perm);
44         if (tmp_size == *size)
45                 return vva;
46
47         iova += tmp_size;
48
49         if (!vhost_user_iotlb_pending_miss(vq, iova, perm)) {
50                 /*
51                  * iotlb_lock is read-locked for a full burst,
52                  * but it only protects the iotlb cache.
53                  * In case of IOTLB miss, we might block on the socket,
54                  * which could cause a deadlock with QEMU if an IOTLB update
55                  * is being handled. We can safely unlock here to avoid it.
56                  */
57                 vhost_user_iotlb_rd_unlock(vq);
58
59                 vhost_user_iotlb_pending_insert(vq, iova, perm);
60                 if (vhost_user_iotlb_miss(dev, iova, perm)) {
61                         VHOST_LOG_CONFIG(ERR,
62                                 "IOTLB miss req failed for IOVA 0x%" PRIx64 "\n",
63                                 iova);
64                         vhost_user_iotlb_pending_remove(vq, iova, 1, perm);
65                 }
66
67                 vhost_user_iotlb_rd_lock(vq);
68         }
69
70         return 0;
71 }
72
73 #define VHOST_LOG_PAGE  4096
74
75 /*
76  * Atomically set a bit in memory.
77  */
78 static __rte_always_inline void
79 vhost_set_bit(unsigned int nr, volatile uint8_t *addr)
80 {
81 #if defined(RTE_TOOLCHAIN_GCC) && (GCC_VERSION < 70100)
82         /*
83          * __sync_ built-ins are deprecated, but __atomic_ ones
84          * are sub-optimized in older GCC versions.
85          */
86         __sync_fetch_and_or_1(addr, (1U << nr));
87 #else
88         __atomic_fetch_or(addr, (1U << nr), __ATOMIC_RELAXED);
89 #endif
90 }
91
92 static __rte_always_inline void
93 vhost_log_page(uint8_t *log_base, uint64_t page)
94 {
95         vhost_set_bit(page % 8, &log_base[page / 8]);
96 }
97
98 void
99 __vhost_log_write(struct virtio_net *dev, uint64_t addr, uint64_t len)
100 {
101         uint64_t page;
102
103         if (unlikely(!dev->log_base || !len))
104                 return;
105
106         if (unlikely(dev->log_size <= ((addr + len - 1) / VHOST_LOG_PAGE / 8)))
107                 return;
108
109         /* To make sure guest memory updates are committed before logging */
110         rte_atomic_thread_fence(__ATOMIC_RELEASE);
111
112         page = addr / VHOST_LOG_PAGE;
113         while (page * VHOST_LOG_PAGE < addr + len) {
114                 vhost_log_page((uint8_t *)(uintptr_t)dev->log_base, page);
115                 page += 1;
116         }
117 }
118
119 void
120 __vhost_log_write_iova(struct virtio_net *dev, struct vhost_virtqueue *vq,
121                              uint64_t iova, uint64_t len)
122 {
123         uint64_t hva, gpa, map_len;
124         map_len = len;
125
126         hva = __vhost_iova_to_vva(dev, vq, iova, &map_len, VHOST_ACCESS_RW);
127         if (map_len != len) {
128                 VHOST_LOG_DATA(ERR,
129                         "Failed to write log for IOVA 0x%" PRIx64 ". No IOTLB entry found\n",
130                         iova);
131                 return;
132         }
133
134         gpa = hva_to_gpa(dev, hva, len);
135         if (gpa)
136                 __vhost_log_write(dev, gpa, len);
137 }
138
139 void
140 __vhost_log_cache_sync(struct virtio_net *dev, struct vhost_virtqueue *vq)
141 {
142         unsigned long *log_base;
143         int i;
144
145         if (unlikely(!dev->log_base))
146                 return;
147
148         rte_atomic_thread_fence(__ATOMIC_RELEASE);
149
150         log_base = (unsigned long *)(uintptr_t)dev->log_base;
151
152         for (i = 0; i < vq->log_cache_nb_elem; i++) {
153                 struct log_cache_entry *elem = vq->log_cache + i;
154
155 #if defined(RTE_TOOLCHAIN_GCC) && (GCC_VERSION < 70100)
156                 /*
157                  * '__sync' builtins are deprecated, but '__atomic' ones
158                  * are sub-optimized in older GCC versions.
159                  */
160                 __sync_fetch_and_or(log_base + elem->offset, elem->val);
161 #else
162                 __atomic_fetch_or(log_base + elem->offset, elem->val,
163                                 __ATOMIC_RELAXED);
164 #endif
165         }
166
167         rte_atomic_thread_fence(__ATOMIC_RELEASE);
168
169         vq->log_cache_nb_elem = 0;
170 }
171
172 static __rte_always_inline void
173 vhost_log_cache_page(struct virtio_net *dev, struct vhost_virtqueue *vq,
174                         uint64_t page)
175 {
176         uint32_t bit_nr = page % (sizeof(unsigned long) << 3);
177         uint32_t offset = page / (sizeof(unsigned long) << 3);
178         int i;
179
180         for (i = 0; i < vq->log_cache_nb_elem; i++) {
181                 struct log_cache_entry *elem = vq->log_cache + i;
182
183                 if (elem->offset == offset) {
184                         elem->val |= (1UL << bit_nr);
185                         return;
186                 }
187         }
188
189         if (unlikely(i >= VHOST_LOG_CACHE_NR)) {
190                 /*
191                  * No more room for a new log cache entry,
192                  * so write the dirty log map directly.
193                  */
194                 rte_atomic_thread_fence(__ATOMIC_RELEASE);
195                 vhost_log_page((uint8_t *)(uintptr_t)dev->log_base, page);
196
197                 return;
198         }
199
200         vq->log_cache[i].offset = offset;
201         vq->log_cache[i].val = (1UL << bit_nr);
202         vq->log_cache_nb_elem++;
203 }
204
205 void
206 __vhost_log_cache_write(struct virtio_net *dev, struct vhost_virtqueue *vq,
207                         uint64_t addr, uint64_t len)
208 {
209         uint64_t page;
210
211         if (unlikely(!dev->log_base || !len))
212                 return;
213
214         if (unlikely(dev->log_size <= ((addr + len - 1) / VHOST_LOG_PAGE / 8)))
215                 return;
216
217         page = addr / VHOST_LOG_PAGE;
218         while (page * VHOST_LOG_PAGE < addr + len) {
219                 vhost_log_cache_page(dev, vq, page);
220                 page += 1;
221         }
222 }
223
224 void
225 __vhost_log_cache_write_iova(struct virtio_net *dev, struct vhost_virtqueue *vq,
226                              uint64_t iova, uint64_t len)
227 {
228         uint64_t hva, gpa, map_len;
229         map_len = len;
230
231         hva = __vhost_iova_to_vva(dev, vq, iova, &map_len, VHOST_ACCESS_RW);
232         if (map_len != len) {
233                 VHOST_LOG_DATA(ERR,
234                         "Failed to write log for IOVA 0x%" PRIx64 ". No IOTLB entry found\n",
235                         iova);
236                 return;
237         }
238
239         gpa = hva_to_gpa(dev, hva, len);
240         if (gpa)
241                 __vhost_log_cache_write(dev, vq, gpa, len);
242 }
243
244 void *
245 vhost_alloc_copy_ind_table(struct virtio_net *dev, struct vhost_virtqueue *vq,
246                 uint64_t desc_addr, uint64_t desc_len)
247 {
248         void *idesc;
249         uint64_t src, dst;
250         uint64_t len, remain = desc_len;
251
252         idesc = rte_malloc(__func__, desc_len, 0);
253         if (unlikely(!idesc))
254                 return NULL;
255
256         dst = (uint64_t)(uintptr_t)idesc;
257
258         while (remain) {
259                 len = remain;
260                 src = vhost_iova_to_vva(dev, vq, desc_addr, &len,
261                                 VHOST_ACCESS_RO);
262                 if (unlikely(!src || !len)) {
263                         rte_free(idesc);
264                         return NULL;
265                 }
266
267                 rte_memcpy((void *)(uintptr_t)dst, (void *)(uintptr_t)src, len);
268
269                 remain -= len;
270                 dst += len;
271                 desc_addr += len;
272         }
273
274         return idesc;
275 }
276
277 void
278 cleanup_vq(struct vhost_virtqueue *vq, int destroy)
279 {
280         if ((vq->callfd >= 0) && (destroy != 0))
281                 close(vq->callfd);
282         if (vq->kickfd >= 0)
283                 close(vq->kickfd);
284 }
285
286 void
287 cleanup_vq_inflight(struct virtio_net *dev, struct vhost_virtqueue *vq)
288 {
289         if (!(dev->protocol_features &
290             (1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)))
291                 return;
292
293         if (vq_is_packed(dev)) {
294                 if (vq->inflight_packed)
295                         vq->inflight_packed = NULL;
296         } else {
297                 if (vq->inflight_split)
298                         vq->inflight_split = NULL;
299         }
300
301         if (vq->resubmit_inflight) {
302                 if (vq->resubmit_inflight->resubmit_list) {
303                         free(vq->resubmit_inflight->resubmit_list);
304                         vq->resubmit_inflight->resubmit_list = NULL;
305                 }
306                 free(vq->resubmit_inflight);
307                 vq->resubmit_inflight = NULL;
308         }
309 }
310
311 /*
312  * Unmap any memory, close any file descriptors and
313  * free any memory owned by a device.
314  */
315 void
316 cleanup_device(struct virtio_net *dev, int destroy)
317 {
318         uint32_t i;
319
320         vhost_backend_cleanup(dev);
321
322         for (i = 0; i < dev->nr_vring; i++) {
323                 cleanup_vq(dev->virtqueue[i], destroy);
324                 cleanup_vq_inflight(dev, dev->virtqueue[i]);
325         }
326 }
327
328 static void
329 vhost_free_async_mem(struct vhost_virtqueue *vq)
330 {
331         if (vq->async_pkts_info)
332                 rte_free(vq->async_pkts_info);
333         if (vq->async_descs_split)
334                 rte_free(vq->async_descs_split);
335         if (vq->it_pool)
336                 rte_free(vq->it_pool);
337         if (vq->vec_pool)
338                 rte_free(vq->vec_pool);
339
340         vq->async_pkts_info = NULL;
341         vq->async_descs_split = NULL;
342         vq->it_pool = NULL;
343         vq->vec_pool = NULL;
344 }
345
346 void
347 free_vq(struct virtio_net *dev, struct vhost_virtqueue *vq)
348 {
349         if (vq_is_packed(dev))
350                 rte_free(vq->shadow_used_packed);
351         else {
352                 rte_free(vq->shadow_used_split);
353                 vhost_free_async_mem(vq);
354         }
355         rte_free(vq->batch_copy_elems);
356         rte_mempool_free(vq->iotlb_pool);
357         rte_free(vq);
358 }
359
360 /*
361  * Release virtqueues and device memory.
362  */
363 static void
364 free_device(struct virtio_net *dev)
365 {
366         uint32_t i;
367
368         for (i = 0; i < dev->nr_vring; i++)
369                 free_vq(dev, dev->virtqueue[i]);
370
371         rte_free(dev);
372 }
373
374 static __rte_always_inline int
375 log_translate(struct virtio_net *dev, struct vhost_virtqueue *vq)
376 {
377         if (likely(!(vq->ring_addrs.flags & (1 << VHOST_VRING_F_LOG))))
378                 return 0;
379
380         vq->log_guest_addr = translate_log_addr(dev, vq,
381                                                 vq->ring_addrs.log_guest_addr);
382         if (vq->log_guest_addr == 0)
383                 return -1;
384
385         return 0;
386 }
387
388 /*
389  * Converts vring log address to GPA
390  * If IOMMU is enabled, the log address is IOVA
391  * If IOMMU not enabled, the log address is already GPA
392  *
393  * Caller should have iotlb_lock read-locked
394  */
395 uint64_t
396 translate_log_addr(struct virtio_net *dev, struct vhost_virtqueue *vq,
397                 uint64_t log_addr)
398 {
399         if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)) {
400                 const uint64_t exp_size = sizeof(uint64_t);
401                 uint64_t hva, gpa;
402                 uint64_t size = exp_size;
403
404                 hva = vhost_iova_to_vva(dev, vq, log_addr,
405                                         &size, VHOST_ACCESS_RW);
406
407                 if (size != exp_size)
408                         return 0;
409
410                 gpa = hva_to_gpa(dev, hva, exp_size);
411                 if (!gpa) {
412                         VHOST_LOG_CONFIG(ERR,
413                                 "VQ: Failed to find GPA for log_addr: 0x%"
414                                 PRIx64 " hva: 0x%" PRIx64 "\n",
415                                 log_addr, hva);
416                         return 0;
417                 }
418                 return gpa;
419
420         } else
421                 return log_addr;
422 }
423
424 /* Caller should have iotlb_lock read-locked */
425 static int
426 vring_translate_split(struct virtio_net *dev, struct vhost_virtqueue *vq)
427 {
428         uint64_t req_size, size;
429
430         req_size = sizeof(struct vring_desc) * vq->size;
431         size = req_size;
432         vq->desc = (struct vring_desc *)(uintptr_t)vhost_iova_to_vva(dev, vq,
433                                                 vq->ring_addrs.desc_user_addr,
434                                                 &size, VHOST_ACCESS_RW);
435         if (!vq->desc || size != req_size)
436                 return -1;
437
438         req_size = sizeof(struct vring_avail);
439         req_size += sizeof(uint16_t) * vq->size;
440         if (dev->features & (1ULL << VIRTIO_RING_F_EVENT_IDX))
441                 req_size += sizeof(uint16_t);
442         size = req_size;
443         vq->avail = (struct vring_avail *)(uintptr_t)vhost_iova_to_vva(dev, vq,
444                                                 vq->ring_addrs.avail_user_addr,
445                                                 &size, VHOST_ACCESS_RW);
446         if (!vq->avail || size != req_size)
447                 return -1;
448
449         req_size = sizeof(struct vring_used);
450         req_size += sizeof(struct vring_used_elem) * vq->size;
451         if (dev->features & (1ULL << VIRTIO_RING_F_EVENT_IDX))
452                 req_size += sizeof(uint16_t);
453         size = req_size;
454         vq->used = (struct vring_used *)(uintptr_t)vhost_iova_to_vva(dev, vq,
455                                                 vq->ring_addrs.used_user_addr,
456                                                 &size, VHOST_ACCESS_RW);
457         if (!vq->used || size != req_size)
458                 return -1;
459
460         return 0;
461 }
462
463 /* Caller should have iotlb_lock read-locked */
464 static int
465 vring_translate_packed(struct virtio_net *dev, struct vhost_virtqueue *vq)
466 {
467         uint64_t req_size, size;
468
469         req_size = sizeof(struct vring_packed_desc) * vq->size;
470         size = req_size;
471         vq->desc_packed = (struct vring_packed_desc *)(uintptr_t)
472                 vhost_iova_to_vva(dev, vq, vq->ring_addrs.desc_user_addr,
473                                 &size, VHOST_ACCESS_RW);
474         if (!vq->desc_packed || size != req_size)
475                 return -1;
476
477         req_size = sizeof(struct vring_packed_desc_event);
478         size = req_size;
479         vq->driver_event = (struct vring_packed_desc_event *)(uintptr_t)
480                 vhost_iova_to_vva(dev, vq, vq->ring_addrs.avail_user_addr,
481                                 &size, VHOST_ACCESS_RW);
482         if (!vq->driver_event || size != req_size)
483                 return -1;
484
485         req_size = sizeof(struct vring_packed_desc_event);
486         size = req_size;
487         vq->device_event = (struct vring_packed_desc_event *)(uintptr_t)
488                 vhost_iova_to_vva(dev, vq, vq->ring_addrs.used_user_addr,
489                                 &size, VHOST_ACCESS_RW);
490         if (!vq->device_event || size != req_size)
491                 return -1;
492
493         return 0;
494 }
495
496 int
497 vring_translate(struct virtio_net *dev, struct vhost_virtqueue *vq)
498 {
499
500         if (!(dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)))
501                 return -1;
502
503         if (vq_is_packed(dev)) {
504                 if (vring_translate_packed(dev, vq) < 0)
505                         return -1;
506         } else {
507                 if (vring_translate_split(dev, vq) < 0)
508                         return -1;
509         }
510
511         if (log_translate(dev, vq) < 0)
512                 return -1;
513
514         vq->access_ok = 1;
515
516         return 0;
517 }
518
519 void
520 vring_invalidate(struct virtio_net *dev, struct vhost_virtqueue *vq)
521 {
522         if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM))
523                 vhost_user_iotlb_wr_lock(vq);
524
525         vq->access_ok = 0;
526         vq->desc = NULL;
527         vq->avail = NULL;
528         vq->used = NULL;
529         vq->log_guest_addr = 0;
530
531         if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM))
532                 vhost_user_iotlb_wr_unlock(vq);
533 }
534
535 static void
536 init_vring_queue(struct virtio_net *dev, uint32_t vring_idx)
537 {
538         struct vhost_virtqueue *vq;
539
540         if (vring_idx >= VHOST_MAX_VRING) {
541                 VHOST_LOG_CONFIG(ERR,
542                                 "Failed not init vring, out of bound (%d)\n",
543                                 vring_idx);
544                 return;
545         }
546
547         vq = dev->virtqueue[vring_idx];
548         if (!vq) {
549                 VHOST_LOG_CONFIG(ERR, "Virtqueue not allocated (%d)\n",
550                                 vring_idx);
551                 return;
552         }
553
554         memset(vq, 0, sizeof(struct vhost_virtqueue));
555
556         vq->kickfd = VIRTIO_UNINITIALIZED_EVENTFD;
557         vq->callfd = VIRTIO_UNINITIALIZED_EVENTFD;
558         vq->notif_enable = VIRTIO_UNINITIALIZED_NOTIF;
559
560         vhost_user_iotlb_init(dev, vring_idx);
561         /* Backends are set to -1 indicating an inactive device. */
562         vq->backend = -1;
563 }
564
565 static void
566 reset_vring_queue(struct virtio_net *dev, uint32_t vring_idx)
567 {
568         struct vhost_virtqueue *vq;
569         int callfd;
570
571         if (vring_idx >= VHOST_MAX_VRING) {
572                 VHOST_LOG_CONFIG(ERR,
573                                 "Failed not init vring, out of bound (%d)\n",
574                                 vring_idx);
575                 return;
576         }
577
578         vq = dev->virtqueue[vring_idx];
579         if (!vq) {
580                 VHOST_LOG_CONFIG(ERR, "Virtqueue not allocated (%d)\n",
581                                 vring_idx);
582                 return;
583         }
584
585         callfd = vq->callfd;
586         init_vring_queue(dev, vring_idx);
587         vq->callfd = callfd;
588 }
589
590 int
591 alloc_vring_queue(struct virtio_net *dev, uint32_t vring_idx)
592 {
593         struct vhost_virtqueue *vq;
594         uint32_t i;
595
596         /* Also allocate holes, if any, up to requested vring index. */
597         for (i = 0; i <= vring_idx; i++) {
598                 if (dev->virtqueue[i])
599                         continue;
600
601                 vq = rte_malloc(NULL, sizeof(struct vhost_virtqueue), 0);
602                 if (vq == NULL) {
603                         VHOST_LOG_CONFIG(ERR,
604                                 "Failed to allocate memory for vring:%u.\n", i);
605                         return -1;
606                 }
607
608                 dev->virtqueue[i] = vq;
609                 init_vring_queue(dev, i);
610                 rte_spinlock_init(&vq->access_lock);
611                 vq->avail_wrap_counter = 1;
612                 vq->used_wrap_counter = 1;
613                 vq->signalled_used_valid = false;
614         }
615
616         dev->nr_vring = RTE_MAX(dev->nr_vring, vring_idx + 1);
617
618         return 0;
619 }
620
621 /*
622  * Reset some variables in device structure, while keeping few
623  * others untouched, such as vid, ifname, nr_vring: they
624  * should be same unless the device is removed.
625  */
626 void
627 reset_device(struct virtio_net *dev)
628 {
629         uint32_t i;
630
631         dev->features = 0;
632         dev->protocol_features = 0;
633         dev->flags &= VIRTIO_DEV_BUILTIN_VIRTIO_NET;
634
635         for (i = 0; i < dev->nr_vring; i++)
636                 reset_vring_queue(dev, i);
637 }
638
639 /*
640  * Invoked when there is a new vhost-user connection established (when
641  * there is a new virtio device being attached).
642  */
643 int
644 vhost_new_device(void)
645 {
646         struct virtio_net *dev;
647         int i;
648
649         pthread_mutex_lock(&vhost_dev_lock);
650         for (i = 0; i < MAX_VHOST_DEVICE; i++) {
651                 if (vhost_devices[i] == NULL)
652                         break;
653         }
654
655         if (i == MAX_VHOST_DEVICE) {
656                 VHOST_LOG_CONFIG(ERR,
657                         "Failed to find a free slot for new device.\n");
658                 pthread_mutex_unlock(&vhost_dev_lock);
659                 return -1;
660         }
661
662         dev = rte_zmalloc(NULL, sizeof(struct virtio_net), 0);
663         if (dev == NULL) {
664                 VHOST_LOG_CONFIG(ERR,
665                         "Failed to allocate memory for new dev.\n");
666                 pthread_mutex_unlock(&vhost_dev_lock);
667                 return -1;
668         }
669
670         vhost_devices[i] = dev;
671         pthread_mutex_unlock(&vhost_dev_lock);
672
673         dev->vid = i;
674         dev->flags = VIRTIO_DEV_BUILTIN_VIRTIO_NET;
675         dev->slave_req_fd = -1;
676         dev->postcopy_ufd = -1;
677         rte_spinlock_init(&dev->slave_req_lock);
678
679         return i;
680 }
681
682 void
683 vhost_destroy_device_notify(struct virtio_net *dev)
684 {
685         struct rte_vdpa_device *vdpa_dev;
686
687         if (dev->flags & VIRTIO_DEV_RUNNING) {
688                 vdpa_dev = dev->vdpa_dev;
689                 if (vdpa_dev)
690                         vdpa_dev->ops->dev_close(dev->vid);
691                 dev->flags &= ~VIRTIO_DEV_RUNNING;
692                 dev->notify_ops->destroy_device(dev->vid);
693         }
694 }
695
696 /*
697  * Invoked when there is the vhost-user connection is broken (when
698  * the virtio device is being detached).
699  */
700 void
701 vhost_destroy_device(int vid)
702 {
703         struct virtio_net *dev = get_device(vid);
704
705         if (dev == NULL)
706                 return;
707
708         vhost_destroy_device_notify(dev);
709
710         cleanup_device(dev, 1);
711         free_device(dev);
712
713         vhost_devices[vid] = NULL;
714 }
715
716 void
717 vhost_attach_vdpa_device(int vid, struct rte_vdpa_device *vdpa_dev)
718 {
719         struct virtio_net *dev = get_device(vid);
720
721         if (dev == NULL)
722                 return;
723
724         dev->vdpa_dev = vdpa_dev;
725 }
726
727 void
728 vhost_set_ifname(int vid, const char *if_name, unsigned int if_len)
729 {
730         struct virtio_net *dev;
731         unsigned int len;
732
733         dev = get_device(vid);
734         if (dev == NULL)
735                 return;
736
737         len = if_len > sizeof(dev->ifname) ?
738                 sizeof(dev->ifname) : if_len;
739
740         strncpy(dev->ifname, if_name, len);
741         dev->ifname[sizeof(dev->ifname) - 1] = '\0';
742 }
743
744 void
745 vhost_set_builtin_virtio_net(int vid, bool enable)
746 {
747         struct virtio_net *dev = get_device(vid);
748
749         if (dev == NULL)
750                 return;
751
752         if (enable)
753                 dev->flags |= VIRTIO_DEV_BUILTIN_VIRTIO_NET;
754         else
755                 dev->flags &= ~VIRTIO_DEV_BUILTIN_VIRTIO_NET;
756 }
757
758 void
759 vhost_enable_extbuf(int vid)
760 {
761         struct virtio_net *dev = get_device(vid);
762
763         if (dev == NULL)
764                 return;
765
766         dev->extbuf = 1;
767 }
768
769 void
770 vhost_enable_linearbuf(int vid)
771 {
772         struct virtio_net *dev = get_device(vid);
773
774         if (dev == NULL)
775                 return;
776
777         dev->linearbuf = 1;
778 }
779
780 int
781 rte_vhost_get_mtu(int vid, uint16_t *mtu)
782 {
783         struct virtio_net *dev = get_device(vid);
784
785         if (dev == NULL || mtu == NULL)
786                 return -ENODEV;
787
788         if (!(dev->flags & VIRTIO_DEV_READY))
789                 return -EAGAIN;
790
791         if (!(dev->features & (1ULL << VIRTIO_NET_F_MTU)))
792                 return -ENOTSUP;
793
794         *mtu = dev->mtu;
795
796         return 0;
797 }
798
799 int
800 rte_vhost_get_numa_node(int vid)
801 {
802 #ifdef RTE_LIBRTE_VHOST_NUMA
803         struct virtio_net *dev = get_device(vid);
804         int numa_node;
805         int ret;
806
807         if (dev == NULL || numa_available() != 0)
808                 return -1;
809
810         ret = get_mempolicy(&numa_node, NULL, 0, dev,
811                             MPOL_F_NODE | MPOL_F_ADDR);
812         if (ret < 0) {
813                 VHOST_LOG_CONFIG(ERR,
814                         "(%d) failed to query numa node: %s\n",
815                         vid, rte_strerror(errno));
816                 return -1;
817         }
818
819         return numa_node;
820 #else
821         RTE_SET_USED(vid);
822         return -1;
823 #endif
824 }
825
826 uint32_t
827 rte_vhost_get_queue_num(int vid)
828 {
829         struct virtio_net *dev = get_device(vid);
830
831         if (dev == NULL)
832                 return 0;
833
834         return dev->nr_vring / 2;
835 }
836
837 uint16_t
838 rte_vhost_get_vring_num(int vid)
839 {
840         struct virtio_net *dev = get_device(vid);
841
842         if (dev == NULL)
843                 return 0;
844
845         return dev->nr_vring;
846 }
847
848 int
849 rte_vhost_get_ifname(int vid, char *buf, size_t len)
850 {
851         struct virtio_net *dev = get_device(vid);
852
853         if (dev == NULL || buf == NULL)
854                 return -1;
855
856         len = RTE_MIN(len, sizeof(dev->ifname));
857
858         strncpy(buf, dev->ifname, len);
859         buf[len - 1] = '\0';
860
861         return 0;
862 }
863
864 int
865 rte_vhost_get_negotiated_features(int vid, uint64_t *features)
866 {
867         struct virtio_net *dev;
868
869         dev = get_device(vid);
870         if (dev == NULL || features == NULL)
871                 return -1;
872
873         *features = dev->features;
874         return 0;
875 }
876
877 int
878 rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem)
879 {
880         struct virtio_net *dev;
881         struct rte_vhost_memory *m;
882         size_t size;
883
884         dev = get_device(vid);
885         if (dev == NULL || mem == NULL)
886                 return -1;
887
888         size = dev->mem->nregions * sizeof(struct rte_vhost_mem_region);
889         m = malloc(sizeof(struct rte_vhost_memory) + size);
890         if (!m)
891                 return -1;
892
893         m->nregions = dev->mem->nregions;
894         memcpy(m->regions, dev->mem->regions, size);
895         *mem = m;
896
897         return 0;
898 }
899
900 int
901 rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
902                           struct rte_vhost_vring *vring)
903 {
904         struct virtio_net *dev;
905         struct vhost_virtqueue *vq;
906
907         dev = get_device(vid);
908         if (dev == NULL || vring == NULL)
909                 return -1;
910
911         if (vring_idx >= VHOST_MAX_VRING)
912                 return -1;
913
914         vq = dev->virtqueue[vring_idx];
915         if (!vq)
916                 return -1;
917
918         if (vq_is_packed(dev)) {
919                 vring->desc_packed = vq->desc_packed;
920                 vring->driver_event = vq->driver_event;
921                 vring->device_event = vq->device_event;
922         } else {
923                 vring->desc = vq->desc;
924                 vring->avail = vq->avail;
925                 vring->used = vq->used;
926         }
927         vring->log_guest_addr  = vq->log_guest_addr;
928
929         vring->callfd  = vq->callfd;
930         vring->kickfd  = vq->kickfd;
931         vring->size    = vq->size;
932
933         return 0;
934 }
935
936 int
937 rte_vhost_get_vhost_ring_inflight(int vid, uint16_t vring_idx,
938                                   struct rte_vhost_ring_inflight *vring)
939 {
940         struct virtio_net *dev;
941         struct vhost_virtqueue *vq;
942
943         dev = get_device(vid);
944         if (unlikely(!dev))
945                 return -1;
946
947         if (vring_idx >= VHOST_MAX_VRING)
948                 return -1;
949
950         vq = dev->virtqueue[vring_idx];
951         if (unlikely(!vq))
952                 return -1;
953
954         if (vq_is_packed(dev)) {
955                 if (unlikely(!vq->inflight_packed))
956                         return -1;
957
958                 vring->inflight_packed = vq->inflight_packed;
959         } else {
960                 if (unlikely(!vq->inflight_split))
961                         return -1;
962
963                 vring->inflight_split = vq->inflight_split;
964         }
965
966         vring->resubmit_inflight = vq->resubmit_inflight;
967
968         return 0;
969 }
970
971 int
972 rte_vhost_set_inflight_desc_split(int vid, uint16_t vring_idx,
973                                   uint16_t idx)
974 {
975         struct vhost_virtqueue *vq;
976         struct virtio_net *dev;
977
978         dev = get_device(vid);
979         if (unlikely(!dev))
980                 return -1;
981
982         if (unlikely(!(dev->protocol_features &
983             (1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD))))
984                 return 0;
985
986         if (unlikely(vq_is_packed(dev)))
987                 return -1;
988
989         if (unlikely(vring_idx >= VHOST_MAX_VRING))
990                 return -1;
991
992         vq = dev->virtqueue[vring_idx];
993         if (unlikely(!vq))
994                 return -1;
995
996         if (unlikely(!vq->inflight_split))
997                 return -1;
998
999         if (unlikely(idx >= vq->size))
1000                 return -1;
1001
1002         vq->inflight_split->desc[idx].counter = vq->global_counter++;
1003         vq->inflight_split->desc[idx].inflight = 1;
1004         return 0;
1005 }
1006
1007 int
1008 rte_vhost_set_inflight_desc_packed(int vid, uint16_t vring_idx,
1009                                    uint16_t head, uint16_t last,
1010                                    uint16_t *inflight_entry)
1011 {
1012         struct rte_vhost_inflight_info_packed *inflight_info;
1013         struct virtio_net *dev;
1014         struct vhost_virtqueue *vq;
1015         struct vring_packed_desc *desc;
1016         uint16_t old_free_head, free_head;
1017
1018         dev = get_device(vid);
1019         if (unlikely(!dev))
1020                 return -1;
1021
1022         if (unlikely(!(dev->protocol_features &
1023             (1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD))))
1024                 return 0;
1025
1026         if (unlikely(!vq_is_packed(dev)))
1027                 return -1;
1028
1029         if (unlikely(vring_idx >= VHOST_MAX_VRING))
1030                 return -1;
1031
1032         vq = dev->virtqueue[vring_idx];
1033         if (unlikely(!vq))
1034                 return -1;
1035
1036         inflight_info = vq->inflight_packed;
1037         if (unlikely(!inflight_info))
1038                 return -1;
1039
1040         if (unlikely(head >= vq->size))
1041                 return -1;
1042
1043         desc = vq->desc_packed;
1044         old_free_head = inflight_info->old_free_head;
1045         if (unlikely(old_free_head >= vq->size))
1046                 return -1;
1047
1048         free_head = old_free_head;
1049
1050         /* init header descriptor */
1051         inflight_info->desc[old_free_head].num = 0;
1052         inflight_info->desc[old_free_head].counter = vq->global_counter++;
1053         inflight_info->desc[old_free_head].inflight = 1;
1054
1055         /* save desc entry in flight entry */
1056         while (head != ((last + 1) % vq->size)) {
1057                 inflight_info->desc[old_free_head].num++;
1058                 inflight_info->desc[free_head].addr = desc[head].addr;
1059                 inflight_info->desc[free_head].len = desc[head].len;
1060                 inflight_info->desc[free_head].flags = desc[head].flags;
1061                 inflight_info->desc[free_head].id = desc[head].id;
1062
1063                 inflight_info->desc[old_free_head].last = free_head;
1064                 free_head = inflight_info->desc[free_head].next;
1065                 inflight_info->free_head = free_head;
1066                 head = (head + 1) % vq->size;
1067         }
1068
1069         inflight_info->old_free_head = free_head;
1070         *inflight_entry = old_free_head;
1071
1072         return 0;
1073 }
1074
1075 int
1076 rte_vhost_clr_inflight_desc_split(int vid, uint16_t vring_idx,
1077                                   uint16_t last_used_idx, uint16_t idx)
1078 {
1079         struct virtio_net *dev;
1080         struct vhost_virtqueue *vq;
1081
1082         dev = get_device(vid);
1083         if (unlikely(!dev))
1084                 return -1;
1085
1086         if (unlikely(!(dev->protocol_features &
1087             (1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD))))
1088                 return 0;
1089
1090         if (unlikely(vq_is_packed(dev)))
1091                 return -1;
1092
1093         if (unlikely(vring_idx >= VHOST_MAX_VRING))
1094                 return -1;
1095
1096         vq = dev->virtqueue[vring_idx];
1097         if (unlikely(!vq))
1098                 return -1;
1099
1100         if (unlikely(!vq->inflight_split))
1101                 return -1;
1102
1103         if (unlikely(idx >= vq->size))
1104                 return -1;
1105
1106         rte_atomic_thread_fence(__ATOMIC_SEQ_CST);
1107
1108         vq->inflight_split->desc[idx].inflight = 0;
1109
1110         rte_atomic_thread_fence(__ATOMIC_SEQ_CST);
1111
1112         vq->inflight_split->used_idx = last_used_idx;
1113         return 0;
1114 }
1115
1116 int
1117 rte_vhost_clr_inflight_desc_packed(int vid, uint16_t vring_idx,
1118                                    uint16_t head)
1119 {
1120         struct rte_vhost_inflight_info_packed *inflight_info;
1121         struct virtio_net *dev;
1122         struct vhost_virtqueue *vq;
1123
1124         dev = get_device(vid);
1125         if (unlikely(!dev))
1126                 return -1;
1127
1128         if (unlikely(!(dev->protocol_features &
1129             (1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD))))
1130                 return 0;
1131
1132         if (unlikely(!vq_is_packed(dev)))
1133                 return -1;
1134
1135         if (unlikely(vring_idx >= VHOST_MAX_VRING))
1136                 return -1;
1137
1138         vq = dev->virtqueue[vring_idx];
1139         if (unlikely(!vq))
1140                 return -1;
1141
1142         inflight_info = vq->inflight_packed;
1143         if (unlikely(!inflight_info))
1144                 return -1;
1145
1146         if (unlikely(head >= vq->size))
1147                 return -1;
1148
1149         rte_atomic_thread_fence(__ATOMIC_SEQ_CST);
1150
1151         inflight_info->desc[head].inflight = 0;
1152
1153         rte_atomic_thread_fence(__ATOMIC_SEQ_CST);
1154
1155         inflight_info->old_free_head = inflight_info->free_head;
1156         inflight_info->old_used_idx = inflight_info->used_idx;
1157         inflight_info->old_used_wrap_counter = inflight_info->used_wrap_counter;
1158
1159         return 0;
1160 }
1161
1162 int
1163 rte_vhost_set_last_inflight_io_split(int vid, uint16_t vring_idx,
1164                                      uint16_t idx)
1165 {
1166         struct virtio_net *dev;
1167         struct vhost_virtqueue *vq;
1168
1169         dev = get_device(vid);
1170         if (unlikely(!dev))
1171                 return -1;
1172
1173         if (unlikely(!(dev->protocol_features &
1174             (1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD))))
1175                 return 0;
1176
1177         if (unlikely(vq_is_packed(dev)))
1178                 return -1;
1179
1180         if (unlikely(vring_idx >= VHOST_MAX_VRING))
1181                 return -1;
1182
1183         vq = dev->virtqueue[vring_idx];
1184         if (unlikely(!vq))
1185                 return -1;
1186
1187         if (unlikely(!vq->inflight_split))
1188                 return -1;
1189
1190         vq->inflight_split->last_inflight_io = idx;
1191         return 0;
1192 }
1193
1194 int
1195 rte_vhost_set_last_inflight_io_packed(int vid, uint16_t vring_idx,
1196                                       uint16_t head)
1197 {
1198         struct rte_vhost_inflight_info_packed *inflight_info;
1199         struct virtio_net *dev;
1200         struct vhost_virtqueue *vq;
1201         uint16_t last;
1202
1203         dev = get_device(vid);
1204         if (unlikely(!dev))
1205                 return -1;
1206
1207         if (unlikely(!(dev->protocol_features &
1208             (1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD))))
1209                 return 0;
1210
1211         if (unlikely(!vq_is_packed(dev)))
1212                 return -1;
1213
1214         if (unlikely(vring_idx >= VHOST_MAX_VRING))
1215                 return -1;
1216
1217         vq = dev->virtqueue[vring_idx];
1218         if (unlikely(!vq))
1219                 return -1;
1220
1221         inflight_info = vq->inflight_packed;
1222         if (unlikely(!inflight_info))
1223                 return -1;
1224
1225         if (unlikely(head >= vq->size))
1226                 return -1;
1227
1228         last = inflight_info->desc[head].last;
1229         if (unlikely(last >= vq->size))
1230                 return -1;
1231
1232         inflight_info->desc[last].next = inflight_info->free_head;
1233         inflight_info->free_head = head;
1234         inflight_info->used_idx += inflight_info->desc[head].num;
1235         if (inflight_info->used_idx >= inflight_info->desc_num) {
1236                 inflight_info->used_idx -= inflight_info->desc_num;
1237                 inflight_info->used_wrap_counter =
1238                         !inflight_info->used_wrap_counter;
1239         }
1240
1241         return 0;
1242 }
1243
1244 int
1245 rte_vhost_vring_call(int vid, uint16_t vring_idx)
1246 {
1247         struct virtio_net *dev;
1248         struct vhost_virtqueue *vq;
1249
1250         dev = get_device(vid);
1251         if (!dev)
1252                 return -1;
1253
1254         if (vring_idx >= VHOST_MAX_VRING)
1255                 return -1;
1256
1257         vq = dev->virtqueue[vring_idx];
1258         if (!vq)
1259                 return -1;
1260
1261         if (vq_is_packed(dev))
1262                 vhost_vring_call_packed(dev, vq);
1263         else
1264                 vhost_vring_call_split(dev, vq);
1265
1266         return 0;
1267 }
1268
1269 uint16_t
1270 rte_vhost_avail_entries(int vid, uint16_t queue_id)
1271 {
1272         struct virtio_net *dev;
1273         struct vhost_virtqueue *vq;
1274         uint16_t ret = 0;
1275
1276         dev = get_device(vid);
1277         if (!dev)
1278                 return 0;
1279
1280         if (queue_id >= VHOST_MAX_VRING)
1281                 return 0;
1282
1283         vq = dev->virtqueue[queue_id];
1284         if (!vq)
1285                 return 0;
1286
1287         rte_spinlock_lock(&vq->access_lock);
1288
1289         if (unlikely(!vq->enabled || vq->avail == NULL))
1290                 goto out;
1291
1292         ret = *(volatile uint16_t *)&vq->avail->idx - vq->last_used_idx;
1293
1294 out:
1295         rte_spinlock_unlock(&vq->access_lock);
1296         return ret;
1297 }
1298
1299 static inline int
1300 vhost_enable_notify_split(struct virtio_net *dev,
1301                 struct vhost_virtqueue *vq, int enable)
1302 {
1303         if (vq->used == NULL)
1304                 return -1;
1305
1306         if (!(dev->features & (1ULL << VIRTIO_RING_F_EVENT_IDX))) {
1307                 if (enable)
1308                         vq->used->flags &= ~VRING_USED_F_NO_NOTIFY;
1309                 else
1310                         vq->used->flags |= VRING_USED_F_NO_NOTIFY;
1311         } else {
1312                 if (enable)
1313                         vhost_avail_event(vq) = vq->last_avail_idx;
1314         }
1315         return 0;
1316 }
1317
1318 static inline int
1319 vhost_enable_notify_packed(struct virtio_net *dev,
1320                 struct vhost_virtqueue *vq, int enable)
1321 {
1322         uint16_t flags;
1323
1324         if (vq->device_event == NULL)
1325                 return -1;
1326
1327         if (!enable) {
1328                 vq->device_event->flags = VRING_EVENT_F_DISABLE;
1329                 return 0;
1330         }
1331
1332         flags = VRING_EVENT_F_ENABLE;
1333         if (dev->features & (1ULL << VIRTIO_RING_F_EVENT_IDX)) {
1334                 flags = VRING_EVENT_F_DESC;
1335                 vq->device_event->off_wrap = vq->last_avail_idx |
1336                         vq->avail_wrap_counter << 15;
1337         }
1338
1339         rte_atomic_thread_fence(__ATOMIC_RELEASE);
1340
1341         vq->device_event->flags = flags;
1342         return 0;
1343 }
1344
1345 int
1346 vhost_enable_guest_notification(struct virtio_net *dev,
1347                 struct vhost_virtqueue *vq, int enable)
1348 {
1349         /*
1350          * If the virtqueue is not ready yet, it will be applied
1351          * when it will become ready.
1352          */
1353         if (!vq->ready)
1354                 return 0;
1355
1356         if (vq_is_packed(dev))
1357                 return vhost_enable_notify_packed(dev, vq, enable);
1358         else
1359                 return vhost_enable_notify_split(dev, vq, enable);
1360 }
1361
1362 int
1363 rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable)
1364 {
1365         struct virtio_net *dev = get_device(vid);
1366         struct vhost_virtqueue *vq;
1367         int ret;
1368
1369         if (!dev)
1370                 return -1;
1371
1372         if (queue_id >= VHOST_MAX_VRING)
1373                 return -1;
1374
1375         vq = dev->virtqueue[queue_id];
1376         if (!vq)
1377                 return -1;
1378
1379         rte_spinlock_lock(&vq->access_lock);
1380
1381         vq->notif_enable = enable;
1382         ret = vhost_enable_guest_notification(dev, vq, enable);
1383
1384         rte_spinlock_unlock(&vq->access_lock);
1385
1386         return ret;
1387 }
1388
1389 void
1390 rte_vhost_log_write(int vid, uint64_t addr, uint64_t len)
1391 {
1392         struct virtio_net *dev = get_device(vid);
1393
1394         if (dev == NULL)
1395                 return;
1396
1397         vhost_log_write(dev, addr, len);
1398 }
1399
1400 void
1401 rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
1402                          uint64_t offset, uint64_t len)
1403 {
1404         struct virtio_net *dev;
1405         struct vhost_virtqueue *vq;
1406
1407         dev = get_device(vid);
1408         if (dev == NULL)
1409                 return;
1410
1411         if (vring_idx >= VHOST_MAX_VRING)
1412                 return;
1413         vq = dev->virtqueue[vring_idx];
1414         if (!vq)
1415                 return;
1416
1417         vhost_log_used_vring(dev, vq, offset, len);
1418 }
1419
1420 uint32_t
1421 rte_vhost_rx_queue_count(int vid, uint16_t qid)
1422 {
1423         struct virtio_net *dev;
1424         struct vhost_virtqueue *vq;
1425         uint32_t ret = 0;
1426
1427         dev = get_device(vid);
1428         if (dev == NULL)
1429                 return 0;
1430
1431         if (unlikely(qid >= dev->nr_vring || (qid & 1) == 0)) {
1432                 VHOST_LOG_DATA(ERR, "(%d) %s: invalid virtqueue idx %d.\n",
1433                         dev->vid, __func__, qid);
1434                 return 0;
1435         }
1436
1437         vq = dev->virtqueue[qid];
1438         if (vq == NULL)
1439                 return 0;
1440
1441         rte_spinlock_lock(&vq->access_lock);
1442
1443         if (unlikely(vq->enabled == 0 || vq->avail == NULL))
1444                 goto out;
1445
1446         ret = *((volatile uint16_t *)&vq->avail->idx) - vq->last_avail_idx;
1447
1448 out:
1449         rte_spinlock_unlock(&vq->access_lock);
1450         return ret;
1451 }
1452
1453 struct rte_vdpa_device *
1454 rte_vhost_get_vdpa_device(int vid)
1455 {
1456         struct virtio_net *dev = get_device(vid);
1457
1458         if (dev == NULL)
1459                 return NULL;
1460
1461         return dev->vdpa_dev;
1462 }
1463
1464 int rte_vhost_get_log_base(int vid, uint64_t *log_base,
1465                 uint64_t *log_size)
1466 {
1467         struct virtio_net *dev = get_device(vid);
1468
1469         if (dev == NULL || log_base == NULL || log_size == NULL)
1470                 return -1;
1471
1472         *log_base = dev->log_base;
1473         *log_size = dev->log_size;
1474
1475         return 0;
1476 }
1477
1478 int rte_vhost_get_vring_base(int vid, uint16_t queue_id,
1479                 uint16_t *last_avail_idx, uint16_t *last_used_idx)
1480 {
1481         struct vhost_virtqueue *vq;
1482         struct virtio_net *dev = get_device(vid);
1483
1484         if (dev == NULL || last_avail_idx == NULL || last_used_idx == NULL)
1485                 return -1;
1486
1487         if (queue_id >= VHOST_MAX_VRING)
1488                 return -1;
1489
1490         vq = dev->virtqueue[queue_id];
1491         if (!vq)
1492                 return -1;
1493
1494         if (vq_is_packed(dev)) {
1495                 *last_avail_idx = (vq->avail_wrap_counter << 15) |
1496                                   vq->last_avail_idx;
1497                 *last_used_idx = (vq->used_wrap_counter << 15) |
1498                                  vq->last_used_idx;
1499         } else {
1500                 *last_avail_idx = vq->last_avail_idx;
1501                 *last_used_idx = vq->last_used_idx;
1502         }
1503
1504         return 0;
1505 }
1506
1507 int rte_vhost_set_vring_base(int vid, uint16_t queue_id,
1508                 uint16_t last_avail_idx, uint16_t last_used_idx)
1509 {
1510         struct vhost_virtqueue *vq;
1511         struct virtio_net *dev = get_device(vid);
1512
1513         if (!dev)
1514                 return -1;
1515
1516         if (queue_id >= VHOST_MAX_VRING)
1517                 return -1;
1518
1519         vq = dev->virtqueue[queue_id];
1520         if (!vq)
1521                 return -1;
1522
1523         if (vq_is_packed(dev)) {
1524                 vq->last_avail_idx = last_avail_idx & 0x7fff;
1525                 vq->avail_wrap_counter = !!(last_avail_idx & (1 << 15));
1526                 vq->last_used_idx = last_used_idx & 0x7fff;
1527                 vq->used_wrap_counter = !!(last_used_idx & (1 << 15));
1528         } else {
1529                 vq->last_avail_idx = last_avail_idx;
1530                 vq->last_used_idx = last_used_idx;
1531         }
1532
1533         return 0;
1534 }
1535
1536 int
1537 rte_vhost_get_vring_base_from_inflight(int vid,
1538                                        uint16_t queue_id,
1539                                        uint16_t *last_avail_idx,
1540                                        uint16_t *last_used_idx)
1541 {
1542         struct rte_vhost_inflight_info_packed *inflight_info;
1543         struct vhost_virtqueue *vq;
1544         struct virtio_net *dev = get_device(vid);
1545
1546         if (dev == NULL || last_avail_idx == NULL || last_used_idx == NULL)
1547                 return -1;
1548
1549         if (queue_id >= VHOST_MAX_VRING)
1550                 return -1;
1551
1552         vq = dev->virtqueue[queue_id];
1553         if (!vq)
1554                 return -1;
1555
1556         if (!vq_is_packed(dev))
1557                 return -1;
1558
1559         inflight_info = vq->inflight_packed;
1560         if (!inflight_info)
1561                 return -1;
1562
1563         *last_avail_idx = (inflight_info->old_used_wrap_counter << 15) |
1564                           inflight_info->old_used_idx;
1565         *last_used_idx = *last_avail_idx;
1566
1567         return 0;
1568 }
1569
1570 int rte_vhost_extern_callback_register(int vid,
1571                 struct rte_vhost_user_extern_ops const * const ops, void *ctx)
1572 {
1573         struct virtio_net *dev = get_device(vid);
1574
1575         if (dev == NULL || ops == NULL)
1576                 return -1;
1577
1578         dev->extern_ops = *ops;
1579         dev->extern_data = ctx;
1580         return 0;
1581 }
1582
1583 int rte_vhost_async_channel_register(int vid, uint16_t queue_id,
1584                                         uint32_t features,
1585                                         struct rte_vhost_async_channel_ops *ops)
1586 {
1587         struct vhost_virtqueue *vq;
1588         struct virtio_net *dev = get_device(vid);
1589         struct rte_vhost_async_features f;
1590         int node;
1591
1592         if (dev == NULL || ops == NULL)
1593                 return -1;
1594
1595         f.intval = features;
1596
1597         if (queue_id >= VHOST_MAX_VRING)
1598                 return -1;
1599
1600         vq = dev->virtqueue[queue_id];
1601
1602         if (unlikely(vq == NULL || !dev->async_copy))
1603                 return -1;
1604
1605         /* packed queue is not supported */
1606         if (unlikely(vq_is_packed(dev) || !f.async_inorder)) {
1607                 VHOST_LOG_CONFIG(ERR,
1608                         "async copy is not supported on packed queue or non-inorder mode "
1609                         "(vid %d, qid: %d)\n", vid, queue_id);
1610                 return -1;
1611         }
1612
1613         if (unlikely(ops->check_completed_copies == NULL ||
1614                 ops->transfer_data == NULL))
1615                 return -1;
1616
1617         rte_spinlock_lock(&vq->access_lock);
1618
1619         if (unlikely(vq->async_registered)) {
1620                 VHOST_LOG_CONFIG(ERR,
1621                         "async register failed: channel already registered "
1622                         "(vid %d, qid: %d)\n", vid, queue_id);
1623                 goto reg_out;
1624         }
1625
1626 #ifdef RTE_LIBRTE_VHOST_NUMA
1627         if (get_mempolicy(&node, NULL, 0, vq, MPOL_F_NODE | MPOL_F_ADDR)) {
1628                 VHOST_LOG_CONFIG(ERR,
1629                         "unable to get numa information in async register. "
1630                         "allocating async buffer memory on the caller thread node\n");
1631                 node = SOCKET_ID_ANY;
1632         }
1633 #else
1634         node = SOCKET_ID_ANY;
1635 #endif
1636
1637         vq->async_pkts_info = rte_malloc_socket(NULL,
1638                         vq->size * sizeof(struct async_inflight_info),
1639                         RTE_CACHE_LINE_SIZE, node);
1640         vq->it_pool = rte_malloc_socket(NULL,
1641                         VHOST_MAX_ASYNC_IT * sizeof(struct rte_vhost_iov_iter),
1642                         RTE_CACHE_LINE_SIZE, node);
1643         vq->vec_pool = rte_malloc_socket(NULL,
1644                         VHOST_MAX_ASYNC_VEC * sizeof(struct iovec),
1645                         RTE_CACHE_LINE_SIZE, node);
1646         vq->async_descs_split = rte_malloc_socket(NULL,
1647                         vq->size * sizeof(struct vring_used_elem),
1648                         RTE_CACHE_LINE_SIZE, node);
1649         if (!vq->async_descs_split || !vq->async_pkts_info ||
1650                 !vq->it_pool || !vq->vec_pool) {
1651                 vhost_free_async_mem(vq);
1652                 VHOST_LOG_CONFIG(ERR,
1653                                 "async register failed: cannot allocate memory for vq data "
1654                                 "(vid %d, qid: %d)\n", vid, queue_id);
1655                 goto reg_out;
1656         }
1657
1658         vq->async_ops.check_completed_copies = ops->check_completed_copies;
1659         vq->async_ops.transfer_data = ops->transfer_data;
1660
1661         vq->async_inorder = f.async_inorder;
1662         vq->async_threshold = f.async_threshold;
1663
1664         vq->async_registered = true;
1665
1666 reg_out:
1667         rte_spinlock_unlock(&vq->access_lock);
1668
1669         return 0;
1670 }
1671
1672 int rte_vhost_async_channel_unregister(int vid, uint16_t queue_id)
1673 {
1674         struct vhost_virtqueue *vq;
1675         struct virtio_net *dev = get_device(vid);
1676         int ret = -1;
1677
1678         if (dev == NULL)
1679                 return ret;
1680
1681         if (queue_id >= VHOST_MAX_VRING)
1682                 return ret;
1683
1684         vq = dev->virtqueue[queue_id];
1685
1686         if (vq == NULL)
1687                 return ret;
1688
1689         ret = 0;
1690
1691         if (!vq->async_registered)
1692                 return ret;
1693
1694         if (!rte_spinlock_trylock(&vq->access_lock)) {
1695                 VHOST_LOG_CONFIG(ERR, "Failed to unregister async channel. "
1696                         "virt queue busy.\n");
1697                 return -1;
1698         }
1699
1700         if (vq->async_pkts_inflight_n) {
1701                 VHOST_LOG_CONFIG(ERR, "Failed to unregister async channel. "
1702                         "async inflight packets must be completed before unregistration.\n");
1703                 ret = -1;
1704                 goto out;
1705         }
1706
1707         vhost_free_async_mem(vq);
1708
1709         vq->async_ops.transfer_data = NULL;
1710         vq->async_ops.check_completed_copies = NULL;
1711         vq->async_registered = false;
1712
1713 out:
1714         rte_spinlock_unlock(&vq->access_lock);
1715
1716         return ret;
1717 }
1718
1719 RTE_LOG_REGISTER(vhost_config_log_level, lib.vhost.config, INFO);
1720 RTE_LOG_REGISTER(vhost_data_log_level, lib.vhost.data, WARNING);