vhost: remove switching related logics
[dpdk.git] / lib / librte_vhost / virtio-net.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <dirent.h>
35 #include <fuse/cuse_lowlevel.h>
36 #include <linux/vhost.h>
37 #include <linux/virtio_net.h>
38 #include <stddef.h>
39 #include <stdint.h>
40 #include <stdlib.h>
41 #include <sys/eventfd.h>
42 #include <sys/ioctl.h>
43 #include <sys/mman.h>
44 #include <unistd.h>
45
46 #include <rte_ethdev.h>
47 #include <rte_log.h>
48 #include <rte_string_fns.h>
49 #include <rte_memory.h>
50
51 #include "main.h"
52 #include "virtio-net.h"
53 #include "vhost-net-cdev.h"
54 #include "eventfd_link/eventfd_link.h"
55
56 const char eventfd_cdev[] = "/dev/eventfd-link";
57
58 /* device ops to add/remove device to data core. */
59 static struct virtio_net_device_ops const * notify_ops;
60 /* Root address of the linked list in the configuration core. */
61 static struct virtio_net_config_ll                      *ll_root = NULL;
62
63 /* Features supported by this application. RX merge buffers are disabled by default. */
64 uint64_t VHOST_FEATURES = (0ULL << VIRTIO_NET_F_MRG_RXBUF);
65
66 /* Line size for reading maps file. */
67 const uint32_t BUFSIZE = PATH_MAX;
68
69 /* Size of prot char array in procmap. */
70 #define PROT_SZ 5
71
72 /* Number of elements in procmap struct. */
73 #define PROCMAP_SZ 8
74
75 /* Structure containing information gathered from maps file. */
76 struct procmap
77 {
78         uint64_t        va_start;                       /* Start virtual address in file. */
79         uint64_t        len;                            /* Size of file. */
80         uint64_t        pgoff;                          /* Not used. */
81         uint32_t        maj;                            /* Not used. */
82         uint32_t        min;                            /* Not used. */
83         uint32_t        ino;                            /* Not used. */
84         char            prot[PROT_SZ];          /* Not used. */
85         char            fname[PATH_MAX];        /* File name. */
86 };
87
88 /*
89  * Converts QEMU virtual address to Vhost virtual address. This function is used
90  * to convert the ring addresses to our address space.
91  */
92 static uint64_t
93 qva_to_vva(struct virtio_net *dev, uint64_t qemu_va)
94 {
95         struct virtio_memory_regions *region;
96         uint64_t vhost_va = 0;
97         uint32_t regionidx = 0;
98
99         /* Find the region where the address lives. */
100         for (regionidx = 0; regionidx < dev->mem->nregions; regionidx++) {
101                 region = &dev->mem->regions[regionidx];
102                 if ((qemu_va >= region->userspace_address) &&
103                                 (qemu_va <= region->userspace_address +
104                                 region->memory_size)) {
105                         vhost_va = dev->mem->mapped_address + qemu_va - dev->mem->base_address;
106                         break;
107                 }
108         }
109         return vhost_va;
110 }
111
112 /*
113  * Locate the file containing QEMU's memory space and map it to our address space.
114  */
115 static int
116 host_memory_map (struct virtio_net *dev, struct virtio_memory *mem, pid_t pid, uint64_t addr)
117 {
118         struct dirent *dptr = NULL;
119         struct procmap procmap;
120         DIR *dp = NULL;
121         int fd;
122         int i;
123         char memfile[PATH_MAX];
124         char mapfile[PATH_MAX];
125         char procdir[PATH_MAX];
126         char resolved_path[PATH_MAX];
127         FILE            *fmap;
128         void            *map;
129         uint8_t         found = 0;
130         char            line[BUFSIZE];
131         char dlm[] = "-   :   ";
132         char *str, *sp, *in[PROCMAP_SZ];
133         char *end = NULL;
134
135         /* Path where mem files are located. */
136         snprintf (procdir, PATH_MAX, "/proc/%u/fd/", pid);
137         /* Maps file used to locate mem file. */
138         snprintf (mapfile, PATH_MAX, "/proc/%u/maps", pid);
139
140         fmap = fopen(mapfile, "r");
141         if (fmap == NULL) {
142                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to open maps file for pid %d\n", dev->device_fh, pid);
143                 return -1;
144         }
145
146         /* Read through maps file until we find out base_address. */
147         while (fgets(line, BUFSIZE, fmap) != 0) {
148                 str = line;
149                 errno = 0;
150                 /* Split line in to fields. */
151                 for (i = 0; i < PROCMAP_SZ; i++) {
152                         if (((in[i] = strtok_r(str, &dlm[i], &sp)) == NULL) || (errno != 0)) {
153                                 fclose(fmap);
154                                 return -1;
155                         }
156                         str = NULL;
157                 }
158
159                 /* Convert/Copy each field as needed. */
160                 procmap.va_start = strtoull(in[0], &end, 16);
161                 if ((in[0] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) {
162                         fclose(fmap);
163                         return -1;
164                 }
165
166                 procmap.len = strtoull(in[1], &end, 16);
167                 if ((in[1] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) {
168                         fclose(fmap);
169                         return -1;
170                 }
171
172                 procmap.pgoff = strtoull(in[3], &end, 16);
173                 if ((in[3] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) {
174                         fclose(fmap);
175                         return -1;
176                 }
177
178                 procmap.maj = strtoul(in[4], &end, 16);
179                 if ((in[4] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) {
180                         fclose(fmap);
181                         return -1;
182                 }
183
184                 procmap.min = strtoul(in[5], &end, 16);
185                 if ((in[5] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) {
186                         fclose(fmap);
187                         return -1;
188                 }
189
190                 procmap.ino = strtoul(in[6], &end, 16);
191                 if ((in[6] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) {
192                         fclose(fmap);
193                         return -1;
194                 }
195
196                 memcpy(&procmap.prot, in[2], PROT_SZ);
197                 memcpy(&procmap.fname, in[7], PATH_MAX);
198
199                 if (procmap.va_start == addr) {
200                         procmap.len = procmap.len - procmap.va_start;
201                         found = 1;
202                         break;
203                 }
204         }
205         fclose(fmap);
206
207         if (!found) {
208                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find memory file in pid %d maps file\n", dev->device_fh, pid);
209                 return -1;
210         }
211
212         /* Find the guest memory file among the process fds. */
213         dp = opendir(procdir);
214         if (dp == NULL) {
215                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Cannot open pid %d process directory \n", dev->device_fh, pid);
216                 return -1;
217
218         }
219
220         found = 0;
221
222         /* Read the fd directory contents. */
223         while (NULL != (dptr = readdir(dp))) {
224                 snprintf (memfile, PATH_MAX, "/proc/%u/fd/%s", pid, dptr->d_name);
225             realpath(memfile, resolved_path);
226                 if (resolved_path == NULL) {
227                         RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to resolve fd directory\n", dev->device_fh);
228                         closedir(dp);
229                         return -1;
230                 }
231                 if (strncmp(resolved_path, procmap.fname,
232                         strnlen(procmap.fname, PATH_MAX)) == 0) {
233                         found = 1;
234                         break;
235                 }
236         }
237
238         closedir(dp);
239
240         if (found == 0) {
241                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find memory file for pid %d\n", dev->device_fh, pid);
242                 return -1;
243         }
244         /* Open the shared memory file and map the memory into this process. */
245         fd = open(memfile, O_RDWR);
246
247         if (fd == -1) {
248                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to open %s for pid %d\n", dev->device_fh, memfile, pid);
249                 return -1;
250         }
251
252         map = mmap(0, (size_t)procmap.len, PROT_READ|PROT_WRITE , MAP_POPULATE|MAP_SHARED, fd, 0);
253         close (fd);
254
255         if (map == MAP_FAILED) {
256                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Error mapping the file %s for pid %d\n",  dev->device_fh, memfile, pid);
257                 return -1;
258         }
259
260         /* Store the memory address and size in the device data structure */
261         mem->mapped_address = (uint64_t)(uintptr_t)map;
262         mem->mapped_size = procmap.len;
263
264         LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") Mem File: %s->%s - Size: %llu - VA: %p\n", dev->device_fh,
265                 memfile, resolved_path, (long long unsigned)mem->mapped_size, map);
266
267         return 0;
268 }
269
270 /*
271  * Retrieves an entry from the devices configuration linked list.
272  */
273 static struct virtio_net_config_ll *
274 get_config_ll_entry(struct vhost_device_ctx ctx)
275 {
276         struct virtio_net_config_ll *ll_dev = ll_root;
277
278         /* Loop through linked list until the device_fh is found. */
279         while (ll_dev != NULL) {
280                 if (ll_dev->dev.device_fh == ctx.fh)
281                         return ll_dev;
282                 ll_dev = ll_dev->next;
283         }
284
285         return NULL;
286 }
287
288 /*
289  * Searches the configuration core linked list and retrieves the device if it exists.
290  */
291 static struct virtio_net *
292 get_device(struct vhost_device_ctx ctx)
293 {
294         struct virtio_net_config_ll *ll_dev;
295
296         ll_dev = get_config_ll_entry(ctx);
297
298         /* If a matching entry is found in the linked list, return the device in that entry. */
299         if (ll_dev) {
300                 return &ll_dev->dev;
301         }
302
303         RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Device not found in linked list.\n", ctx.fh);
304         return NULL;
305 }
306
307 /*
308  * Add entry containing a device to the device configuration linked list.
309  */
310 static void
311 add_config_ll_entry(struct virtio_net_config_ll *new_ll_dev)
312 {
313         struct virtio_net_config_ll *ll_dev = ll_root;
314
315         /* If ll_dev == NULL then this is the first device so go to else */
316         if (ll_dev) {
317                 /* If the 1st device_fh != 0 then we insert our device here. */
318                 if (ll_dev->dev.device_fh != 0) {
319                         new_ll_dev->dev.device_fh = 0;
320                         new_ll_dev->next = ll_dev;
321                         ll_root = new_ll_dev;
322                 } else {
323                         /* Increment through the ll until we find un unused device_fh. Insert the device at that entry*/
324                         while ((ll_dev->next != NULL) && (ll_dev->dev.device_fh == (ll_dev->next->dev.device_fh - 1)))
325                                 ll_dev = ll_dev->next;
326
327                         new_ll_dev->dev.device_fh = ll_dev->dev.device_fh + 1;
328                         new_ll_dev->next = ll_dev->next;
329                         ll_dev->next = new_ll_dev;
330                 }
331         } else {
332                 ll_root = new_ll_dev;
333                 ll_root->dev.device_fh = 0;
334         }
335
336 }
337
338 /*
339  * Unmap any memory, close any file descriptors and free any memory owned by a device.
340  */
341 static void
342 cleanup_device(struct virtio_net *dev)
343 {
344         /* Unmap QEMU memory file if mapped. */
345         if (dev->mem) {
346                 munmap((void*)(uintptr_t)dev->mem->mapped_address, (size_t)dev->mem->mapped_size);
347                 if (dev->mem->regions_hpa)
348                         free(dev->mem->regions_hpa);
349                 free(dev->mem);
350         }
351
352         /* Close any event notifiers opened by device. */
353         if (dev->virtqueue[VIRTIO_RXQ]->callfd)
354                 close((int)dev->virtqueue[VIRTIO_RXQ]->callfd);
355         if (dev->virtqueue[VIRTIO_RXQ]->kickfd)
356                 close((int)dev->virtqueue[VIRTIO_RXQ]->kickfd);
357         if (dev->virtqueue[VIRTIO_TXQ]->callfd)
358                 close((int)dev->virtqueue[VIRTIO_TXQ]->callfd);
359         if (dev->virtqueue[VIRTIO_TXQ]->kickfd)
360                 close((int)dev->virtqueue[VIRTIO_TXQ]->kickfd);
361 }
362
363 /*
364  * Release virtqueues and device memory.
365  */
366 static void
367 free_device(struct virtio_net_config_ll *ll_dev)
368 {
369         /* Free any malloc'd memory */
370         free(ll_dev->dev.virtqueue[VIRTIO_RXQ]);
371         free(ll_dev->dev.virtqueue[VIRTIO_TXQ]);
372         free(ll_dev);
373 }
374 /*
375  * Remove an entry from the device configuration linked list.
376  */
377 static struct virtio_net_config_ll *
378 rm_config_ll_entry(struct virtio_net_config_ll *ll_dev, struct virtio_net_config_ll *ll_dev_last)
379 {
380         /* First remove the device and then clean it up. */
381         if (ll_dev == ll_root) {
382                 ll_root = ll_dev->next;
383                 cleanup_device(&ll_dev->dev);
384                 free_device(ll_dev);
385                 return ll_root;
386         } else {
387                 if (likely(ll_dev_last != NULL)) {
388                         ll_dev_last->next = ll_dev->next;
389                         cleanup_device(&ll_dev->dev);
390                         free_device(ll_dev);
391                         return ll_dev_last->next;
392                 } else {
393                         cleanup_device(&ll_dev->dev);
394                         free_device(ll_dev);
395                         RTE_LOG(ERR, VHOST_CONFIG, "Remove entry from config_ll failed\n");
396                         return NULL;
397                 }
398         }
399 }
400
401 /*
402  *  Initialise all variables in device structure.
403  */
404 static void
405 init_device(struct virtio_net *dev)
406 {
407         uint64_t vq_offset;
408
409         /* Virtqueues have already been malloced so we don't want to set them to NULL. */
410         vq_offset = offsetof(struct virtio_net, mem);
411
412         /* Set everything to 0. */
413         memset((void*)(uintptr_t)((uint64_t)(uintptr_t)dev + vq_offset), 0,
414                 (sizeof(struct virtio_net) - (size_t)vq_offset));
415         memset(dev->virtqueue[VIRTIO_RXQ], 0, sizeof(struct vhost_virtqueue));
416         memset(dev->virtqueue[VIRTIO_TXQ], 0, sizeof(struct vhost_virtqueue));
417
418         /* Backends are set to -1 indicating an inactive device. */
419         dev->virtqueue[VIRTIO_RXQ]->backend = VIRTIO_DEV_STOPPED;
420         dev->virtqueue[VIRTIO_TXQ]->backend = VIRTIO_DEV_STOPPED;
421 }
422
423 /*
424  * Function is called from the CUSE open function. The device structure is
425  * initialised and a new entry is added to the device configuration linked
426  * list.
427  */
428 static int
429 new_device(struct vhost_device_ctx ctx)
430 {
431         struct virtio_net_config_ll *new_ll_dev;
432         struct vhost_virtqueue *virtqueue_rx, *virtqueue_tx;
433
434         /* Setup device and virtqueues. */
435         new_ll_dev = malloc(sizeof(struct virtio_net_config_ll));
436         if (new_ll_dev == NULL) {
437                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to allocate memory for dev.\n", ctx.fh);
438                 return -1;
439         }
440
441         virtqueue_rx = malloc(sizeof(struct vhost_virtqueue));
442         if (virtqueue_rx == NULL) {
443                 free(new_ll_dev);
444                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to allocate memory for virtqueue_rx.\n", ctx.fh);
445                 return -1;
446         }
447
448         virtqueue_tx = malloc(sizeof(struct vhost_virtqueue));
449         if (virtqueue_tx == NULL) {
450                 free(virtqueue_rx);
451                 free(new_ll_dev);
452                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to allocate memory for virtqueue_tx.\n", ctx.fh);
453                 return -1;
454         }
455
456         new_ll_dev->dev.virtqueue[VIRTIO_RXQ] = virtqueue_rx;
457         new_ll_dev->dev.virtqueue[VIRTIO_TXQ] = virtqueue_tx;
458
459         /* Initialise device and virtqueues. */
460         init_device(&new_ll_dev->dev);
461
462         new_ll_dev->next = NULL;
463
464         /* Add entry to device configuration linked list. */
465         add_config_ll_entry(new_ll_dev);
466
467         return new_ll_dev->dev.device_fh;
468 }
469
470 /*
471  * Function is called from the CUSE release function. This function will cleanup
472  * the device and remove it from device configuration linked list.
473  */
474 static void
475 destroy_device(struct vhost_device_ctx ctx)
476 {
477         struct virtio_net_config_ll *ll_dev_cur_ctx, *ll_dev_last = NULL;
478         struct virtio_net_config_ll *ll_dev_cur = ll_root;
479
480         /* Find the linked list entry for the device to be removed. */
481         ll_dev_cur_ctx = get_config_ll_entry(ctx);
482         while (ll_dev_cur != NULL) {
483                 /* If the device is found or a device that doesn't exist is found then it is removed. */
484                 if (ll_dev_cur == ll_dev_cur_ctx) {
485                         /*
486                          * If the device is running on a data core then call the function to remove it from
487                          * the data core.
488                          */
489                         if ((ll_dev_cur->dev.flags & VIRTIO_DEV_RUNNING))
490                                 notify_ops->destroy_device(&(ll_dev_cur->dev));
491                         ll_dev_cur = rm_config_ll_entry(ll_dev_cur, ll_dev_last);
492                 } else {
493                         ll_dev_last = ll_dev_cur;
494                         ll_dev_cur = ll_dev_cur->next;
495                 }
496         }
497 }
498
499 /*
500  * Called from CUSE IOCTL: VHOST_SET_OWNER
501  * This function just returns success at the moment unless the device hasn't been initialised.
502  */
503 static int
504 set_owner(struct vhost_device_ctx ctx)
505 {
506         struct virtio_net *dev;
507
508         dev = get_device(ctx);
509         if (dev == NULL)
510                 return -1;
511
512         return 0;
513 }
514
515 /*
516  * Called from CUSE IOCTL: VHOST_RESET_OWNER
517  */
518 static int
519 reset_owner(struct vhost_device_ctx ctx)
520 {
521         struct virtio_net_config_ll *ll_dev;
522
523         ll_dev = get_config_ll_entry(ctx);
524
525         cleanup_device(&ll_dev->dev);
526         init_device(&ll_dev->dev);
527
528         return 0;
529 }
530
531 /*
532  * Called from CUSE IOCTL: VHOST_GET_FEATURES
533  * The features that we support are requested.
534  */
535 static int
536 get_features(struct vhost_device_ctx ctx, uint64_t *pu)
537 {
538         struct virtio_net *dev;
539
540         dev = get_device(ctx);
541         if (dev == NULL)
542                 return -1;
543
544         /* Send our supported features. */
545         *pu = VHOST_FEATURES;
546         return 0;
547 }
548
549 /*
550  * Called from CUSE IOCTL: VHOST_SET_FEATURES
551  * We receive the negotiated set of features supported by us and the virtio device.
552  */
553 static int
554 set_features(struct vhost_device_ctx ctx, uint64_t *pu)
555 {
556         struct virtio_net *dev;
557
558         dev = get_device(ctx);
559         if (dev == NULL)
560                 return -1;
561         if (*pu & ~VHOST_FEATURES)
562                 return -1;
563
564         /* Store the negotiated feature list for the device. */
565         dev->features = *pu;
566
567         /* Set the vhost_hlen depending on if VIRTIO_NET_F_MRG_RXBUF is set. */
568         if (dev->features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
569                 LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") Mergeable RX buffers enabled\n", dev->device_fh);
570                 dev->virtqueue[VIRTIO_RXQ]->vhost_hlen = sizeof(struct virtio_net_hdr_mrg_rxbuf);
571                 dev->virtqueue[VIRTIO_TXQ]->vhost_hlen = sizeof(struct virtio_net_hdr_mrg_rxbuf);
572         } else {
573                 LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") Mergeable RX buffers disabled\n", dev->device_fh);
574                 dev->virtqueue[VIRTIO_RXQ]->vhost_hlen = sizeof(struct virtio_net_hdr);
575                 dev->virtqueue[VIRTIO_TXQ]->vhost_hlen = sizeof(struct virtio_net_hdr);
576         }
577         return 0;
578 }
579
580 /*
581  * Calculate the region count of physical continous regions for one particular
582  * region of whose vhost virtual address is continous. The particular region
583  * start from vva_start, with size of 'size' in argument.
584  */
585 static uint32_t check_hpa_regions(uint64_t vva_start, uint64_t size)
586 {
587         uint32_t i, nregions = 0, page_size = PAGE_SIZE;
588         uint64_t cur_phys_addr = 0, next_phys_addr = 0;
589         if (vva_start % page_size) {
590                 LOG_DEBUG(VHOST_CONFIG,
591                         "in check_countinous: vva start(%p) mod page_size(%d) "
592                         "has remainder\n",
593                         (void *)(uintptr_t)vva_start, page_size);
594                 return 0;
595         }
596         if (size % page_size) {
597                 LOG_DEBUG(VHOST_CONFIG,
598                         "in check_countinous: "
599                         "size((%"PRIu64")) mod page_size(%d) has remainder\n",
600                         size, page_size);
601                 return 0;
602         }
603         for (i = 0; i < size - page_size; i = i + page_size) {
604                 cur_phys_addr
605                         = rte_mem_virt2phy((void *)(uintptr_t)(vva_start + i));
606                 next_phys_addr = rte_mem_virt2phy(
607                         (void *)(uintptr_t)(vva_start + i + page_size));
608                 if ((cur_phys_addr + page_size) != next_phys_addr) {
609                         ++nregions;
610                         LOG_DEBUG(VHOST_CONFIG,
611                                 "in check_continuous: hva addr:(%p) is not "
612                                 "continuous with hva addr:(%p), diff:%d\n",
613                                 (void *)(uintptr_t)(vva_start + (uint64_t)i),
614                                 (void *)(uintptr_t)(vva_start + (uint64_t)i
615                                 + page_size), page_size);
616                         LOG_DEBUG(VHOST_CONFIG,
617                                 "in check_continuous: hpa addr:(%p) is not "
618                                 "continuous with hpa addr:(%p), "
619                                 "diff:(%"PRIu64")\n",
620                                 (void *)(uintptr_t)cur_phys_addr,
621                                 (void *)(uintptr_t)next_phys_addr,
622                                 (next_phys_addr-cur_phys_addr));
623                 }
624         }
625         return nregions;
626 }
627
628 /*
629  * Divide each region whose vhost virtual address is continous into a few
630  * sub-regions, make sure the physical address within each sub-region are
631  * continous. And fill offset(to GPA) and size etc. information of each
632  * sub-region into regions_hpa.
633  */
634 static uint32_t fill_hpa_memory_regions(void *memory)
635 {
636         uint32_t regionidx, regionidx_hpa = 0, i, k, page_size = PAGE_SIZE;
637         uint64_t cur_phys_addr = 0, next_phys_addr = 0, vva_start;
638         struct virtio_memory *virtio_memory = (struct virtio_memory *)memory;
639         struct virtio_memory_regions_hpa *mem_region_hpa
640                 = virtio_memory->regions_hpa;
641
642         if (mem_region_hpa == NULL)
643                 return 0;
644
645         for (regionidx = 0; regionidx < virtio_memory->nregions; regionidx++) {
646                 vva_start = virtio_memory->regions[regionidx].guest_phys_address
647                         + virtio_memory->regions[regionidx].address_offset;
648                 mem_region_hpa[regionidx_hpa].guest_phys_address
649                         = virtio_memory->regions[regionidx].guest_phys_address;
650                 mem_region_hpa[regionidx_hpa].host_phys_addr_offset =
651                         rte_mem_virt2phy((void *)(uintptr_t)(vva_start))
652                         - mem_region_hpa[regionidx_hpa].guest_phys_address;
653                 LOG_DEBUG(VHOST_CONFIG,
654                         "in fill_hpa_regions: guest phys addr start[%d]:(%p)\n",
655                         regionidx_hpa,
656                         (void *)(uintptr_t)
657                         (mem_region_hpa[regionidx_hpa].guest_phys_address));
658                 LOG_DEBUG(VHOST_CONFIG,
659                         "in fill_hpa_regions: host  phys addr start[%d]:(%p)\n",
660                         regionidx_hpa,
661                         (void *)(uintptr_t)
662                         (mem_region_hpa[regionidx_hpa].host_phys_addr_offset));
663                 for (i = 0, k = 0;
664                         i < virtio_memory->regions[regionidx].memory_size
665                                 - page_size;
666                         i += page_size) {
667                         cur_phys_addr = rte_mem_virt2phy(
668                                         (void *)(uintptr_t)(vva_start + i));
669                         next_phys_addr = rte_mem_virt2phy(
670                                         (void *)(uintptr_t)(vva_start
671                                         + i + page_size));
672                         if ((cur_phys_addr + page_size) != next_phys_addr) {
673                                 mem_region_hpa[regionidx_hpa].guest_phys_address_end =
674                                         mem_region_hpa[regionidx_hpa].guest_phys_address
675                                         + k + page_size;
676                                 mem_region_hpa[regionidx_hpa].memory_size
677                                         = k + page_size;
678                                 LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: guest "
679                                         "phys addr end  [%d]:(%p)\n",
680                                         regionidx_hpa,
681                                         (void *)(uintptr_t)
682                                         (mem_region_hpa[regionidx_hpa].guest_phys_address_end));
683                                 LOG_DEBUG(VHOST_CONFIG,
684                                         "in fill_hpa_regions: guest phys addr "
685                                         "size [%d]:(%p)\n",
686                                         regionidx_hpa,
687                                         (void *)(uintptr_t)
688                                         (mem_region_hpa[regionidx_hpa].memory_size));
689                                 mem_region_hpa[regionidx_hpa + 1].guest_phys_address
690                                         = mem_region_hpa[regionidx_hpa].guest_phys_address_end;
691                                 ++regionidx_hpa;
692                                 mem_region_hpa[regionidx_hpa].host_phys_addr_offset =
693                                         next_phys_addr
694                                         - mem_region_hpa[regionidx_hpa].guest_phys_address;
695                                 LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: guest"
696                                         " phys addr start[%d]:(%p)\n",
697                                         regionidx_hpa,
698                                         (void *)(uintptr_t)
699                                         (mem_region_hpa[regionidx_hpa].guest_phys_address));
700                                 LOG_DEBUG(VHOST_CONFIG,
701                                         "in fill_hpa_regions: host  phys addr "
702                                         "start[%d]:(%p)\n",
703                                         regionidx_hpa,
704                                         (void *)(uintptr_t)
705                                         (mem_region_hpa[regionidx_hpa].host_phys_addr_offset));
706                                 k = 0;
707                         } else {
708                                 k += page_size;
709                         }
710                 }
711                 mem_region_hpa[regionidx_hpa].guest_phys_address_end
712                         = mem_region_hpa[regionidx_hpa].guest_phys_address
713                         + k + page_size;
714                 mem_region_hpa[regionidx_hpa].memory_size = k + page_size;
715                 LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: guest phys addr end  "
716                         "[%d]:(%p)\n", regionidx_hpa,
717                         (void *)(uintptr_t)
718                         (mem_region_hpa[regionidx_hpa].guest_phys_address_end));
719                 LOG_DEBUG(VHOST_CONFIG, "in fill_hpa_regions: guest phys addr size "
720                         "[%d]:(%p)\n", regionidx_hpa,
721                         (void *)(uintptr_t)
722                         (mem_region_hpa[regionidx_hpa].memory_size));
723                 ++regionidx_hpa;
724         }
725         return regionidx_hpa;
726 }
727
728 /*
729  * Called from CUSE IOCTL: VHOST_SET_MEM_TABLE
730  * This function creates and populates the memory structure for the device. This includes
731  * storing offsets used to translate buffer addresses.
732  */
733 static int
734 set_mem_table(struct vhost_device_ctx ctx, const void *mem_regions_addr, uint32_t nregions)
735 {
736         struct virtio_net *dev;
737         struct vhost_memory_region *mem_regions;
738         struct virtio_memory *mem;
739         uint64_t size = offsetof(struct vhost_memory, regions);
740         uint32_t regionidx, valid_regions;
741
742         dev = get_device(ctx);
743         if (dev == NULL)
744                 return -1;
745
746         if (dev->mem) {
747                 munmap((void*)(uintptr_t)dev->mem->mapped_address, (size_t)dev->mem->mapped_size);
748                 free(dev->mem);
749         }
750
751         /* Malloc the memory structure depending on the number of regions. */
752         mem = calloc(1, sizeof(struct virtio_memory) + (sizeof(struct virtio_memory_regions) * nregions));
753         if (mem == NULL) {
754                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to allocate memory for dev->mem.\n", dev->device_fh);
755                 return -1;
756         }
757
758         mem->nregions = nregions;
759
760         mem_regions = (void*)(uintptr_t)((uint64_t)(uintptr_t)mem_regions_addr + size);
761
762         for (regionidx = 0; regionidx < mem->nregions; regionidx++) {
763                 /* Populate the region structure for each region. */
764                 mem->regions[regionidx].guest_phys_address = mem_regions[regionidx].guest_phys_addr;
765                 mem->regions[regionidx].guest_phys_address_end = mem->regions[regionidx].guest_phys_address +
766                         mem_regions[regionidx].memory_size;
767                 mem->regions[regionidx].memory_size = mem_regions[regionidx].memory_size;
768                 mem->regions[regionidx].userspace_address = mem_regions[regionidx].userspace_addr;
769
770                 LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") REGION: %u - GPA: %p - QEMU VA: %p - SIZE (%"PRIu64")\n", dev->device_fh,
771                                 regionidx, (void*)(uintptr_t)mem->regions[regionidx].guest_phys_address,
772                                 (void*)(uintptr_t)mem->regions[regionidx].userspace_address,
773                                 mem->regions[regionidx].memory_size);
774
775                 /*set the base address mapping*/
776                 if (mem->regions[regionidx].guest_phys_address == 0x0) {
777                         mem->base_address = mem->regions[regionidx].userspace_address;
778                         /* Map VM memory file */
779                         if (host_memory_map(dev, mem, ctx.pid, mem->base_address) != 0) {
780                                 free(mem);
781                                 return -1;
782                         }
783                 }
784         }
785
786         /* Check that we have a valid base address. */
787         if (mem->base_address == 0) {
788                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find base address of qemu memory file.\n", dev->device_fh);
789                 free(mem);
790                 return -1;
791         }
792
793         /* Check if all of our regions have valid mappings. Usually one does not exist in the QEMU memory file. */
794         valid_regions = mem->nregions;
795         for (regionidx = 0; regionidx < mem->nregions; regionidx++) {
796                 if ((mem->regions[regionidx].userspace_address < mem->base_address) ||
797                         (mem->regions[regionidx].userspace_address > (mem->base_address + mem->mapped_size)))
798                                 valid_regions--;
799         }
800
801         /* If a region does not have a valid mapping we rebuild our memory struct to contain only valid entries. */
802         if (valid_regions != mem->nregions) {
803                 LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") Not all memory regions exist in the QEMU mem file. Re-populating mem structure\n",
804                         dev->device_fh);
805
806                 /* Re-populate the memory structure with only valid regions. Invalid regions are over-written with memmove. */
807                 valid_regions = 0;
808
809                 for (regionidx = mem->nregions; 0 != regionidx--;) {
810                         if ((mem->regions[regionidx].userspace_address < mem->base_address) ||
811                                         (mem->regions[regionidx].userspace_address > (mem->base_address + mem->mapped_size))) {
812                                 memmove(&mem->regions[regionidx], &mem->regions[regionidx + 1],
813                                         sizeof(struct virtio_memory_regions) * valid_regions);
814                         } else {
815                                 valid_regions++;
816                         }
817                 }
818         }
819         mem->nregions = valid_regions;
820         mem->nregions_hpa = mem->nregions;
821         dev->mem = mem;
822
823         /*
824          * Calculate the address offset for each region. This offset is used to identify the vhost virtual address
825          * corresponding to a QEMU guest physical address.
826          */
827         for (regionidx = 0; regionidx < dev->mem->nregions; regionidx++) {
828                 dev->mem->regions[regionidx].address_offset = dev->mem->regions[regionidx].userspace_address - dev->mem->base_address
829                         + dev->mem->mapped_address - dev->mem->regions[regionidx].guest_phys_address;
830
831                 dev->mem->nregions_hpa
832                         += check_hpa_regions(
833                                 dev->mem->regions[regionidx].guest_phys_address
834                                 + dev->mem->regions[regionidx].address_offset,
835                                 dev->mem->regions[regionidx].memory_size);
836         }
837         if (dev->mem->regions_hpa != NULL) {
838                 free(dev->mem->regions_hpa);
839                 dev->mem->regions_hpa = NULL;
840         }
841
842         dev->mem->regions_hpa = (struct virtio_memory_regions_hpa *) calloc(1,
843                 (sizeof(struct virtio_memory_regions_hpa)
844                 * dev->mem->nregions_hpa));
845         if (dev->mem->regions_hpa == NULL) {
846                 RTE_LOG(ERR, VHOST_CONFIG,
847                         "(%"PRIu64") Failed to allocate memory for "
848                         "dev->mem->regions_hpa.\n", dev->device_fh);
849                 return -1;
850         }
851         if (fill_hpa_memory_regions(
852                 (void *)dev->mem) != dev->mem->nregions_hpa) {
853                 RTE_LOG(ERR, VHOST_CONFIG,
854                         "in set_mem_table: hpa memory regions number mismatch: "
855                         "[%d]\n", dev->mem->nregions_hpa);
856                 return -1;
857         }
858
859         return 0;
860 }
861
862 /*
863  * Called from CUSE IOCTL: VHOST_SET_VRING_NUM
864  * The virtio device sends us the size of the descriptor ring.
865  */
866 static int
867 set_vring_num(struct vhost_device_ctx ctx, struct vhost_vring_state *state)
868 {
869         struct virtio_net *dev;
870
871         dev = get_device(ctx);
872         if (dev == NULL)
873                 return -1;
874
875         /* State->index refers to the queue index. The TX queue is 1, RX queue is 0. */
876         dev->virtqueue[state->index]->size = state->num;
877
878         return 0;
879 }
880
881 /*
882  * Called from CUSE IOCTL: VHOST_SET_VRING_ADDR
883  * The virtio device sends us the desc, used and avail ring addresses. This function
884  * then converts these to our address space.
885  */
886 static int
887 set_vring_addr(struct vhost_device_ctx ctx, struct vhost_vring_addr *addr)
888 {
889         struct virtio_net *dev;
890         struct vhost_virtqueue *vq;
891
892         dev = get_device(ctx);
893         if (dev == NULL)
894                 return -1;
895
896         /* addr->index refers to the queue index. The TX queue is 1, RX queue is 0. */
897         vq = dev->virtqueue[addr->index];
898
899         /* The addresses are converted from QEMU virtual to Vhost virtual. */
900         vq->desc = (struct vring_desc*)(uintptr_t)qva_to_vva(dev, addr->desc_user_addr);
901         if (vq->desc == 0) {
902                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find descriptor ring address.\n", dev->device_fh);
903                 return -1;
904         }
905
906         vq->avail = (struct vring_avail*)(uintptr_t)qva_to_vva(dev, addr->avail_user_addr);
907         if (vq->avail == 0) {
908                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find available ring address.\n", dev->device_fh);
909                 return -1;
910         }
911
912         vq->used = (struct vring_used*)(uintptr_t)qva_to_vva(dev, addr->used_user_addr);
913         if (vq->used == 0) {
914                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find used ring address.\n", dev->device_fh);
915                 return -1;
916         }
917
918         LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") mapped address desc: %p\n", dev->device_fh, vq->desc);
919         LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") mapped address avail: %p\n", dev->device_fh, vq->avail);
920         LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") mapped address used: %p\n", dev->device_fh, vq->used);
921
922         return 0;
923 }
924
925 /*
926  * Called from CUSE IOCTL: VHOST_SET_VRING_BASE
927  * The virtio device sends us the available ring last used index.
928  */
929 static int
930 set_vring_base(struct vhost_device_ctx ctx, struct vhost_vring_state *state)
931 {
932         struct virtio_net *dev;
933
934         dev = get_device(ctx);
935         if (dev == NULL)
936                 return -1;
937
938         /* State->index refers to the queue index. The TX queue is 1, RX queue is 0. */
939         dev->virtqueue[state->index]->last_used_idx = state->num;
940         dev->virtqueue[state->index]->last_used_idx_res = state->num;
941
942         return 0;
943 }
944
945 /*
946  * Called from CUSE IOCTL: VHOST_GET_VRING_BASE
947  * We send the virtio device our available ring last used index.
948  */
949 static int
950 get_vring_base(struct vhost_device_ctx ctx, uint32_t index, struct vhost_vring_state *state)
951 {
952         struct virtio_net *dev;
953
954         dev = get_device(ctx);
955         if (dev == NULL)
956                 return -1;
957
958         state->index = index;
959         /* State->index refers to the queue index. The TX queue is 1, RX queue is 0. */
960         state->num = dev->virtqueue[state->index]->last_used_idx;
961
962         return 0;
963 }
964
965 /*
966  * This function uses the eventfd_link kernel module to copy an eventfd file descriptor
967  * provided by QEMU in to our process space.
968  */
969 static int
970 eventfd_copy(struct virtio_net *dev, struct eventfd_copy *eventfd_copy)
971 {
972         int eventfd_link, ret;
973
974         /* Open the character device to the kernel module. */
975         eventfd_link = open(eventfd_cdev, O_RDWR);
976         if (eventfd_link < 0) {
977                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") eventfd_link module is not loaded\n",  dev->device_fh);
978                 return -1;
979         }
980
981         /* Call the IOCTL to copy the eventfd. */
982         ret = ioctl(eventfd_link, EVENTFD_COPY, eventfd_copy);
983         close(eventfd_link);
984
985         if (ret < 0) {
986                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") EVENTFD_COPY ioctl failed\n",  dev->device_fh);
987                 return -1;
988         }
989
990
991         return 0;
992 }
993
994 /*
995  * Called from CUSE IOCTL: VHOST_SET_VRING_CALL
996  * The virtio device sends an eventfd to interrupt the guest. This fd gets copied in
997  * to our process space.
998  */
999 static int
1000 set_vring_call(struct vhost_device_ctx ctx, struct vhost_vring_file *file)
1001 {
1002         struct virtio_net *dev;
1003         struct eventfd_copy     eventfd_kick;
1004         struct vhost_virtqueue *vq;
1005
1006         dev = get_device(ctx);
1007         if (dev == NULL)
1008                 return -1;
1009
1010         /* file->index refers to the queue index. The TX queue is 1, RX queue is 0. */
1011         vq = dev->virtqueue[file->index];
1012
1013         if (vq->kickfd)
1014                 close((int)vq->kickfd);
1015
1016         /* Populate the eventfd_copy structure and call eventfd_copy. */
1017         vq->kickfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
1018         eventfd_kick.source_fd = vq->kickfd;
1019         eventfd_kick.target_fd = file->fd;
1020         eventfd_kick.target_pid = ctx.pid;
1021
1022         if (eventfd_copy(dev, &eventfd_kick))
1023                 return -1;
1024
1025         return 0;
1026 }
1027
1028 /*
1029  * Called from CUSE IOCTL: VHOST_SET_VRING_KICK
1030  * The virtio device sends an eventfd that it can use to notify us. This fd gets copied in
1031  * to our process space.
1032  */
1033 static int
1034 set_vring_kick(struct vhost_device_ctx ctx, struct vhost_vring_file *file)
1035 {
1036         struct virtio_net *dev;
1037         struct eventfd_copy eventfd_call;
1038         struct vhost_virtqueue *vq;
1039
1040         dev = get_device(ctx);
1041         if (dev == NULL)
1042                 return -1;
1043
1044         /* file->index refers to the queue index. The TX queue is 1, RX queue is 0. */
1045         vq = dev->virtqueue[file->index];
1046
1047         if (vq->callfd)
1048                 close((int)vq->callfd);
1049
1050         /* Populate the eventfd_copy structure and call eventfd_copy. */
1051         vq->callfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
1052         eventfd_call.source_fd = vq->callfd;
1053         eventfd_call.target_fd = file->fd;
1054         eventfd_call.target_pid = ctx.pid;
1055
1056         if (eventfd_copy(dev, &eventfd_call))
1057         return -1;
1058
1059         return 0;
1060 }
1061
1062 /*
1063  * Called from CUSE IOCTL: VHOST_NET_SET_BACKEND
1064  * To complete device initialisation when the virtio driver is loaded we are provided with a
1065  * valid fd for a tap device (not used by us). If this happens then we can add the device to a
1066  * data core. When the virtio driver is removed we get fd=-1. At that point we remove the device
1067  * from the data core. The device will still exist in the device configuration linked list.
1068  */
1069 static int
1070 set_backend(struct vhost_device_ctx ctx, struct vhost_vring_file *file)
1071 {
1072         struct virtio_net *dev;
1073
1074         dev = get_device(ctx);
1075         if (dev == NULL) {
1076                 return -1;
1077         }
1078
1079         /* file->index refers to the queue index. The TX queue is 1, RX queue is 0. */
1080         dev->virtqueue[file->index]->backend = file->fd;
1081
1082         /* If the device isn't already running and both backend fds are set we add the device. */
1083         if (!(dev->flags & VIRTIO_DEV_RUNNING)) {
1084                 if (((int)dev->virtqueue[VIRTIO_TXQ]->backend != VIRTIO_DEV_STOPPED) &&
1085                         ((int)dev->virtqueue[VIRTIO_RXQ]->backend != VIRTIO_DEV_STOPPED))
1086                         return notify_ops->new_device(dev);
1087         /* Otherwise we remove it. */
1088         } else
1089                 if (file->fd == VIRTIO_DEV_STOPPED) {
1090                         notify_ops->destroy_device(dev);
1091                 }
1092         return 0;
1093 }
1094
1095 /*
1096  * Function pointers are set for the device operations to allow CUSE to call functions
1097  * when an IOCTL, device_add or device_release is received.
1098  */
1099 static const struct vhost_net_device_ops vhost_device_ops =
1100 {
1101         .new_device = new_device,
1102         .destroy_device = destroy_device,
1103
1104         .get_features = get_features,
1105         .set_features = set_features,
1106
1107         .set_mem_table = set_mem_table,
1108
1109         .set_vring_num = set_vring_num,
1110         .set_vring_addr = set_vring_addr,
1111         .set_vring_base = set_vring_base,
1112         .get_vring_base = get_vring_base,
1113
1114         .set_vring_kick = set_vring_kick,
1115         .set_vring_call = set_vring_call,
1116
1117         .set_backend = set_backend,
1118
1119         .set_owner = set_owner,
1120         .reset_owner = reset_owner,
1121 };
1122
1123 /*
1124  * Called by main to setup callbacks when registering CUSE device.
1125  */
1126 struct vhost_net_device_ops const *
1127 get_virtio_net_callbacks(void)
1128 {
1129         return &vhost_device_ops;
1130 }
1131
1132 /*
1133  * Register ops so that we can add/remove device to data core.
1134  */
1135 int
1136 init_virtio_net(struct virtio_net_device_ops const * const ops)
1137 {
1138         notify_ops = ops;
1139
1140         return 0;
1141 }
1142
1143 /*
1144  * Currently not used as we Ctrl+c to exit application.
1145  */
1146 int
1147 deinit_virtio_net(void)
1148 {
1149         return 0;
1150 }