]> git.droids-corp.org - dpdk.git/commitdiff
net/virtio: allow virtual address to fill vring descriptors
authorJianfeng Tan <jianfeng.tan@intel.com>
Wed, 15 Jun 2016 09:03:21 +0000 (09:03 +0000)
committerYuanhan Liu <yuanhan.liu@linux.intel.com>
Wed, 22 Jun 2016 07:47:12 +0000 (09:47 +0200)
This patch is related to how to calculate relative address for vhost
backend.

The principle is that: based on one or multiple shared memory regions,
vhost maintains a reference system with the frontend start address,
backend start address, and length for each segment, so that each
frontend address (GPA, Guest Physical Address) can be translated into
vhost-recognizable backend address. To make the address translation
efficient, we need to maintain as few regions as possible. In the case
of VM, GPA is always locally continuous. But for some other case, like
virtio-user, GPA continuous is not guaranteed, therefore, we use virtual
address here.

It basically means:
  a. when set_base_addr, VA address is used;
  b. when preparing RX's descriptors, VA address is used;
  c. when transmitting packets, VA is filled in TX's descriptors;
  d. in TX and CQ's header, VA is used.

Signed-off-by: Huawei Xie <huawei.xie@intel.com>
Signed-off-by: Jianfeng Tan <jianfeng.tan@intel.com>
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Acked-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
drivers/net/virtio/virtio_ethdev.c
drivers/net/virtio/virtio_rxtx.c
drivers/net/virtio/virtio_rxtx_simple.c
drivers/net/virtio/virtqueue.h

index 48f5d9ee80668f18288b59262abc736b68589744..405f0c7d73bd16a26c95c7de6aa48d5b95a92325 100644 (file)
@@ -191,14 +191,14 @@ virtio_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl,
         * One RX packet for ACK.
         */
        vq->vq_ring.desc[head].flags = VRING_DESC_F_NEXT;
-       vq->vq_ring.desc[head].addr = cvq->virtio_net_hdr_mz->phys_addr;
+       vq->vq_ring.desc[head].addr = cvq->virtio_net_hdr_mem;
        vq->vq_ring.desc[head].len = sizeof(struct virtio_net_ctrl_hdr);
        vq->vq_free_cnt--;
        i = vq->vq_ring.desc[head].next;
 
        for (k = 0; k < pkt_num; k++) {
                vq->vq_ring.desc[i].flags = VRING_DESC_F_NEXT;
-               vq->vq_ring.desc[i].addr = cvq->virtio_net_hdr_mz->phys_addr
+               vq->vq_ring.desc[i].addr = cvq->virtio_net_hdr_mem
                        + sizeof(struct virtio_net_ctrl_hdr)
                        + sizeof(ctrl->status) + sizeof(uint8_t)*sum;
                vq->vq_ring.desc[i].len = dlen[k];
@@ -208,7 +208,7 @@ virtio_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl,
        }
 
        vq->vq_ring.desc[i].flags = VRING_DESC_F_WRITE;
-       vq->vq_ring.desc[i].addr = cvq->virtio_net_hdr_mz->phys_addr
+       vq->vq_ring.desc[i].addr = cvq->virtio_net_hdr_mem
                        + sizeof(struct virtio_net_ctrl_hdr);
        vq->vq_ring.desc[i].len = sizeof(ctrl->status);
        vq->vq_free_cnt--;
@@ -311,9 +311,9 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev,
        const struct rte_memzone *mz = NULL, *hdr_mz = NULL;
        unsigned int vq_size, size;
        struct virtio_hw *hw = dev->data->dev_private;
-       struct virtnet_rx *rxvq;
-       struct virtnet_tx *txvq;
-       struct virtnet_ctl *cvq;
+       struct virtnet_rx *rxvq = NULL;
+       struct virtnet_tx *txvq = NULL;
+       struct virtnet_ctl *cvq = NULL;
        struct virtqueue *vq;
        const char *queue_names[] = {"rvq", "txq", "cvq"};
        size_t sz_vq, sz_q = 0, sz_hdr_mz = 0;
@@ -437,9 +437,6 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev,
                rxvq->mz = mz;
                *pvq = rxvq;
        } else if (queue_type == VTNET_TQ) {
-               struct virtio_tx_region *txr;
-               unsigned int i;
-
                txvq = (struct virtnet_tx *)RTE_PTR_ADD(vq, sz_vq);
                txvq->vq = vq;
                txvq->port_id = dev->data->port_id;
@@ -448,6 +445,36 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev,
                txvq->virtio_net_hdr_mz = hdr_mz;
                txvq->virtio_net_hdr_mem = hdr_mz->phys_addr;
 
+               *pvq = txvq;
+       } else if (queue_type == VTNET_CQ) {
+               cvq = (struct virtnet_ctl *)RTE_PTR_ADD(vq, sz_vq);
+               cvq->vq = vq;
+               cvq->mz = mz;
+               cvq->virtio_net_hdr_mz = hdr_mz;
+               cvq->virtio_net_hdr_mem = hdr_mz->phys_addr;
+               memset(cvq->virtio_net_hdr_mz->addr, 0, PAGE_SIZE);
+               *pvq = cvq;
+       }
+
+       /* For virtio-user case (that is when dev->pci_dev is NULL), we use
+        * virtual address. And we need properly set _offset_, please see
+        * MBUF_DATA_DMA_ADDR in virtqueue.h for more information.
+        */
+       if (dev->pci_dev)
+               vq->offset = offsetof(struct rte_mbuf, buf_physaddr);
+       else {
+               vq->vq_ring_mem = (uintptr_t)mz->addr;
+               vq->offset = offsetof(struct rte_mbuf, buf_addr);
+               if (queue_type == VTNET_TQ)
+                       txvq->virtio_net_hdr_mem = (uintptr_t)hdr_mz->addr;
+               else if (queue_type == VTNET_CQ)
+                       cvq->virtio_net_hdr_mem = (uintptr_t)hdr_mz->addr;
+       }
+
+       if (queue_type == VTNET_TQ) {
+               struct virtio_tx_region *txr;
+               unsigned int i;
+
                txr = hdr_mz->addr;
                memset(txr, 0, vq_size * sizeof(*txr));
                for (i = 0; i < vq_size; i++) {
@@ -463,16 +490,6 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev,
                        start_dp->len = hw->vtnet_hdr_size;
                        start_dp->flags = VRING_DESC_F_NEXT;
                }
-
-               *pvq = txvq;
-       } else if (queue_type == VTNET_CQ) {
-               cvq = (struct virtnet_ctl *)RTE_PTR_ADD(vq, sz_vq);
-               cvq->vq = vq;
-               cvq->mz = mz;
-               cvq->virtio_net_hdr_mz = hdr_mz;
-               cvq->virtio_net_hdr_mem = hdr_mz->phys_addr;
-               memset(cvq->virtio_net_hdr_mz->addr, 0, PAGE_SIZE);
-               *pvq = cvq;
        }
 
        if (hw->vtpci_ops->setup_queue(hw, vq) < 0) {
index 3c69110f15348c127891950976dbab59bca99919..a27208e30376b9e8429c70fc834fd6bc175058c3 100644 (file)
@@ -193,8 +193,7 @@ virtqueue_enqueue_recv_refill(struct virtqueue *vq, struct rte_mbuf *cookie)
 
        start_dp = vq->vq_ring.desc;
        start_dp[idx].addr =
-               (uint64_t)(cookie->buf_physaddr + RTE_PKTMBUF_HEADROOM
-               - hw->vtnet_hdr_size);
+               MBUF_DATA_DMA_ADDR(cookie, vq->offset) - hw->vtnet_hdr_size;
        start_dp[idx].len =
                cookie->buf_len - RTE_PKTMBUF_HEADROOM + hw->vtnet_hdr_size;
        start_dp[idx].flags =  VRING_DESC_F_WRITE;
@@ -266,7 +265,7 @@ virtqueue_enqueue_xmit(struct virtnet_tx *txvq, struct rte_mbuf *cookie,
        }
 
        do {
-               start_dp[idx].addr  = rte_mbuf_data_dma_addr(cookie);
+               start_dp[idx].addr  = MBUF_DATA_DMA_ADDR(cookie, vq->offset);
                start_dp[idx].len   = cookie->data_len;
                start_dp[idx].flags = cookie->next ? VRING_DESC_F_NEXT : 0;
                idx = start_dp[idx].next;
index fdd655de22caf5a42d042f380118ee898b111947..7b50119f460909875bfa10a4a350ba83674d19e3 100644 (file)
@@ -80,8 +80,8 @@ virtqueue_enqueue_recv_refill_simple(struct virtqueue *vq,
        vq->sw_ring[desc_idx] = cookie;
 
        start_dp = vq->vq_ring.desc;
-       start_dp[desc_idx].addr = (uint64_t)((uintptr_t)cookie->buf_physaddr +
-               RTE_PKTMBUF_HEADROOM - vq->hw->vtnet_hdr_size);
+       start_dp[desc_idx].addr = MBUF_DATA_DMA_ADDR(cookie, vq->offset) -
+                                 vq->hw->vtnet_hdr_size;
        start_dp[desc_idx].len = cookie->buf_len -
                RTE_PKTMBUF_HEADROOM + vq->hw->vtnet_hdr_size;
 
@@ -120,8 +120,8 @@ virtio_rxq_rearm_vec(struct virtnet_rx *rxvq)
                *(uint64_t *)p = rxvq->mbuf_initializer;
 
                start_dp[i].addr =
-                       (uint64_t)((uintptr_t)sw_ring[i]->buf_physaddr +
-                       RTE_PKTMBUF_HEADROOM - vq->hw->vtnet_hdr_size);
+                       MBUF_DATA_DMA_ADDR(sw_ring[i], vq->offset) -
+                       vq->hw->vtnet_hdr_size;
                start_dp[i].len = sw_ring[i]->buf_len -
                        RTE_PKTMBUF_HEADROOM + vq->hw->vtnet_hdr_size;
        }
@@ -369,7 +369,7 @@ virtio_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts,
                        vq->vq_descx[desc_idx + i].cookie = tx_pkts[i];
                for (i = 0; i < nb_tail; i++) {
                        start_dp[desc_idx].addr =
-                               rte_mbuf_data_dma_addr(*tx_pkts);
+                               MBUF_DATA_DMA_ADDR(*tx_pkts, vq->offset);
                        start_dp[desc_idx].len = (*tx_pkts)->pkt_len;
                        tx_pkts++;
                        desc_idx++;
@@ -380,7 +380,8 @@ virtio_xmit_pkts_simple(void *tx_queue, struct rte_mbuf **tx_pkts,
        for (i = 0; i < nb_commit; i++)
                vq->vq_descx[desc_idx + i].cookie = tx_pkts[i];
        for (i = 0; i < nb_commit; i++) {
-               start_dp[desc_idx].addr = rte_mbuf_data_dma_addr(*tx_pkts);
+               start_dp[desc_idx].addr =
+                       MBUF_DATA_DMA_ADDR(*tx_pkts, vq->offset);
                start_dp[desc_idx].len = (*tx_pkts)->pkt_len;
                tx_pkts++;
                desc_idx++;
index 17c1ea1d1bdadaae9a9e2ef70b276e4f0ce8412c..455aaafec1147c4d59cea46b8435eb490c0c2b84 100644 (file)
@@ -66,6 +66,14 @@ struct rte_mbuf;
 
 #define VIRTQUEUE_MAX_NAME_SZ 32
 
+#ifdef RTE_VIRTIO_USER
+#define MBUF_DATA_DMA_ADDR(mb, offset) \
+       ((uint64_t)((uintptr_t)(*(void **)((uintptr_t)mb + offset)) \
+                       + (mb)->data_off))
+#else /* RTE_VIRTIO_USER */
+#define MBUF_DATA_DMA_ADDR(mb, offset) rte_mbuf_data_dma_addr(mb)
+#endif /* RTE_VIRTIO_USER */
+
 #define VTNET_SQ_RQ_QUEUE_IDX 0
 #define VTNET_SQ_TQ_QUEUE_IDX 1
 #define VTNET_SQ_CQ_QUEUE_IDX 2
@@ -175,6 +183,7 @@ struct virtqueue {
        unsigned int vq_ring_size;
 
        phys_addr_t vq_ring_mem; /**< physical address of vring */
+                               /**< use virtual address for virtio-user. */
 
        /**
         * Head of the free chain in the descriptor table. If
@@ -184,6 +193,7 @@ struct virtqueue {
        uint16_t  vq_desc_head_idx;
        uint16_t  vq_desc_tail_idx;
        uint16_t  vq_queue_index;   /**< PCI queue index */
+       uint16_t offset; /**< relative offset to obtain addr in mbuf */
        uint16_t  *notify_addr;
        int configured;
        struct rte_mbuf **sw_ring;  /**< RX software ring. */