get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 48725,
    "url": "http://patches.dpdk.org/api/patches/48725/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20181213011014.110089-9-xiao.w.wang@intel.com/",
    "project": {
        "id": 1,
        "url": "http://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": "<20181213011014.110089-9-xiao.w.wang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20181213011014.110089-9-xiao.w.wang@intel.com",
    "date": "2018-12-13T01:10:13",
    "name": "[v2,8/9] net/ifc: support SW assisted VDPA live migration",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "5adef1879e710ae9561836dd34f5d70fb98347dd",
    "submitter": {
        "id": 281,
        "url": "http://patches.dpdk.org/api/people/281/?format=api",
        "name": "Xiao Wang",
        "email": "xiao.w.wang@intel.com"
    },
    "delegate": {
        "id": 2642,
        "url": "http://patches.dpdk.org/api/users/2642/?format=api",
        "username": "mcoquelin",
        "first_name": "Maxime",
        "last_name": "Coquelin",
        "email": "maxime.coquelin@redhat.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20181213011014.110089-9-xiao.w.wang@intel.com/mbox/",
    "series": [
        {
            "id": 2747,
            "url": "http://patches.dpdk.org/api/series/2747/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=2747",
            "date": "2018-12-13T01:10:05",
            "name": "support SW assisted VDPA live migration",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/2747/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/48725/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/48725/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 7A84E1B460;\n\tThu, 13 Dec 2018 02:23:28 +0100 (CET)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby dpdk.org (Postfix) with ESMTP id 52EE71B47C\n\tfor <dev@dpdk.org>; Thu, 13 Dec 2018 02:23:27 +0100 (CET)",
            "from orsmga008.jf.intel.com ([10.7.209.65])\n\tby fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t12 Dec 2018 17:23:26 -0800",
            "from dpdk-xiao-1.sh.intel.com ([10.67.111.145])\n\tby orsmga008.jf.intel.com with ESMTP; 12 Dec 2018 17:23:25 -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,346,1539673200\"; d=\"scan'208\";a=\"101112927\"",
        "From": "Xiao Wang <xiao.w.wang@intel.com>",
        "To": "alejandro.lucero@netronome.com,\n\ttiwei.bie@intel.com",
        "Cc": "maxime.coquelin@redhat.com, dev@dpdk.org, zhihong.wang@intel.com,\n\txiaolong.ye@intel.com, Xiao Wang <xiao.w.wang@intel.com>",
        "Date": "Thu, 13 Dec 2018 09:10:13 +0800",
        "Message-Id": "<20181213011014.110089-9-xiao.w.wang@intel.com>",
        "X-Mailer": "git-send-email 2.15.1",
        "In-Reply-To": "<20181213011014.110089-1-xiao.w.wang@intel.com>",
        "References": "<20181128094607.106173-3-xiao.w.wang@intel.com>\n\t<20181213011014.110089-1-xiao.w.wang@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v2 8/9] net/ifc: support SW assisted VDPA live\n\tmigration",
        "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": "In SW assisted live migration mode, driver will stop the device and\nsetup a mediate virtio ring to relay the communication between the\nvirtio driver and the VDPA device.\n\nThis data path intervention will allow SW to help on guest dirty page\nlogging for live migration.\n\nThis SW fallback is event driven relay thread, so when the network\nthroughput is low, this SW fallback will take little CPU resource, but\nwhen the throughput goes up, the relay thread's CPU usage will goes up\naccordinly.\n\nUser needs to take all the factors including CPU usage, guest perf\ndegradation, etc. into consideration when selecting the live migration\nsupport mode.\n\nSigned-off-by: Xiao Wang <xiao.w.wang@intel.com>\n---\nv2:\n* Make the parameter parsing code shorter.\n---\n drivers/net/ifc/base/ifcvf.h |   1 +\n drivers/net/ifc/ifcvf_vdpa.c | 346 ++++++++++++++++++++++++++++++++++++++++++-\n 2 files changed, 344 insertions(+), 3 deletions(-)",
    "diff": "diff --git a/drivers/net/ifc/base/ifcvf.h b/drivers/net/ifc/base/ifcvf.h\nindex f026c70ab..8eb70ae9d 100644\n--- a/drivers/net/ifc/base/ifcvf.h\n+++ b/drivers/net/ifc/base/ifcvf.h\n@@ -50,6 +50,7 @@\n #define IFCVF_LM_ENABLE_VF\t\t0x1\n #define IFCVF_LM_ENABLE_PF\t\t0x3\n #define IFCVF_LOG_BASE\t\t\t0x100000000000\n+#define IFCVF_MEDIATE_VRING\t\t0x200000000000\n \n #define IFCVF_32_BIT_MASK\t\t0xffffffff\n \ndiff --git a/drivers/net/ifc/ifcvf_vdpa.c b/drivers/net/ifc/ifcvf_vdpa.c\nindex f181c5a6e..31ea880b2 100644\n--- a/drivers/net/ifc/ifcvf_vdpa.c\n+++ b/drivers/net/ifc/ifcvf_vdpa.c\n@@ -63,6 +63,9 @@ struct ifcvf_internal {\n \trte_atomic32_t running;\n \trte_spinlock_t lock;\n \tbool sw_lm;\n+\tbool sw_fallback_running;\n+\t/* mediated vring for sw fallback */\n+\tstruct vring m_vring[IFCVF_MAX_QUEUES * 2];\n };\n \n struct internal_list {\n@@ -308,6 +311,9 @@ vdpa_ifcvf_stop(struct ifcvf_internal *internal)\n \t\trte_vhost_set_vring_base(vid, i, hw->vring[i].last_avail_idx,\n \t\t\t\thw->vring[i].last_used_idx);\n \n+\tif (internal->sw_lm)\n+\t\treturn;\n+\n \trte_vhost_get_negotiated_features(vid, &features);\n \tif (RTE_VHOST_NEED_LOG(features)) {\n \t\tifcvf_disable_logging(hw);\n@@ -539,6 +545,318 @@ update_datapath(struct ifcvf_internal *internal)\n \treturn ret;\n }\n \n+static int\n+m_ifcvf_start(struct ifcvf_internal *internal)\n+{\n+\tstruct ifcvf_hw *hw = &internal->hw;\n+\tuint32_t i, nr_vring;\n+\tint vid, ret;\n+\tstruct rte_vhost_vring vq;\n+\tvoid *vring_buf;\n+\tuint64_t m_vring_iova = IFCVF_MEDIATE_VRING;\n+\tuint64_t size;\n+\tuint64_t gpa;\n+\n+\tvid = internal->vid;\n+\tnr_vring = rte_vhost_get_vring_num(vid);\n+\trte_vhost_get_negotiated_features(vid, &hw->req_features);\n+\n+\tfor (i = 0; i < nr_vring; i++) {\n+\t\trte_vhost_get_vhost_vring(vid, i, &vq);\n+\n+\t\tsize = RTE_ALIGN_CEIL(vring_size(vq.size, PAGE_SIZE),\n+\t\t\t\tPAGE_SIZE);\n+\t\tvring_buf = rte_zmalloc(\"ifcvf\", size, PAGE_SIZE);\n+\t\tvring_init(&internal->m_vring[i], vq.size, vring_buf,\n+\t\t\t\tPAGE_SIZE);\n+\n+\t\tret = rte_vfio_container_dma_map(internal->vfio_container_fd,\n+\t\t\t(uint64_t)(uintptr_t)vring_buf, m_vring_iova, size);\n+\t\tif (ret < 0) {\n+\t\t\tDRV_LOG(ERR, \"mediate vring DMA map failed.\");\n+\t\t\tgoto error;\n+\t\t}\n+\n+\t\tgpa = hva_to_gpa(vid, (uint64_t)(uintptr_t)vq.desc);\n+\t\tif (gpa == 0) {\n+\t\t\tDRV_LOG(ERR, \"Fail to get GPA for descriptor ring.\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\thw->vring[i].desc = gpa;\n+\n+\t\thw->vring[i].avail = m_vring_iova +\n+\t\t\t(char *)internal->m_vring[i].avail -\n+\t\t\t(char *)internal->m_vring[i].desc;\n+\n+\t\thw->vring[i].used = m_vring_iova +\n+\t\t\t(char *)internal->m_vring[i].used -\n+\t\t\t(char *)internal->m_vring[i].desc;\n+\n+\t\thw->vring[i].size = vq.size;\n+\n+\t\trte_vhost_get_vring_base(vid, i, &hw->vring[i].last_avail_idx,\n+\t\t\t\t&hw->vring[i].last_used_idx);\n+\n+\t\tm_vring_iova += size;\n+\t}\n+\thw->nr_vring = nr_vring;\n+\n+\treturn ifcvf_start_hw(&internal->hw);\n+\n+error:\n+\tfor (i = 0; i < nr_vring; i++)\n+\t\tif (internal->m_vring[i].desc)\n+\t\t\trte_free(internal->m_vring[i].desc);\n+\n+\treturn -1;\n+}\n+\n+static int\n+m_ifcvf_stop(struct ifcvf_internal *internal)\n+{\n+\tint vid;\n+\tuint32_t i;\n+\tstruct rte_vhost_vring vq;\n+\tstruct ifcvf_hw *hw = &internal->hw;\n+\tuint64_t m_vring_iova = IFCVF_MEDIATE_VRING;\n+\tuint64_t size, len;\n+\n+\tvid = internal->vid;\n+\tifcvf_stop_hw(hw);\n+\n+\tfor (i = 0; i < hw->nr_vring; i++) {\n+\t\trte_vhost_get_vhost_vring(vid, i, &vq);\n+\t\tlen = IFCVF_USED_RING_LEN(vq.size);\n+\t\trte_vhost_log_used_vring(vid, i, 0, len);\n+\n+\t\tsize = RTE_ALIGN_CEIL(vring_size(vq.size, PAGE_SIZE),\n+\t\t\t\tPAGE_SIZE);\n+\t\trte_vfio_container_dma_unmap(internal->vfio_container_fd,\n+\t\t\t(uint64_t)(uintptr_t)internal->m_vring[i].desc,\n+\t\t\tm_vring_iova, size);\n+\n+\t\trte_vhost_set_vring_base(vid, i, hw->vring[i].last_avail_idx,\n+\t\t\t\thw->vring[i].last_used_idx);\n+\t\trte_free(internal->m_vring[i].desc);\n+\t\tm_vring_iova += size;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+m_enable_vfio_intr(struct ifcvf_internal *internal)\n+{\n+\tuint32_t nr_vring;\n+\tstruct rte_intr_handle *intr_handle = &internal->pdev->intr_handle;\n+\tint ret;\n+\n+\tnr_vring = rte_vhost_get_vring_num(internal->vid);\n+\n+\tret = rte_intr_efd_enable(intr_handle, nr_vring);\n+\tif (ret)\n+\t\treturn -1;\n+\n+\tret = rte_intr_enable(intr_handle);\n+\tif (ret)\n+\t\treturn -1;\n+\n+\treturn 0;\n+}\n+\n+static void\n+m_disable_vfio_intr(struct ifcvf_internal *internal)\n+{\n+\tstruct rte_intr_handle *intr_handle = &internal->pdev->intr_handle;\n+\n+\trte_intr_efd_disable(intr_handle);\n+\trte_intr_disable(intr_handle);\n+}\n+\n+static void\n+update_avail_ring(struct ifcvf_internal *internal, uint16_t qid)\n+{\n+\trte_vdpa_relay_avail_ring(internal->vid, qid, &internal->m_vring[qid]);\n+\tifcvf_notify_queue(&internal->hw, qid);\n+}\n+\n+static void\n+update_used_ring(struct ifcvf_internal *internal, uint16_t qid)\n+{\n+\trte_vdpa_relay_used_ring(internal->vid, qid, &internal->m_vring[qid]);\n+\trte_vhost_vring_call(internal->vid, qid);\n+}\n+\n+static void *\n+vring_relay(void *arg)\n+{\n+\tint i, vid, epfd, fd, nfds;\n+\tstruct ifcvf_internal *internal = (struct ifcvf_internal *)arg;\n+\tstruct rte_vhost_vring vring;\n+\tstruct rte_intr_handle *intr_handle;\n+\tuint16_t qid, q_num;\n+\tstruct epoll_event events[IFCVF_MAX_QUEUES * 4];\n+\tstruct epoll_event ev;\n+\tint nbytes;\n+\tuint64_t buf;\n+\n+\tvid = internal->vid;\n+\tq_num = rte_vhost_get_vring_num(vid);\n+\t/* prepare the mediate vring */\n+\tfor (qid = 0; qid < q_num; qid++) {\n+\t\trte_vhost_get_vring_base(vid, qid,\n+\t\t\t\t&internal->m_vring[qid].avail->idx,\n+\t\t\t\t&internal->m_vring[qid].used->idx);\n+\t\trte_vdpa_relay_avail_ring(vid, qid, &internal->m_vring[qid]);\n+\t}\n+\n+\t/* add notify fd and interrupt fd to epoll */\n+\tepfd = epoll_create(IFCVF_MAX_QUEUES * 2);\n+\tif (epfd < 0) {\n+\t\tDRV_LOG(ERR, \"failed to create epoll instance.\");\n+\t\treturn NULL;\n+\t}\n+\tinternal->epfd = epfd;\n+\n+\tfor (qid = 0; qid < q_num; qid++) {\n+\t\tev.events = EPOLLIN | EPOLLPRI;\n+\t\trte_vhost_get_vhost_vring(vid, qid, &vring);\n+\t\tev.data.u64 = qid << 1 | (uint64_t)vring.kickfd << 32;\n+\t\tif (epoll_ctl(epfd, EPOLL_CTL_ADD, vring.kickfd, &ev) < 0) {\n+\t\t\tDRV_LOG(ERR, \"epoll add error: %s\", strerror(errno));\n+\t\t\treturn NULL;\n+\t\t}\n+\t}\n+\n+\tintr_handle = &internal->pdev->intr_handle;\n+\tfor (qid = 0; qid < q_num; qid++) {\n+\t\tev.events = EPOLLIN | EPOLLPRI;\n+\t\tev.data.u64 = 1 | qid << 1 |\n+\t\t\t(uint64_t)intr_handle->efds[qid] << 32;\n+\t\tif (epoll_ctl(epfd, EPOLL_CTL_ADD, intr_handle->efds[qid], &ev)\n+\t\t\t\t< 0) {\n+\t\t\tDRV_LOG(ERR, \"epoll add error: %s\", strerror(errno));\n+\t\t\treturn NULL;\n+\t\t}\n+\t}\n+\n+\t/* start relay with a first kick */\n+\tfor (qid = 0; qid < q_num; qid++)\n+\t\tifcvf_notify_queue(&internal->hw, qid);\n+\n+\t/* listen to the events and react accordingly */\n+\tfor (;;) {\n+\t\tnfds = epoll_wait(epfd, events, q_num * 2, -1);\n+\t\tif (nfds < 0) {\n+\t\t\tif (errno == EINTR)\n+\t\t\t\tcontinue;\n+\t\t\tDRV_LOG(ERR, \"epoll_wait return fail\\n\");\n+\t\t\treturn NULL;\n+\t\t}\n+\n+\t\tfor (i = 0; i < nfds; i++) {\n+\t\t\tfd = (uint32_t)(events[i].data.u64 >> 32);\n+\t\t\tdo {\n+\t\t\t\tnbytes = read(fd, &buf, 8);\n+\t\t\t\tif (nbytes < 0) {\n+\t\t\t\t\tif (errno == EINTR ||\n+\t\t\t\t\t    errno == EWOULDBLOCK ||\n+\t\t\t\t\t    errno == EAGAIN)\n+\t\t\t\t\t\tcontinue;\n+\t\t\t\t\tDRV_LOG(INFO, \"Error reading \"\n+\t\t\t\t\t\t\"kickfd: %s\",\n+\t\t\t\t\t\tstrerror(errno));\n+\t\t\t\t}\n+\t\t\t\tbreak;\n+\t\t\t} while (1);\n+\n+\t\t\tqid = events[i].data.u32 >> 1;\n+\n+\t\t\tif (events[i].data.u32 & 1)\n+\t\t\t\tupdate_used_ring(internal, qid);\n+\t\t\telse\n+\t\t\t\tupdate_avail_ring(internal, qid);\n+\t\t}\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+static int\n+setup_vring_relay(struct ifcvf_internal *internal)\n+{\n+\tint ret;\n+\n+\tret = pthread_create(&internal->tid, NULL, vring_relay,\n+\t\t\t(void *)internal);\n+\tif (ret) {\n+\t\tDRV_LOG(ERR, \"failed to create ring relay pthread.\");\n+\t\treturn -1;\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+unset_vring_relay(struct ifcvf_internal *internal)\n+{\n+\tvoid *status;\n+\n+\tif (internal->tid) {\n+\t\tpthread_cancel(internal->tid);\n+\t\tpthread_join(internal->tid, &status);\n+\t}\n+\tinternal->tid = 0;\n+\n+\tif (internal->epfd >= 0)\n+\t\tclose(internal->epfd);\n+\tinternal->epfd = -1;\n+\n+\treturn 0;\n+}\n+\n+static int\n+ifcvf_sw_fallback_switchover(struct ifcvf_internal *internal)\n+{\n+\tint ret;\n+\n+\t/* stop the direct IO data path */\n+\tunset_notify_relay(internal);\n+\tvdpa_ifcvf_stop(internal);\n+\tvdpa_disable_vfio_intr(internal);\n+\n+\tret = rte_vhost_host_notifier_ctrl(internal->vid, false);\n+\tif (ret && ret != -ENOTSUP)\n+\t\tgoto error;\n+\n+\t/* set up interrupt for interrupt relay */\n+\tret = m_enable_vfio_intr(internal);\n+\tif (ret)\n+\t\tgoto unmap;\n+\n+\t/* config the VF */\n+\tret = m_ifcvf_start(internal);\n+\tif (ret)\n+\t\tgoto unset_intr;\n+\n+\t/* set up vring relay thread */\n+\tret = setup_vring_relay(internal);\n+\tif (ret)\n+\t\tgoto stop_vf;\n+\n+\tinternal->sw_fallback_running = true;\n+\n+\treturn 0;\n+\n+stop_vf:\n+\tm_ifcvf_stop(internal);\n+unset_intr:\n+\tm_disable_vfio_intr(internal);\n+unmap:\n+\tifcvf_dma_map(internal, 0);\n+error:\n+\treturn -1;\n+}\n+\n static int\n ifcvf_dev_config(int vid)\n {\n@@ -579,8 +897,25 @@ ifcvf_dev_close(int vid)\n \t}\n \n \tinternal = list->internal;\n-\trte_atomic32_set(&internal->dev_attached, 0);\n-\tupdate_datapath(internal);\n+\n+\tif (internal->sw_fallback_running) {\n+\t\t/* unset ring relay */\n+\t\tunset_vring_relay(internal);\n+\n+\t\t/* reset VF */\n+\t\tm_ifcvf_stop(internal);\n+\n+\t\t/* remove interrupt setting */\n+\t\tm_disable_vfio_intr(internal);\n+\n+\t\t/* unset DMA map for guest memory */\n+\t\tifcvf_dma_map(internal, 0);\n+\n+\t\tinternal->sw_fallback_running = false;\n+\t} else {\n+\t\trte_atomic32_set(&internal->dev_attached, 0);\n+\t\tupdate_datapath(internal);\n+\t}\n \n \treturn 0;\n }\n@@ -604,7 +939,12 @@ ifcvf_set_features(int vid)\n \tinternal = list->internal;\n \trte_vhost_get_negotiated_features(vid, &features);\n \n-\tif (RTE_VHOST_NEED_LOG(features)) {\n+\tif (!RTE_VHOST_NEED_LOG(features))\n+\t\treturn 0;\n+\n+\tif (internal->sw_lm) {\n+\t\tifcvf_sw_fallback_switchover(internal);\n+\t} else {\n \t\trte_vhost_get_log_base(vid, &log_base, &log_size);\n \t\trte_vfio_container_dma_map(internal->vfio_container_fd,\n \t\t\t\tlog_base, IFCVF_LOG_BASE, log_size);\n",
    "prefixes": [
        "v2",
        "8/9"
    ]
}