vhost: move internal structure
[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 /**
57  * Device linked list structure for configuration.
58  */
59 struct virtio_net_config_ll {
60         struct virtio_net             dev;    /* Virtio device. */
61         struct virtio_net_config_ll   *next;  /* Next entry on linked list. */
62 };
63
64 const char eventfd_cdev[] = "/dev/eventfd-link";
65
66 /* device ops to add/remove device to data core. */
67 static struct virtio_net_device_ops const * notify_ops;
68 /* Root address of the linked list in the configuration core. */
69 static struct virtio_net_config_ll                      *ll_root = NULL;
70
71 /* Features supported by this application. RX merge buffers are disabled by default. */
72 uint64_t VHOST_FEATURES = (0ULL << VIRTIO_NET_F_MRG_RXBUF);
73
74 /* Line size for reading maps file. */
75 const uint32_t BUFSIZE = PATH_MAX;
76
77 /* Size of prot char array in procmap. */
78 #define PROT_SZ 5
79
80 /* Number of elements in procmap struct. */
81 #define PROCMAP_SZ 8
82
83 /* Structure containing information gathered from maps file. */
84 struct procmap
85 {
86         uint64_t        va_start;                       /* Start virtual address in file. */
87         uint64_t        len;                            /* Size of file. */
88         uint64_t        pgoff;                          /* Not used. */
89         uint32_t        maj;                            /* Not used. */
90         uint32_t        min;                            /* Not used. */
91         uint32_t        ino;                            /* Not used. */
92         char            prot[PROT_SZ];          /* Not used. */
93         char            fname[PATH_MAX];        /* File name. */
94 };
95
96 /*
97  * Converts QEMU virtual address to Vhost virtual address. This function is used
98  * to convert the ring addresses to our address space.
99  */
100 static uint64_t
101 qva_to_vva(struct virtio_net *dev, uint64_t qemu_va)
102 {
103         struct virtio_memory_regions *region;
104         uint64_t vhost_va = 0;
105         uint32_t regionidx = 0;
106
107         /* Find the region where the address lives. */
108         for (regionidx = 0; regionidx < dev->mem->nregions; regionidx++) {
109                 region = &dev->mem->regions[regionidx];
110                 if ((qemu_va >= region->userspace_address) &&
111                                 (qemu_va <= region->userspace_address +
112                                 region->memory_size)) {
113                         vhost_va = dev->mem->mapped_address + qemu_va - dev->mem->base_address;
114                         break;
115                 }
116         }
117         return vhost_va;
118 }
119
120 /*
121  * Locate the file containing QEMU's memory space and map it to our address space.
122  */
123 static int
124 host_memory_map (struct virtio_net *dev, struct virtio_memory *mem, pid_t pid, uint64_t addr)
125 {
126         struct dirent *dptr = NULL;
127         struct procmap procmap;
128         DIR *dp = NULL;
129         int fd;
130         int i;
131         char memfile[PATH_MAX];
132         char mapfile[PATH_MAX];
133         char procdir[PATH_MAX];
134         char resolved_path[PATH_MAX];
135         FILE            *fmap;
136         void            *map;
137         uint8_t         found = 0;
138         char            line[BUFSIZE];
139         char dlm[] = "-   :   ";
140         char *str, *sp, *in[PROCMAP_SZ];
141         char *end = NULL;
142
143         /* Path where mem files are located. */
144         snprintf (procdir, PATH_MAX, "/proc/%u/fd/", pid);
145         /* Maps file used to locate mem file. */
146         snprintf (mapfile, PATH_MAX, "/proc/%u/maps", pid);
147
148         fmap = fopen(mapfile, "r");
149         if (fmap == NULL) {
150                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to open maps file for pid %d\n", dev->device_fh, pid);
151                 return -1;
152         }
153
154         /* Read through maps file until we find out base_address. */
155         while (fgets(line, BUFSIZE, fmap) != 0) {
156                 str = line;
157                 errno = 0;
158                 /* Split line in to fields. */
159                 for (i = 0; i < PROCMAP_SZ; i++) {
160                         if (((in[i] = strtok_r(str, &dlm[i], &sp)) == NULL) || (errno != 0)) {
161                                 fclose(fmap);
162                                 return -1;
163                         }
164                         str = NULL;
165                 }
166
167                 /* Convert/Copy each field as needed. */
168                 procmap.va_start = strtoull(in[0], &end, 16);
169                 if ((in[0] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) {
170                         fclose(fmap);
171                         return -1;
172                 }
173
174                 procmap.len = strtoull(in[1], &end, 16);
175                 if ((in[1] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) {
176                         fclose(fmap);
177                         return -1;
178                 }
179
180                 procmap.pgoff = strtoull(in[3], &end, 16);
181                 if ((in[3] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) {
182                         fclose(fmap);
183                         return -1;
184                 }
185
186                 procmap.maj = strtoul(in[4], &end, 16);
187                 if ((in[4] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) {
188                         fclose(fmap);
189                         return -1;
190                 }
191
192                 procmap.min = strtoul(in[5], &end, 16);
193                 if ((in[5] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) {
194                         fclose(fmap);
195                         return -1;
196                 }
197
198                 procmap.ino = strtoul(in[6], &end, 16);
199                 if ((in[6] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) {
200                         fclose(fmap);
201                         return -1;
202                 }
203
204                 memcpy(&procmap.prot, in[2], PROT_SZ);
205                 memcpy(&procmap.fname, in[7], PATH_MAX);
206
207                 if (procmap.va_start == addr) {
208                         procmap.len = procmap.len - procmap.va_start;
209                         found = 1;
210                         break;
211                 }
212         }
213         fclose(fmap);
214
215         if (!found) {
216                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find memory file in pid %d maps file\n", dev->device_fh, pid);
217                 return -1;
218         }
219
220         /* Find the guest memory file among the process fds. */
221         dp = opendir(procdir);
222         if (dp == NULL) {
223                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Cannot open pid %d process directory \n", dev->device_fh, pid);
224                 return -1;
225
226         }
227
228         found = 0;
229
230         /* Read the fd directory contents. */
231         while (NULL != (dptr = readdir(dp))) {
232                 snprintf (memfile, PATH_MAX, "/proc/%u/fd/%s", pid, dptr->d_name);
233             realpath(memfile, resolved_path);
234                 if (resolved_path == NULL) {
235                         RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to resolve fd directory\n", dev->device_fh);
236                         closedir(dp);
237                         return -1;
238                 }
239                 if (strncmp(resolved_path, procmap.fname,
240                         strnlen(procmap.fname, PATH_MAX)) == 0) {
241                         found = 1;
242                         break;
243                 }
244         }
245
246         closedir(dp);
247
248         if (found == 0) {
249                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find memory file for pid %d\n", dev->device_fh, pid);
250                 return -1;
251         }
252         /* Open the shared memory file and map the memory into this process. */
253         fd = open(memfile, O_RDWR);
254
255         if (fd == -1) {
256                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to open %s for pid %d\n", dev->device_fh, memfile, pid);
257                 return -1;
258         }
259
260         map = mmap(0, (size_t)procmap.len, PROT_READ|PROT_WRITE , MAP_POPULATE|MAP_SHARED, fd, 0);
261         close (fd);
262
263         if (map == MAP_FAILED) {
264                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Error mapping the file %s for pid %d\n",  dev->device_fh, memfile, pid);
265                 return -1;
266         }
267
268         /* Store the memory address and size in the device data structure */
269         mem->mapped_address = (uint64_t)(uintptr_t)map;
270         mem->mapped_size = procmap.len;
271
272         LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") Mem File: %s->%s - Size: %llu - VA: %p\n", dev->device_fh,
273                 memfile, resolved_path, (long long unsigned)mem->mapped_size, map);
274
275         return 0;
276 }
277
278 /*
279  * Retrieves an entry from the devices configuration linked list.
280  */
281 static struct virtio_net_config_ll *
282 get_config_ll_entry(struct vhost_device_ctx ctx)
283 {
284         struct virtio_net_config_ll *ll_dev = ll_root;
285
286         /* Loop through linked list until the device_fh is found. */
287         while (ll_dev != NULL) {
288                 if (ll_dev->dev.device_fh == ctx.fh)
289                         return ll_dev;
290                 ll_dev = ll_dev->next;
291         }
292
293         return NULL;
294 }
295
296 /*
297  * Searches the configuration core linked list and retrieves the device if it exists.
298  */
299 static struct virtio_net *
300 get_device(struct vhost_device_ctx ctx)
301 {
302         struct virtio_net_config_ll *ll_dev;
303
304         ll_dev = get_config_ll_entry(ctx);
305
306         /* If a matching entry is found in the linked list, return the device in that entry. */
307         if (ll_dev) {
308                 return &ll_dev->dev;
309         }
310
311         RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Device not found in linked list.\n", ctx.fh);
312         return NULL;
313 }
314
315 /*
316  * Add entry containing a device to the device configuration linked list.
317  */
318 static void
319 add_config_ll_entry(struct virtio_net_config_ll *new_ll_dev)
320 {
321         struct virtio_net_config_ll *ll_dev = ll_root;
322
323         /* If ll_dev == NULL then this is the first device so go to else */
324         if (ll_dev) {
325                 /* If the 1st device_fh != 0 then we insert our device here. */
326                 if (ll_dev->dev.device_fh != 0) {
327                         new_ll_dev->dev.device_fh = 0;
328                         new_ll_dev->next = ll_dev;
329                         ll_root = new_ll_dev;
330                 } else {
331                         /* Increment through the ll until we find un unused device_fh. Insert the device at that entry*/
332                         while ((ll_dev->next != NULL) && (ll_dev->dev.device_fh == (ll_dev->next->dev.device_fh - 1)))
333                                 ll_dev = ll_dev->next;
334
335                         new_ll_dev->dev.device_fh = ll_dev->dev.device_fh + 1;
336                         new_ll_dev->next = ll_dev->next;
337                         ll_dev->next = new_ll_dev;
338                 }
339         } else {
340                 ll_root = new_ll_dev;
341                 ll_root->dev.device_fh = 0;
342         }
343
344 }
345
346 /*
347  * Unmap any memory, close any file descriptors and free any memory owned by a device.
348  */
349 static void
350 cleanup_device(struct virtio_net *dev)
351 {
352         /* Unmap QEMU memory file if mapped. */
353         if (dev->mem) {
354                 munmap((void*)(uintptr_t)dev->mem->mapped_address, (size_t)dev->mem->mapped_size);
355                 free(dev->mem);
356         }
357
358         /* Close any event notifiers opened by device. */
359         if (dev->virtqueue[VIRTIO_RXQ]->callfd)
360                 close((int)dev->virtqueue[VIRTIO_RXQ]->callfd);
361         if (dev->virtqueue[VIRTIO_RXQ]->kickfd)
362                 close((int)dev->virtqueue[VIRTIO_RXQ]->kickfd);
363         if (dev->virtqueue[VIRTIO_TXQ]->callfd)
364                 close((int)dev->virtqueue[VIRTIO_TXQ]->callfd);
365         if (dev->virtqueue[VIRTIO_TXQ]->kickfd)
366                 close((int)dev->virtqueue[VIRTIO_TXQ]->kickfd);
367 }
368
369 /*
370  * Release virtqueues and device memory.
371  */
372 static void
373 free_device(struct virtio_net_config_ll *ll_dev)
374 {
375         /* Free any malloc'd memory */
376         free(ll_dev->dev.virtqueue[VIRTIO_RXQ]);
377         free(ll_dev->dev.virtqueue[VIRTIO_TXQ]);
378         free(ll_dev);
379 }
380 /*
381  * Remove an entry from the device configuration linked list.
382  */
383 static struct virtio_net_config_ll *
384 rm_config_ll_entry(struct virtio_net_config_ll *ll_dev, struct virtio_net_config_ll *ll_dev_last)
385 {
386         /* First remove the device and then clean it up. */
387         if (ll_dev == ll_root) {
388                 ll_root = ll_dev->next;
389                 cleanup_device(&ll_dev->dev);
390                 free_device(ll_dev);
391                 return ll_root;
392         } else {
393                 if (likely(ll_dev_last != NULL)) {
394                         ll_dev_last->next = ll_dev->next;
395                         cleanup_device(&ll_dev->dev);
396                         free_device(ll_dev);
397                         return ll_dev_last->next;
398                 } else {
399                         cleanup_device(&ll_dev->dev);
400                         free_device(ll_dev);
401                         RTE_LOG(ERR, VHOST_CONFIG, "Remove entry from config_ll failed\n");
402                         return NULL;
403                 }
404         }
405 }
406
407 /*
408  *  Initialise all variables in device structure.
409  */
410 static void
411 init_device(struct virtio_net *dev)
412 {
413         uint64_t vq_offset;
414
415         /* Virtqueues have already been malloced so we don't want to set them to NULL. */
416         vq_offset = offsetof(struct virtio_net, mem);
417
418         /* Set everything to 0. */
419         memset((void*)(uintptr_t)((uint64_t)(uintptr_t)dev + vq_offset), 0,
420                 (sizeof(struct virtio_net) - (size_t)vq_offset));
421         memset(dev->virtqueue[VIRTIO_RXQ], 0, sizeof(struct vhost_virtqueue));
422         memset(dev->virtqueue[VIRTIO_TXQ], 0, sizeof(struct vhost_virtqueue));
423
424         /* Backends are set to -1 indicating an inactive device. */
425         dev->virtqueue[VIRTIO_RXQ]->backend = VIRTIO_DEV_STOPPED;
426         dev->virtqueue[VIRTIO_TXQ]->backend = VIRTIO_DEV_STOPPED;
427 }
428
429 /*
430  * Function is called from the CUSE open function. The device structure is
431  * initialised and a new entry is added to the device configuration linked
432  * list.
433  */
434 static int
435 new_device(struct vhost_device_ctx ctx)
436 {
437         struct virtio_net_config_ll *new_ll_dev;
438         struct vhost_virtqueue *virtqueue_rx, *virtqueue_tx;
439
440         /* Setup device and virtqueues. */
441         new_ll_dev = malloc(sizeof(struct virtio_net_config_ll));
442         if (new_ll_dev == NULL) {
443                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to allocate memory for dev.\n", ctx.fh);
444                 return -1;
445         }
446
447         virtqueue_rx = malloc(sizeof(struct vhost_virtqueue));
448         if (virtqueue_rx == NULL) {
449                 free(new_ll_dev);
450                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to allocate memory for virtqueue_rx.\n", ctx.fh);
451                 return -1;
452         }
453
454         virtqueue_tx = malloc(sizeof(struct vhost_virtqueue));
455         if (virtqueue_tx == NULL) {
456                 free(virtqueue_rx);
457                 free(new_ll_dev);
458                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to allocate memory for virtqueue_tx.\n", ctx.fh);
459                 return -1;
460         }
461
462         new_ll_dev->dev.virtqueue[VIRTIO_RXQ] = virtqueue_rx;
463         new_ll_dev->dev.virtqueue[VIRTIO_TXQ] = virtqueue_tx;
464
465         /* Initialise device and virtqueues. */
466         init_device(&new_ll_dev->dev);
467
468         new_ll_dev->next = NULL;
469
470         /* Add entry to device configuration linked list. */
471         add_config_ll_entry(new_ll_dev);
472
473         return new_ll_dev->dev.device_fh;
474 }
475
476 /*
477  * Function is called from the CUSE release function. This function will cleanup
478  * the device and remove it from device configuration linked list.
479  */
480 static void
481 destroy_device(struct vhost_device_ctx ctx)
482 {
483         struct virtio_net_config_ll *ll_dev_cur_ctx, *ll_dev_last = NULL;
484         struct virtio_net_config_ll *ll_dev_cur = ll_root;
485
486         /* Find the linked list entry for the device to be removed. */
487         ll_dev_cur_ctx = get_config_ll_entry(ctx);
488         while (ll_dev_cur != NULL) {
489                 /* If the device is found or a device that doesn't exist is found then it is removed. */
490                 if (ll_dev_cur == ll_dev_cur_ctx) {
491                         /*
492                          * If the device is running on a data core then call the function to remove it from
493                          * the data core.
494                          */
495                         if ((ll_dev_cur->dev.flags & VIRTIO_DEV_RUNNING))
496                                 notify_ops->destroy_device(&(ll_dev_cur->dev));
497                         ll_dev_cur = rm_config_ll_entry(ll_dev_cur, ll_dev_last);
498                 } else {
499                         ll_dev_last = ll_dev_cur;
500                         ll_dev_cur = ll_dev_cur->next;
501                 }
502         }
503 }
504
505 /*
506  * Called from CUSE IOCTL: VHOST_SET_OWNER
507  * This function just returns success at the moment unless the device hasn't been initialised.
508  */
509 static int
510 set_owner(struct vhost_device_ctx ctx)
511 {
512         struct virtio_net *dev;
513
514         dev = get_device(ctx);
515         if (dev == NULL)
516                 return -1;
517
518         return 0;
519 }
520
521 /*
522  * Called from CUSE IOCTL: VHOST_RESET_OWNER
523  */
524 static int
525 reset_owner(struct vhost_device_ctx ctx)
526 {
527         struct virtio_net_config_ll *ll_dev;
528
529         ll_dev = get_config_ll_entry(ctx);
530
531         cleanup_device(&ll_dev->dev);
532         init_device(&ll_dev->dev);
533
534         return 0;
535 }
536
537 /*
538  * Called from CUSE IOCTL: VHOST_GET_FEATURES
539  * The features that we support are requested.
540  */
541 static int
542 get_features(struct vhost_device_ctx ctx, uint64_t *pu)
543 {
544         struct virtio_net *dev;
545
546         dev = get_device(ctx);
547         if (dev == NULL)
548                 return -1;
549
550         /* Send our supported features. */
551         *pu = VHOST_FEATURES;
552         return 0;
553 }
554
555 /*
556  * Called from CUSE IOCTL: VHOST_SET_FEATURES
557  * We receive the negotiated set of features supported by us and the virtio device.
558  */
559 static int
560 set_features(struct vhost_device_ctx ctx, uint64_t *pu)
561 {
562         struct virtio_net *dev;
563
564         dev = get_device(ctx);
565         if (dev == NULL)
566                 return -1;
567         if (*pu & ~VHOST_FEATURES)
568                 return -1;
569
570         /* Store the negotiated feature list for the device. */
571         dev->features = *pu;
572
573         /* Set the vhost_hlen depending on if VIRTIO_NET_F_MRG_RXBUF is set. */
574         if (dev->features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
575                 LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") Mergeable RX buffers enabled\n", dev->device_fh);
576                 dev->virtqueue[VIRTIO_RXQ]->vhost_hlen = sizeof(struct virtio_net_hdr_mrg_rxbuf);
577                 dev->virtqueue[VIRTIO_TXQ]->vhost_hlen = sizeof(struct virtio_net_hdr_mrg_rxbuf);
578         } else {
579                 LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") Mergeable RX buffers disabled\n", dev->device_fh);
580                 dev->virtqueue[VIRTIO_RXQ]->vhost_hlen = sizeof(struct virtio_net_hdr);
581                 dev->virtqueue[VIRTIO_TXQ]->vhost_hlen = sizeof(struct virtio_net_hdr);
582         }
583         return 0;
584 }
585
586
587 /*
588  * Called from CUSE IOCTL: VHOST_SET_MEM_TABLE
589  * This function creates and populates the memory structure for the device. This includes
590  * storing offsets used to translate buffer addresses.
591  */
592 static int
593 set_mem_table(struct vhost_device_ctx ctx, const void *mem_regions_addr, uint32_t nregions)
594 {
595         struct virtio_net *dev;
596         struct vhost_memory_region *mem_regions;
597         struct virtio_memory *mem;
598         uint64_t size = offsetof(struct vhost_memory, regions);
599         uint32_t regionidx, valid_regions;
600
601         dev = get_device(ctx);
602         if (dev == NULL)
603                 return -1;
604
605         if (dev->mem) {
606                 munmap((void*)(uintptr_t)dev->mem->mapped_address, (size_t)dev->mem->mapped_size);
607                 free(dev->mem);
608         }
609
610         /* Malloc the memory structure depending on the number of regions. */
611         mem = calloc(1, sizeof(struct virtio_memory) + (sizeof(struct virtio_memory_regions) * nregions));
612         if (mem == NULL) {
613                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to allocate memory for dev->mem.\n", dev->device_fh);
614                 return -1;
615         }
616
617         mem->nregions = nregions;
618
619         mem_regions = (void*)(uintptr_t)((uint64_t)(uintptr_t)mem_regions_addr + size);
620
621         for (regionidx = 0; regionidx < mem->nregions; regionidx++) {
622                 /* Populate the region structure for each region. */
623                 mem->regions[regionidx].guest_phys_address = mem_regions[regionidx].guest_phys_addr;
624                 mem->regions[regionidx].guest_phys_address_end = mem->regions[regionidx].guest_phys_address +
625                         mem_regions[regionidx].memory_size;
626                 mem->regions[regionidx].memory_size = mem_regions[regionidx].memory_size;
627                 mem->regions[regionidx].userspace_address = mem_regions[regionidx].userspace_addr;
628
629                 LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") REGION: %u - GPA: %p - QEMU VA: %p - SIZE (%"PRIu64")\n", dev->device_fh,
630                                 regionidx, (void*)(uintptr_t)mem->regions[regionidx].guest_phys_address,
631                                 (void*)(uintptr_t)mem->regions[regionidx].userspace_address,
632                                 mem->regions[regionidx].memory_size);
633
634                 /*set the base address mapping*/
635                 if (mem->regions[regionidx].guest_phys_address == 0x0) {
636                         mem->base_address = mem->regions[regionidx].userspace_address;
637                         /* Map VM memory file */
638                         if (host_memory_map(dev, mem, ctx.pid, mem->base_address) != 0) {
639                                 free(mem);
640                                 return -1;
641                         }
642                 }
643         }
644
645         /* Check that we have a valid base address. */
646         if (mem->base_address == 0) {
647                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find base address of qemu memory file.\n", dev->device_fh);
648                 free(mem);
649                 return -1;
650         }
651
652         /* Check if all of our regions have valid mappings. Usually one does not exist in the QEMU memory file. */
653         valid_regions = mem->nregions;
654         for (regionidx = 0; regionidx < mem->nregions; regionidx++) {
655                 if ((mem->regions[regionidx].userspace_address < mem->base_address) ||
656                         (mem->regions[regionidx].userspace_address > (mem->base_address + mem->mapped_size)))
657                                 valid_regions--;
658         }
659
660         /* If a region does not have a valid mapping we rebuild our memory struct to contain only valid entries. */
661         if (valid_regions != mem->nregions) {
662                 LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") Not all memory regions exist in the QEMU mem file. Re-populating mem structure\n",
663                         dev->device_fh);
664
665                 /* Re-populate the memory structure with only valid regions. Invalid regions are over-written with memmove. */
666                 valid_regions = 0;
667
668                 for (regionidx = mem->nregions; 0 != regionidx--;) {
669                         if ((mem->regions[regionidx].userspace_address < mem->base_address) ||
670                                         (mem->regions[regionidx].userspace_address > (mem->base_address + mem->mapped_size))) {
671                                 memmove(&mem->regions[regionidx], &mem->regions[regionidx + 1],
672                                         sizeof(struct virtio_memory_regions) * valid_regions);
673                         } else {
674                                 valid_regions++;
675                         }
676                 }
677         }
678         mem->nregions = valid_regions;
679         dev->mem = mem;
680
681         /*
682          * Calculate the address offset for each region. This offset is used to identify the vhost virtual address
683          * corresponding to a QEMU guest physical address.
684          */
685         for (regionidx = 0; regionidx < dev->mem->nregions; regionidx++) {
686                 dev->mem->regions[regionidx].address_offset = dev->mem->regions[regionidx].userspace_address - dev->mem->base_address
687                         + dev->mem->mapped_address - dev->mem->regions[regionidx].guest_phys_address;
688
689         }
690         return 0;
691 }
692
693 /*
694  * Called from CUSE IOCTL: VHOST_SET_VRING_NUM
695  * The virtio device sends us the size of the descriptor ring.
696  */
697 static int
698 set_vring_num(struct vhost_device_ctx ctx, struct vhost_vring_state *state)
699 {
700         struct virtio_net *dev;
701
702         dev = get_device(ctx);
703         if (dev == NULL)
704                 return -1;
705
706         /* State->index refers to the queue index. The TX queue is 1, RX queue is 0. */
707         dev->virtqueue[state->index]->size = state->num;
708
709         return 0;
710 }
711
712 /*
713  * Called from CUSE IOCTL: VHOST_SET_VRING_ADDR
714  * The virtio device sends us the desc, used and avail ring addresses. This function
715  * then converts these to our address space.
716  */
717 static int
718 set_vring_addr(struct vhost_device_ctx ctx, struct vhost_vring_addr *addr)
719 {
720         struct virtio_net *dev;
721         struct vhost_virtqueue *vq;
722
723         dev = get_device(ctx);
724         if (dev == NULL)
725                 return -1;
726
727         /* addr->index refers to the queue index. The TX queue is 1, RX queue is 0. */
728         vq = dev->virtqueue[addr->index];
729
730         /* The addresses are converted from QEMU virtual to Vhost virtual. */
731         vq->desc = (struct vring_desc*)(uintptr_t)qva_to_vva(dev, addr->desc_user_addr);
732         if (vq->desc == 0) {
733                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find descriptor ring address.\n", dev->device_fh);
734                 return -1;
735         }
736
737         vq->avail = (struct vring_avail*)(uintptr_t)qva_to_vva(dev, addr->avail_user_addr);
738         if (vq->avail == 0) {
739                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find available ring address.\n", dev->device_fh);
740                 return -1;
741         }
742
743         vq->used = (struct vring_used*)(uintptr_t)qva_to_vva(dev, addr->used_user_addr);
744         if (vq->used == 0) {
745                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") Failed to find used ring address.\n", dev->device_fh);
746                 return -1;
747         }
748
749         LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") mapped address desc: %p\n", dev->device_fh, vq->desc);
750         LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") mapped address avail: %p\n", dev->device_fh, vq->avail);
751         LOG_DEBUG(VHOST_CONFIG, "(%"PRIu64") mapped address used: %p\n", dev->device_fh, vq->used);
752
753         return 0;
754 }
755
756 /*
757  * Called from CUSE IOCTL: VHOST_SET_VRING_BASE
758  * The virtio device sends us the available ring last used index.
759  */
760 static int
761 set_vring_base(struct vhost_device_ctx ctx, struct vhost_vring_state *state)
762 {
763         struct virtio_net *dev;
764
765         dev = get_device(ctx);
766         if (dev == NULL)
767                 return -1;
768
769         /* State->index refers to the queue index. The TX queue is 1, RX queue is 0. */
770         dev->virtqueue[state->index]->last_used_idx = state->num;
771         dev->virtqueue[state->index]->last_used_idx_res = state->num;
772
773         return 0;
774 }
775
776 /*
777  * Called from CUSE IOCTL: VHOST_GET_VRING_BASE
778  * We send the virtio device our available ring last used index.
779  */
780 static int
781 get_vring_base(struct vhost_device_ctx ctx, uint32_t index, struct vhost_vring_state *state)
782 {
783         struct virtio_net *dev;
784
785         dev = get_device(ctx);
786         if (dev == NULL)
787                 return -1;
788
789         state->index = index;
790         /* State->index refers to the queue index. The TX queue is 1, RX queue is 0. */
791         state->num = dev->virtqueue[state->index]->last_used_idx;
792
793         return 0;
794 }
795
796 /*
797  * This function uses the eventfd_link kernel module to copy an eventfd file descriptor
798  * provided by QEMU in to our process space.
799  */
800 static int
801 eventfd_copy(struct virtio_net *dev, struct eventfd_copy *eventfd_copy)
802 {
803         int eventfd_link, ret;
804
805         /* Open the character device to the kernel module. */
806         eventfd_link = open(eventfd_cdev, O_RDWR);
807         if (eventfd_link < 0) {
808                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") eventfd_link module is not loaded\n",  dev->device_fh);
809                 return -1;
810         }
811
812         /* Call the IOCTL to copy the eventfd. */
813         ret = ioctl(eventfd_link, EVENTFD_COPY, eventfd_copy);
814         close(eventfd_link);
815
816         if (ret < 0) {
817                 RTE_LOG(ERR, VHOST_CONFIG, "(%"PRIu64") EVENTFD_COPY ioctl failed\n",  dev->device_fh);
818                 return -1;
819         }
820
821
822         return 0;
823 }
824
825 /*
826  * Called from CUSE IOCTL: VHOST_SET_VRING_CALL
827  * The virtio device sends an eventfd to interrupt the guest. This fd gets copied in
828  * to our process space.
829  */
830 static int
831 set_vring_call(struct vhost_device_ctx ctx, struct vhost_vring_file *file)
832 {
833         struct virtio_net *dev;
834         struct eventfd_copy     eventfd_kick;
835         struct vhost_virtqueue *vq;
836
837         dev = get_device(ctx);
838         if (dev == NULL)
839                 return -1;
840
841         /* file->index refers to the queue index. The TX queue is 1, RX queue is 0. */
842         vq = dev->virtqueue[file->index];
843
844         if (vq->kickfd)
845                 close((int)vq->kickfd);
846
847         /* Populate the eventfd_copy structure and call eventfd_copy. */
848         vq->kickfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
849         eventfd_kick.source_fd = vq->kickfd;
850         eventfd_kick.target_fd = file->fd;
851         eventfd_kick.target_pid = ctx.pid;
852
853         if (eventfd_copy(dev, &eventfd_kick))
854                 return -1;
855
856         return 0;
857 }
858
859 /*
860  * Called from CUSE IOCTL: VHOST_SET_VRING_KICK
861  * The virtio device sends an eventfd that it can use to notify us. This fd gets copied in
862  * to our process space.
863  */
864 static int
865 set_vring_kick(struct vhost_device_ctx ctx, struct vhost_vring_file *file)
866 {
867         struct virtio_net *dev;
868         struct eventfd_copy eventfd_call;
869         struct vhost_virtqueue *vq;
870
871         dev = get_device(ctx);
872         if (dev == NULL)
873                 return -1;
874
875         /* file->index refers to the queue index. The TX queue is 1, RX queue is 0. */
876         vq = dev->virtqueue[file->index];
877
878         if (vq->callfd)
879                 close((int)vq->callfd);
880
881         /* Populate the eventfd_copy structure and call eventfd_copy. */
882         vq->callfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
883         eventfd_call.source_fd = vq->callfd;
884         eventfd_call.target_fd = file->fd;
885         eventfd_call.target_pid = ctx.pid;
886
887         if (eventfd_copy(dev, &eventfd_call))
888         return -1;
889
890         return 0;
891 }
892
893 /*
894  * Called from CUSE IOCTL: VHOST_NET_SET_BACKEND
895  * To complete device initialisation when the virtio driver is loaded we are provided with a
896  * valid fd for a tap device (not used by us). If this happens then we can add the device to a
897  * data core. When the virtio driver is removed we get fd=-1. At that point we remove the device
898  * from the data core. The device will still exist in the device configuration linked list.
899  */
900 static int
901 set_backend(struct vhost_device_ctx ctx, struct vhost_vring_file *file)
902 {
903         struct virtio_net *dev;
904
905         dev = get_device(ctx);
906         if (dev == NULL) {
907                 return -1;
908         }
909
910         /* file->index refers to the queue index. The TX queue is 1, RX queue is 0. */
911         dev->virtqueue[file->index]->backend = file->fd;
912
913         /* If the device isn't already running and both backend fds are set we add the device. */
914         if (!(dev->flags & VIRTIO_DEV_RUNNING)) {
915                 if (((int)dev->virtqueue[VIRTIO_TXQ]->backend != VIRTIO_DEV_STOPPED) &&
916                         ((int)dev->virtqueue[VIRTIO_RXQ]->backend != VIRTIO_DEV_STOPPED))
917                         return notify_ops->new_device(dev);
918         /* Otherwise we remove it. */
919         } else
920                 if (file->fd == VIRTIO_DEV_STOPPED) {
921                         notify_ops->destroy_device(dev);
922                 }
923         return 0;
924 }
925
926 /*
927  * Function pointers are set for the device operations to allow CUSE to call functions
928  * when an IOCTL, device_add or device_release is received.
929  */
930 static const struct vhost_net_device_ops vhost_device_ops =
931 {
932         .new_device = new_device,
933         .destroy_device = destroy_device,
934
935         .get_features = get_features,
936         .set_features = set_features,
937
938         .set_mem_table = set_mem_table,
939
940         .set_vring_num = set_vring_num,
941         .set_vring_addr = set_vring_addr,
942         .set_vring_base = set_vring_base,
943         .get_vring_base = get_vring_base,
944
945         .set_vring_kick = set_vring_kick,
946         .set_vring_call = set_vring_call,
947
948         .set_backend = set_backend,
949
950         .set_owner = set_owner,
951         .reset_owner = reset_owner,
952 };
953
954 /*
955  * Called by main to setup callbacks when registering CUSE device.
956  */
957 struct vhost_net_device_ops const *
958 get_virtio_net_callbacks(void)
959 {
960         return &vhost_device_ops;
961 }
962
963 /*
964  * Register ops so that we can add/remove device to data core.
965  */
966 int
967 init_virtio_net(struct virtio_net_device_ops const * const ops)
968 {
969         notify_ops = ops;
970
971         return 0;
972 }
973
974 /*
975  * Currently not used as we Ctrl+c to exit application.
976  */
977 int
978 deinit_virtio_net(void)
979 {
980         return 0;
981 }