New upstream version 18.08
[deb_dpdk.git] / examples / vhost / virtio_net.c
index f6e0067..8ea6b36 100644 (file)
@@ -56,16 +56,20 @@ enqueue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
            struct rte_mbuf *m, uint16_t desc_idx)
 {
        uint32_t desc_avail, desc_offset;
+       uint64_t desc_chunck_len;
        uint32_t mbuf_avail, mbuf_offset;
        uint32_t cpy_len;
        struct vring_desc *desc;
-       uint64_t desc_addr;
+       uint64_t desc_addr, desc_gaddr;
        struct virtio_net_hdr virtio_hdr = {0, 0, 0, 0, 0, 0};
        /* A counter to avoid desc dead loop chain */
        uint16_t nr_desc = 1;
 
        desc = &vr->desc[desc_idx];
-       desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+       desc_chunck_len = desc->len;
+       desc_gaddr = desc->addr;
+       desc_addr = rte_vhost_va_from_guest_pa(
+                       dev->mem, desc_gaddr, &desc_chunck_len);
        /*
         * Checking of 'desc_addr' placed outside of 'unlikely' macro to avoid
         * performance issue with some versions of gcc (4.8.4 and 5.3.0) which
@@ -77,9 +81,42 @@ enqueue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
        rte_prefetch0((void *)(uintptr_t)desc_addr);
 
        /* write virtio-net header */
-       *(struct virtio_net_hdr *)(uintptr_t)desc_addr = virtio_hdr;
+       if (likely(desc_chunck_len >= dev->hdr_len)) {
+               *(struct virtio_net_hdr *)(uintptr_t)desc_addr = virtio_hdr;
+               desc_offset = dev->hdr_len;
+       } else {
+               uint64_t len;
+               uint64_t remain = dev->hdr_len;
+               uint64_t src = (uint64_t)(uintptr_t)&virtio_hdr, dst;
+               uint64_t guest_addr = desc_gaddr;
+
+               while (remain) {
+                       len = remain;
+                       dst = rte_vhost_va_from_guest_pa(dev->mem,
+                                       guest_addr, &len);
+                       if (unlikely(!dst || !len))
+                               return -1;
+
+                       rte_memcpy((void *)(uintptr_t)dst,
+                                       (void *)(uintptr_t)src,
+                                       len);
+
+                       remain -= len;
+                       guest_addr += len;
+                       src += len;
+               }
+
+               desc_chunck_len = desc->len - dev->hdr_len;
+               desc_gaddr += dev->hdr_len;
+               desc_addr = rte_vhost_va_from_guest_pa(
+                               dev->mem, desc_gaddr,
+                               &desc_chunck_len);
+               if (unlikely(!desc_addr))
+                       return -1;
+
+               desc_offset = 0;
+       }
 
-       desc_offset = dev->hdr_len;
        desc_avail  = desc->len - dev->hdr_len;
 
        mbuf_avail  = rte_pktmbuf_data_len(m);
@@ -104,15 +141,28 @@ enqueue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
                                return -1;
 
                        desc = &vr->desc[desc->next];
-                       desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+                       desc_chunck_len = desc->len;
+                       desc_gaddr = desc->addr;
+                       desc_addr = rte_vhost_va_from_guest_pa(
+                                       dev->mem, desc_gaddr, &desc_chunck_len);
                        if (unlikely(!desc_addr))
                                return -1;
 
                        desc_offset = 0;
                        desc_avail  = desc->len;
+               } else if (unlikely(desc_chunck_len == 0)) {
+                       desc_chunck_len = desc_avail;
+                       desc_gaddr += desc_offset;
+                       desc_addr = rte_vhost_va_from_guest_pa(dev->mem,
+                                       desc_gaddr,
+                                       &desc_chunck_len);
+                       if (unlikely(!desc_addr))
+                               return -1;
+
+                       desc_offset = 0;
                }
 
-               cpy_len = RTE_MIN(desc_avail, mbuf_avail);
+               cpy_len = RTE_MIN(desc_chunck_len, mbuf_avail);
                rte_memcpy((void *)((uintptr_t)(desc_addr + desc_offset)),
                        rte_pktmbuf_mtod_offset(m, void *, mbuf_offset),
                        cpy_len);
@@ -121,6 +171,7 @@ enqueue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
                mbuf_offset += cpy_len;
                desc_avail  -= cpy_len;
                desc_offset += cpy_len;
+               desc_chunck_len -= cpy_len;
        }
 
        return 0;
@@ -189,8 +240,9 @@ dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
            struct rte_mempool *mbuf_pool)
 {
        struct vring_desc *desc;
-       uint64_t desc_addr;
+       uint64_t desc_addr, desc_gaddr;
        uint32_t desc_avail, desc_offset;
+       uint64_t desc_chunck_len;
        uint32_t mbuf_avail, mbuf_offset;
        uint32_t cpy_len;
        struct rte_mbuf *cur = m, *prev = m;
@@ -202,7 +254,10 @@ dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
                        (desc->flags & VRING_DESC_F_INDIRECT))
                return -1;
 
-       desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+       desc_chunck_len = desc->len;
+       desc_gaddr = desc->addr;
+       desc_addr = rte_vhost_va_from_guest_pa(
+                       dev->mem, desc_gaddr, &desc_chunck_len);
        if (unlikely(!desc_addr))
                return -1;
 
@@ -216,7 +271,10 @@ dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
         * header.
         */
        desc = &vr->desc[desc->next];
-       desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+       desc_chunck_len = desc->len;
+       desc_gaddr = desc->addr;
+       desc_addr = rte_vhost_va_from_guest_pa(
+                       dev->mem, desc_gaddr, &desc_chunck_len);
        if (unlikely(!desc_addr))
                return -1;
        rte_prefetch0((void *)(uintptr_t)desc_addr);
@@ -228,7 +286,7 @@ dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
        mbuf_offset = 0;
        mbuf_avail  = m->buf_len - RTE_PKTMBUF_HEADROOM;
        while (1) {
-               cpy_len = RTE_MIN(desc_avail, mbuf_avail);
+               cpy_len = RTE_MIN(desc_chunck_len, mbuf_avail);
                rte_memcpy(rte_pktmbuf_mtod_offset(cur, void *,
                                                   mbuf_offset),
                        (void *)((uintptr_t)(desc_addr + desc_offset)),
@@ -238,6 +296,7 @@ dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
                mbuf_offset += cpy_len;
                desc_avail  -= cpy_len;
                desc_offset += cpy_len;
+               desc_chunck_len -= cpy_len;
 
                /* This desc reaches to its end, get the next one */
                if (desc_avail == 0) {
@@ -249,13 +308,26 @@ dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
                                return -1;
                        desc = &vr->desc[desc->next];
 
-                       desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+                       desc_chunck_len = desc->len;
+                       desc_gaddr = desc->addr;
+                       desc_addr = rte_vhost_va_from_guest_pa(
+                                       dev->mem, desc_gaddr, &desc_chunck_len);
                        if (unlikely(!desc_addr))
                                return -1;
                        rte_prefetch0((void *)(uintptr_t)desc_addr);
 
                        desc_offset = 0;
                        desc_avail  = desc->len;
+               } else if (unlikely(desc_chunck_len == 0)) {
+                       desc_chunck_len = desc_avail;
+                       desc_gaddr += desc_offset;
+                       desc_addr = rte_vhost_va_from_guest_pa(dev->mem,
+                                       desc_gaddr,
+                                       &desc_chunck_len);
+                       if (unlikely(!desc_addr))
+                               return -1;
+
+                       desc_offset = 0;
                }
 
                /*