get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/49031/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 49031,
    "url": "https://patches.dpdk.org/api/patches/49031/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20181218080207.178666-4-xiao.w.wang@intel.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20181218080207.178666-4-xiao.w.wang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20181218080207.178666-4-xiao.w.wang@intel.com",
    "date": "2018-12-18T08:02:00",
    "name": "[v5,03/10] vhost: provide helpers for virtio ring relay",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "c2556d2bf704a23a28377e79422ae5e554f84b38",
    "submitter": {
        "id": 281,
        "url": "https://patches.dpdk.org/api/people/281/?format=api",
        "name": "Xiao Wang",
        "email": "xiao.w.wang@intel.com"
    },
    "delegate": {
        "id": 2642,
        "url": "https://patches.dpdk.org/api/users/2642/?format=api",
        "username": "mcoquelin",
        "first_name": "Maxime",
        "last_name": "Coquelin",
        "email": "maxime.coquelin@redhat.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20181218080207.178666-4-xiao.w.wang@intel.com/mbox/",
    "series": [
        {
            "id": 2840,
            "url": "https://patches.dpdk.org/api/series/2840/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=2840",
            "date": "2018-12-18T08:01:57",
            "name": "support SW assisted VDPA live migration",
            "version": 5,
            "mbox": "https://patches.dpdk.org/series/2840/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/49031/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/49031/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 6C9201B939;\n\tTue, 18 Dec 2018 09:12:24 +0100 (CET)",
            "from mga02.intel.com (mga02.intel.com [134.134.136.20])\n\tby dpdk.org (Postfix) with ESMTP id 5BC3A1B6F7\n\tfor <dev@dpdk.org>; Tue, 18 Dec 2018 09:12:20 +0100 (CET)",
            "from orsmga008.jf.intel.com ([10.7.209.65])\n\tby orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t18 Dec 2018 00:12:20 -0800",
            "from dpdk-xiao-1.sh.intel.com ([10.67.111.145])\n\tby orsmga008.jf.intel.com with ESMTP; 18 Dec 2018 00:12:18 -0800"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.56,367,1539673200\"; d=\"scan'208\";a=\"102375023\"",
        "From": "Xiao Wang <xiao.w.wang@intel.com>",
        "To": "tiwei.bie@intel.com,\n\tmaxime.coquelin@redhat.com",
        "Cc": "alejandro.lucero@netronome.com, dev@dpdk.org, zhihong.wang@intel.com,\n\txiaolong.ye@intel.com, Xiao Wang <xiao.w.wang@intel.com>",
        "Date": "Tue, 18 Dec 2018 16:02:00 +0800",
        "Message-Id": "<20181218080207.178666-4-xiao.w.wang@intel.com>",
        "X-Mailer": "git-send-email 2.15.1",
        "In-Reply-To": "<20181218080207.178666-1-xiao.w.wang@intel.com>",
        "References": "<20181214211612.167681-4-xiao.w.wang@intel.com>\n\t<20181218080207.178666-1-xiao.w.wang@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v5 03/10] vhost: provide helpers for virtio ring\n\trelay",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch provides two helpers for vdpa device driver to perform a\nrelay between the guest virtio ring and a mediated virtio ring.\n\nThe available ring relay will synchronize the available entries, and\nhelp to do desc validity checking.\n\nThe used ring relay will synchronize the used entries from mediated ring\nto guest ring, and help to do dirty page logging for live migration.\n\nThe later patch will leverage these two helpers.\n\nSigned-off-by: Xiao Wang <xiao.w.wang@intel.com>\nReviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>\n---\n lib/librte_vhost/rte_vdpa.h            |  39 +++++++\n lib/librte_vhost/rte_vhost_version.map |   2 +\n lib/librte_vhost/vdpa.c                | 194 +++++++++++++++++++++++++++++++++\n lib/librte_vhost/vhost.h               |  40 +++++++\n lib/librte_vhost/virtio_net.c          |  39 -------\n 5 files changed, 275 insertions(+), 39 deletions(-)",
    "diff": "diff --git a/lib/librte_vhost/rte_vdpa.h b/lib/librte_vhost/rte_vdpa.h\nindex fff657391..462df6bf7 100644\n--- a/lib/librte_vhost/rte_vdpa.h\n+++ b/lib/librte_vhost/rte_vdpa.h\n@@ -173,4 +173,43 @@ rte_vdpa_get_device_num(void);\n  */\n int __rte_experimental\n rte_vhost_host_notifier_ctrl(int vid, bool enable);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Synchronize the available ring from guest to mediated ring, help to\n+ * check desc validity to protect against malicious guest driver.\n+ *\n+ * @param vid\n+ *  vhost device id\n+ * @param qid\n+ *  vhost queue id\n+ * @param vring_m\n+ *  mediated virtio ring pointer\n+ * @return\n+ *  number of synced available entries on success, -1 on failure\n+ */\n+int __rte_experimental\n+rte_vdpa_relay_vring_avail(int vid, uint16_t qid, void *vring_m);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Synchronize the used ring from mediated ring to guest, log dirty\n+ * page for each writeable buffer, caller should handle the used\n+ * ring logging before device stop.\n+ *\n+ * @param vid\n+ *  vhost device id\n+ * @param qid\n+ *  vhost queue id\n+ * @param vring_m\n+ *  mediated virtio ring pointer\n+ * @return\n+ *  number of synced used entries on success, -1 on failure\n+ */\n+int __rte_experimental\n+rte_vdpa_relay_vring_used(int vid, uint16_t qid, void *vring_m);\n #endif /* _RTE_VDPA_H_ */\ndiff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map\nindex 22302e972..dd3b4c1cb 100644\n--- a/lib/librte_vhost/rte_vhost_version.map\n+++ b/lib/librte_vhost/rte_vhost_version.map\n@@ -84,4 +84,6 @@ EXPERIMENTAL {\n \trte_vhost_crypto_set_zero_copy;\n \trte_vhost_va_from_guest_pa;\n \trte_vhost_host_notifier_ctrl;\n+\trte_vdpa_relay_vring_avail;\n+\trte_vdpa_relay_vring_used;\n };\ndiff --git a/lib/librte_vhost/vdpa.c b/lib/librte_vhost/vdpa.c\nindex e7d849ee0..240a1fe3a 100644\n--- a/lib/librte_vhost/vdpa.c\n+++ b/lib/librte_vhost/vdpa.c\n@@ -122,3 +122,197 @@ rte_vdpa_get_device_num(void)\n {\n \treturn vdpa_device_num;\n }\n+\n+static bool\n+invalid_desc_check(struct virtio_net *dev, struct vhost_virtqueue *vq,\n+\t\tuint64_t desc_iova, uint64_t desc_len, uint8_t perm)\n+{\n+\tuint64_t desc_addr, desc_chunck_len;\n+\n+\twhile (desc_len) {\n+\t\tdesc_chunck_len = desc_len;\n+\t\tdesc_addr = vhost_iova_to_vva(dev, vq,\n+\t\t\t\tdesc_iova,\n+\t\t\t\t&desc_chunck_len,\n+\t\t\t\tperm);\n+\n+\t\tif (!desc_addr)\n+\t\t\treturn true;\n+\n+\t\tdesc_len -= desc_chunck_len;\n+\t\tdesc_iova += desc_chunck_len;\n+\t}\n+\n+\treturn false;\n+}\n+\n+int __rte_experimental\n+rte_vdpa_relay_vring_avail(int vid, uint16_t qid, void *vring_m)\n+{\n+\tstruct virtio_net *dev = get_device(vid);\n+\tuint16_t idx, idx_m, desc_id;\n+\tstruct vring_desc desc;\n+\tstruct vhost_virtqueue *vq;\n+\tstruct vring_desc *desc_ring;\n+\tstruct vring_desc *idesc = NULL;\n+\tstruct vring *s_vring;\n+\tuint64_t dlen;\n+\tint ret;\n+\tuint8_t perm;\n+\n+\tif (!dev || !vring_m)\n+\t\treturn -1;\n+\n+\tif (qid >= dev->nr_vring)\n+\t\treturn -1;\n+\n+\tif (vq_is_packed(dev))\n+\t\treturn -1;\n+\n+\ts_vring = (struct vring *)vring_m;\n+\tvq = dev->virtqueue[qid];\n+\tidx = vq->avail->idx;\n+\tidx_m = s_vring->avail->idx;\n+\tret = (uint16_t)(idx - idx_m);\n+\n+\twhile (idx_m != idx) {\n+\t\t/* avail entry copy */\n+\t\tdesc_id = vq->avail->ring[idx_m & (vq->size - 1)];\n+\t\ts_vring->avail->ring[idx_m & (vq->size - 1)] = desc_id;\n+\t\tdesc_ring = vq->desc;\n+\n+\t\tif (vq->desc[desc_id].flags & VRING_DESC_F_INDIRECT) {\n+\t\t\tdlen = vq->desc[desc_id].len;\n+\t\t\tdesc_ring = (struct vring_desc *)(uintptr_t)\n+\t\t\t\tvhost_iova_to_vva(dev, vq,\n+\t\t\t\t\t\tvq->desc[desc_id].addr, &dlen,\n+\t\t\t\t\t\tVHOST_ACCESS_RO);\n+\t\t\tif (unlikely(!desc_ring))\n+\t\t\t\treturn -1;\n+\n+\t\t\tif (unlikely(dlen < vq->desc[idx].len)) {\n+\t\t\t\tidesc = alloc_copy_ind_table(dev, vq,\n+\t\t\t\t\t\tvq->desc[idx].addr,\n+\t\t\t\t\t\tvq->desc[idx].len);\n+\t\t\t\tif (unlikely(!idesc))\n+\t\t\t\t\treturn -1;\n+\n+\t\t\t\tdesc_ring = idesc;\n+\t\t\t}\n+\n+\t\t\tdesc_id = 0;\n+\t\t}\n+\n+\t\t/* check if the buf addr is within the guest memory */\n+\t\tdo {\n+\t\t\tdesc = desc_ring[desc_id];\n+\t\t\tperm = desc.flags & VRING_DESC_F_WRITE ?\n+\t\t\t\tVHOST_ACCESS_WO : VHOST_ACCESS_RO;\n+\t\t\tif (invalid_desc_check(dev, vq, desc.addr, desc.len,\n+\t\t\t\t\t\tperm)) {\n+\t\t\t\tif (unlikely(idesc))\n+\t\t\t\t\tfree_ind_table(idesc);\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tdesc_id = desc.next;\n+\t\t} while (desc.flags & VRING_DESC_F_NEXT);\n+\n+\t\tif (unlikely(idesc)) {\n+\t\t\tfree_ind_table(idesc);\n+\t\t\tidesc = NULL;\n+\t\t}\n+\n+\t\tidx_m++;\n+\t}\n+\n+\trte_smp_wmb();\n+\ts_vring->avail->idx = idx;\n+\n+\tif (dev->features & (1ULL << VIRTIO_RING_F_EVENT_IDX))\n+\t\tvhost_avail_event(vq) = idx;\n+\n+\treturn ret;\n+}\n+\n+int __rte_experimental\n+rte_vdpa_relay_vring_used(int vid, uint16_t qid, void *vring_m)\n+{\n+\tstruct virtio_net *dev = get_device(vid);\n+\tuint16_t idx, idx_m, desc_id;\n+\tstruct vhost_virtqueue *vq;\n+\tstruct vring_desc desc;\n+\tstruct vring_desc *desc_ring;\n+\tstruct vring_desc *idesc = NULL;\n+\tstruct vring *s_vring;\n+\tuint64_t dlen;\n+\tint ret;\n+\n+\tif (!dev || !vring_m)\n+\t\treturn -1;\n+\n+\tif (qid >= dev->nr_vring)\n+\t\treturn -1;\n+\n+\tif (vq_is_packed(dev))\n+\t\treturn -1;\n+\n+\ts_vring = (struct vring *)vring_m;\n+\tvq = dev->virtqueue[qid];\n+\tidx = vq->used->idx;\n+\tidx_m = s_vring->used->idx;\n+\tret = (uint16_t)(idx_m - idx);\n+\n+\twhile (idx != idx_m) {\n+\t\t/* copy used entry, used ring logging is not covered here */\n+\t\tvq->used->ring[idx & (vq->size - 1)] =\n+\t\t\ts_vring->used->ring[idx & (vq->size - 1)];\n+\n+\t\tdesc_id = vq->used->ring[idx & (vq->size - 1)].id;\n+\t\tdesc_ring = vq->desc;\n+\n+\t\tif (vq->desc[desc_id].flags & VRING_DESC_F_INDIRECT) {\n+\t\t\tdlen = vq->desc[desc_id].len;\n+\t\t\tdesc_ring = (struct vring_desc *)(uintptr_t)\n+\t\t\t\tvhost_iova_to_vva(dev, vq,\n+\t\t\t\t\t\tvq->desc[desc_id].addr, &dlen,\n+\t\t\t\t\t\tVHOST_ACCESS_RO);\n+\t\t\tif (unlikely(!desc_ring))\n+\t\t\t\treturn -1;\n+\n+\t\t\tif (unlikely(dlen < vq->desc[idx].len)) {\n+\t\t\t\tidesc = alloc_copy_ind_table(dev, vq,\n+\t\t\t\t\t\tvq->desc[idx].addr,\n+\t\t\t\t\t\tvq->desc[idx].len);\n+\t\t\t\tif (unlikely(!idesc))\n+\t\t\t\t\treturn -1;\n+\n+\t\t\t\tdesc_ring = idesc;\n+\t\t\t}\n+\n+\t\t\tdesc_id = 0;\n+\t\t}\n+\n+\t\t/* dirty page logging for DMA writeable buffer */\n+\t\tdo {\n+\t\t\tdesc = desc_ring[desc_id];\n+\t\t\tif (desc.flags & VRING_DESC_F_WRITE)\n+\t\t\t\tvhost_log_write(dev, desc.addr, desc.len);\n+\t\t\tdesc_id = desc.next;\n+\t\t} while (desc.flags & VRING_DESC_F_NEXT);\n+\n+\t\tif (unlikely(idesc)) {\n+\t\t\tfree_ind_table(idesc);\n+\t\t\tidesc = NULL;\n+\t\t}\n+\n+\t\tidx++;\n+\t}\n+\n+\trte_smp_wmb();\n+\tvq->used->idx = idx_m;\n+\n+\tif (dev->features & (1ULL << VIRTIO_RING_F_EVENT_IDX))\n+\t\tvring_used_event(s_vring) = idx_m;\n+\n+\treturn ret;\n+}\ndiff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h\nindex d5bab4803..3b3265c4b 100644\n--- a/lib/librte_vhost/vhost.h\n+++ b/lib/librte_vhost/vhost.h\n@@ -18,6 +18,7 @@\n #include <rte_log.h>\n #include <rte_ether.h>\n #include <rte_rwlock.h>\n+#include <rte_malloc.h>\n \n #include \"rte_vhost.h\"\n #include \"rte_vdpa.h\"\n@@ -754,4 +755,43 @@ vhost_vring_call_packed(struct virtio_net *dev, struct vhost_virtqueue *vq)\n \t\teventfd_write(vq->callfd, (eventfd_t)1);\n }\n \n+static __rte_always_inline void *\n+alloc_copy_ind_table(struct virtio_net *dev, struct vhost_virtqueue *vq,\n+\t\tuint64_t desc_addr, uint64_t desc_len)\n+{\n+\tvoid *idesc;\n+\tuint64_t src, dst;\n+\tuint64_t len, remain = desc_len;\n+\n+\tidesc = rte_malloc(__func__, desc_len, 0);\n+\tif (unlikely(!idesc))\n+\t\treturn 0;\n+\n+\tdst = (uint64_t)(uintptr_t)idesc;\n+\n+\twhile (remain) {\n+\t\tlen = remain;\n+\t\tsrc = vhost_iova_to_vva(dev, vq, desc_addr, &len,\n+\t\t\t\tVHOST_ACCESS_RO);\n+\t\tif (unlikely(!src || !len)) {\n+\t\t\trte_free(idesc);\n+\t\t\treturn 0;\n+\t\t}\n+\n+\t\trte_memcpy((void *)(uintptr_t)dst, (void *)(uintptr_t)src, len);\n+\n+\t\tremain -= len;\n+\t\tdst += len;\n+\t\tdesc_addr += len;\n+\t}\n+\n+\treturn idesc;\n+}\n+\n+static __rte_always_inline void\n+free_ind_table(void *idesc)\n+{\n+\trte_free(idesc);\n+}\n+\n #endif /* _VHOST_NET_CDEV_H_ */\ndiff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c\nindex 5e1a1a727..8c657a101 100644\n--- a/lib/librte_vhost/virtio_net.c\n+++ b/lib/librte_vhost/virtio_net.c\n@@ -37,45 +37,6 @@ is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_t nr_vring)\n \treturn (is_tx ^ (idx & 1)) == 0 && idx < nr_vring;\n }\n \n-static __rte_always_inline void *\n-alloc_copy_ind_table(struct virtio_net *dev, struct vhost_virtqueue *vq,\n-\t\tuint64_t desc_addr, uint64_t desc_len)\n-{\n-\tvoid *idesc;\n-\tuint64_t src, dst;\n-\tuint64_t len, remain = desc_len;\n-\n-\tidesc = rte_malloc(__func__, desc_len, 0);\n-\tif (unlikely(!idesc))\n-\t\treturn 0;\n-\n-\tdst = (uint64_t)(uintptr_t)idesc;\n-\n-\twhile (remain) {\n-\t\tlen = remain;\n-\t\tsrc = vhost_iova_to_vva(dev, vq, desc_addr, &len,\n-\t\t\t\tVHOST_ACCESS_RO);\n-\t\tif (unlikely(!src || !len)) {\n-\t\t\trte_free(idesc);\n-\t\t\treturn 0;\n-\t\t}\n-\n-\t\trte_memcpy((void *)(uintptr_t)dst, (void *)(uintptr_t)src, len);\n-\n-\t\tremain -= len;\n-\t\tdst += len;\n-\t\tdesc_addr += len;\n-\t}\n-\n-\treturn idesc;\n-}\n-\n-static __rte_always_inline void\n-free_ind_table(void *idesc)\n-{\n-\trte_free(idesc);\n-}\n-\n static __rte_always_inline void\n do_flush_shadow_used_ring_split(struct virtio_net *dev,\n \t\t\tstruct vhost_virtqueue *vq,\n",
    "prefixes": [
        "v5",
        "03/10"
    ]
}