get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 85508,
    "url": "https://patches.dpdk.org/api/patches/85508/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20201219143816.64174-2-jingjing.wu@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": "<20201219143816.64174-2-jingjing.wu@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20201219143816.64174-2-jingjing.wu@intel.com",
    "date": "2020-12-19T14:38:15",
    "name": "[v1,1/2] common/iavf: emulated pci interfaces on vfio-user client",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "9ede0f5f7da78956b32c5c9a516609099559119d",
    "submitter": {
        "id": 47,
        "url": "https://patches.dpdk.org/api/people/47/?format=api",
        "name": "Jingjing Wu",
        "email": "jingjing.wu@intel.com"
    },
    "delegate": {
        "id": 1540,
        "url": "https://patches.dpdk.org/api/users/1540/?format=api",
        "username": "qzhan15",
        "first_name": "Qi",
        "last_name": "Zhang",
        "email": "qi.z.zhang@intel.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20201219143816.64174-2-jingjing.wu@intel.com/mbox/",
    "series": [
        {
            "id": 14387,
            "url": "https://patches.dpdk.org/api/series/14387/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=14387",
            "date": "2020-12-19T14:38:14",
            "name": "introduce new iavf driver on vfio-user client",
            "version": 1,
            "mbox": "https://patches.dpdk.org/series/14387/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/85508/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/85508/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 11B4BA04B5;\n\tSat, 19 Dec 2020 15:49:53 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id BD30CCB3A;\n\tSat, 19 Dec 2020 15:49:33 +0100 (CET)",
            "from mga03.intel.com (mga03.intel.com [134.134.136.65])\n by dpdk.org (Postfix) with ESMTP id 4B761CAE2\n for <dev@dpdk.org>; Sat, 19 Dec 2020 15:49:30 +0100 (CET)",
            "from orsmga001.jf.intel.com ([10.7.209.18])\n by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 19 Dec 2020 06:49:29 -0800",
            "from dpdk-wujingji.sh.intel.com ([10.67.119.101])\n by orsmga001.jf.intel.com with ESMTP; 19 Dec 2020 06:49:27 -0800"
        ],
        "IronPort-SDR": [
            "\n 0sr+EF+iMEKaQ+VHwuBEuFmiGDA2osqTbJVR/QC90UvCfWPw+62fKv6kyCuWndDwHOeovEKML+\n vTrMNvFCQfjw==",
            "\n mNgfpWTJPuqDrDiwUX478M1p0V0cl4LYXrz8eOxlKDEffG/gPDoqWo9jIb04rkYDbPtSF5Yxu5\n qByxUw71A7bQ=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9839\"; a=\"175678239\"",
            "E=Sophos;i=\"5.78,433,1599548400\"; d=\"scan'208\";a=\"175678239\"",
            "E=Sophos;i=\"5.78,433,1599548400\"; d=\"scan'208\";a=\"414722504\""
        ],
        "X-ExtLoop1": "1",
        "From": "Jingjing Wu <jingjing.wu@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "jingjing.wu@intel.com, beilei.xing@intel.com, chenbo.xia@intel.com,\n xiuchun.lu@intel.com",
        "Date": "Sat, 19 Dec 2020 22:38:15 +0800",
        "Message-Id": "<20201219143816.64174-2-jingjing.wu@intel.com>",
        "X-Mailer": "git-send-email 2.21.1",
        "In-Reply-To": "<20201219143816.64174-1-jingjing.wu@intel.com>",
        "References": "<20201219143816.64174-1-jingjing.wu@intel.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH v1 1/2] common/iavf: emulated pci interfaces on\n\tvfio-user client",
        "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 <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 <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "This patch implements Emulated pci interfaces on vfio-user client\nwhich is located in common/iavf/vfio_user/.\nFour main functions provided to upper layer (driver) to set\nup or talk to device:\n - client_vfio_user_setup\n - client_vfio_user_release\n - client_vfio_user_get_bar_addr\n - client_vfio_user_pci_bar_access\n\n      ----------------------\n      | ------------------ |\n      | |  iavf driver   | |\n      | ------------------ |\n      | ------------------ |\n      | | device emulate | |------>(common/iavf/vfio_user/)\n      | ------------------ |\n      ----------------------\n                |\n                |\n      ----------------------\n      |      vfio-user     |\n      |       client       |\n      ----------------------\n\nSigned-off-by: Jingjing Wu <jingjing.wu@intel.com>\nSigned-off-by: Chenbo Xia <chenbo.xia@intel.com>\n---\n config/rte_config.h                           |   3 +\n drivers/common/iavf/iavf_common.c             |   7 +\n drivers/common/iavf/iavf_impl.c               |  45 +-\n drivers/common/iavf/iavf_osdep.h              |  14 +\n drivers/common/iavf/iavf_type.h               |   3 +\n drivers/common/iavf/meson.build               |  11 +-\n drivers/common/iavf/version.map               |   4 +\n drivers/common/iavf/vfio_user/vfio_user_pci.c | 517 ++++++++++++++++++\n drivers/common/iavf/vfio_user/vfio_user_pci.h |  66 +++\n 9 files changed, 668 insertions(+), 2 deletions(-)\n create mode 100644 drivers/common/iavf/vfio_user/vfio_user_pci.c\n create mode 100644 drivers/common/iavf/vfio_user/vfio_user_pci.h",
    "diff": "diff --git a/config/rte_config.h b/config/rte_config.h\nindex a0b5160ff2..76ed1ae83f 100644\n--- a/config/rte_config.h\n+++ b/config/rte_config.h\n@@ -151,4 +151,7 @@\n #define RTE_LIBRTE_PMD_DLB2_SW_CREDIT_QUANTA 32\n #define RTE_PMD_DLB2_DEFAULT_DEPTH_THRESH 256\n \n+/* IAVF bsed on vfio_user client */\n+#define RTE_LIBRTE_IAVF_CLIENT 1\n+\n #endif /* _RTE_CONFIG_H_ */\ndiff --git a/drivers/common/iavf/iavf_common.c b/drivers/common/iavf/iavf_common.c\nindex c951b7d787..2e68f5d08b 100644\n--- a/drivers/common/iavf/iavf_common.c\n+++ b/drivers/common/iavf/iavf_common.c\n@@ -20,6 +20,13 @@ enum iavf_status iavf_set_mac_type(struct iavf_hw *hw)\n \n \tDEBUGFUNC(\"iavf_set_mac_type\\n\");\n \n+#ifdef RTE_LIBRTE_IAVF_CLIENT\n+\tif (hw->bus.type == iavf_bus_type_vfio_user) {\n+\t\thw->mac.type = IAVF_MAC_VF;\n+\t\treturn status;\n+\t}\n+#endif\n+\n \tif (hw->vendor_id == IAVF_INTEL_VENDOR_ID) {\n \t\tswitch (hw->device_id) {\n \t\tcase IAVF_DEV_ID_X722_VF:\ndiff --git a/drivers/common/iavf/iavf_impl.c b/drivers/common/iavf/iavf_impl.c\nindex fc0da31753..79262bf50d 100644\n--- a/drivers/common/iavf/iavf_impl.c\n+++ b/drivers/common/iavf/iavf_impl.c\n@@ -10,9 +10,14 @@\n #include <rte_malloc.h>\n #include <rte_memzone.h>\n \n+#ifdef RTE_LIBRTE_IAVF_CLIENT\n+#include \"vfio_user/vfio_user_pci.h\"\n+#endif\n #include \"iavf_type.h\"\n #include \"iavf_prototype.h\"\n \n+int iavf_common_logger;\n+\n enum iavf_status\n iavf_allocate_dma_mem_d(__rte_unused struct iavf_hw *hw,\n \t\t\tstruct iavf_dma_mem *mem,\n@@ -85,4 +90,42 @@ iavf_free_virt_mem_d(__rte_unused struct iavf_hw *hw,\n \treturn IAVF_SUCCESS;\n }\n \n-RTE_LOG_REGISTER(iavf_common_logger, pmd.common.iavf, NOTICE);\n+#ifdef RTE_LIBRTE_IAVF_CLIENT\n+uint32_t\n+iavf_read_addr(struct iavf_hw *hw, uint32_t offset)\n+{\n+\tuint32_t value = 0;\n+\n+\tif (!hw || !hw->hw_addr)\n+\t\treturn 0;\n+\n+\tif (hw->bus.type == iavf_bus_type_vfio_user)\n+\t\tclient_vfio_user_pci_bar_access(\n+\t\t\t\t(struct vfio_device *)hw->hw_addr,\n+\t\t\t\t0, offset, 4, &value, false);\n+\telse\n+\t\tvalue = readl(hw->hw_addr + offset);\n+\n+\treturn value;\n+}\n+\n+void\n+iavf_write_addr(struct iavf_hw *hw, uint32_t offset, uint32_t value)\n+{\n+\tif (!hw || !hw->hw_addr)\n+\t\treturn;\n+\tif (hw->bus.type == iavf_bus_type_vfio_user)\n+\t\tclient_vfio_user_pci_bar_access(\n+\t\t\t\t(struct vfio_device *)hw->hw_addr,\n+\t\t\t\t0, offset, 4, &value, true);\n+\telse\n+\t\twritel(value, hw->hw_addr + offset);\n+}\n+#endif\n+\n+RTE_INIT(iavf_common_init_log)\n+{\n+\tiavf_common_logger = rte_log_register(\"pmd.common.iavf\");\n+\tif (iavf_common_logger >= 0)\n+\t\trte_log_set_level(iavf_common_logger, RTE_LOG_NOTICE);\n+}\ndiff --git a/drivers/common/iavf/iavf_osdep.h b/drivers/common/iavf/iavf_osdep.h\nindex 7cba13ff74..025d48a702 100644\n--- a/drivers/common/iavf/iavf_osdep.h\n+++ b/drivers/common/iavf/iavf_osdep.h\n@@ -107,8 +107,22 @@ writeq(uint64_t value, volatile void *addr)\n \trte_write64(rte_cpu_to_le_64(value), addr);\n }\n \n+#ifdef RTE_LIBRTE_IAVF_CLIENT\n+struct iavf_hw;\n+\n+__rte_internal\n+uint32_t iavf_read_addr(struct iavf_hw *hw, uint32_t offset);\n+__rte_internal\n+void iavf_write_addr(struct iavf_hw *hw, uint32_t offset, uint32_t value);\n+\n+#define wr32(a, reg, value)  iavf_write_addr((a), (reg), (value))\n+#define rd32(a, reg)         iavf_read_addr((a), (reg))\n+\n+#else\n #define wr32(a, reg, value) writel((value), (a)->hw_addr + (reg))\n #define rd32(a, reg)        readl((a)->hw_addr + (reg))\n+#endif /* RTE_LIBRTE_IAVF_CLIENT */\n+\n #define wr64(a, reg, value) writeq((value), (a)->hw_addr + (reg))\n #define rd64(a, reg)        readq((a)->hw_addr + (reg))\n \ndiff --git a/drivers/common/iavf/iavf_type.h b/drivers/common/iavf/iavf_type.h\nindex 0990c9aa33..faa4a21eac 100644\n--- a/drivers/common/iavf/iavf_type.h\n+++ b/drivers/common/iavf/iavf_type.h\n@@ -264,6 +264,9 @@ enum iavf_bus_type {\n \tiavf_bus_type_pci,\n \tiavf_bus_type_pcix,\n \tiavf_bus_type_pci_express,\n+#ifdef RTE_LIBRTE_IAVF_CLIENT\n+\tiavf_bus_type_vfio_user,\n+#endif\n \tiavf_bus_type_reserved\n };\n \ndiff --git a/drivers/common/iavf/meson.build b/drivers/common/iavf/meson.build\nindex 1f4d8b898d..e0160ea135 100644\n--- a/drivers/common/iavf/meson.build\n+++ b/drivers/common/iavf/meson.build\n@@ -1,7 +1,16 @@\n # SPDX-License-Identifier: BSD-3-Clause\n # Copyright(c) 2019-2020 Intel Corporation\n \n-sources = files('iavf_adminq.c', 'iavf_common.c', 'iavf_impl.c')\n+includes += include_directories('vfio_user')\n+\n+sources = files(\n+\t'iavf_adminq.c',\n+\t'iavf_common.c',\n+\t'iavf_impl.c',\n+\t'vfio_user/vfio_user_pci.c'\n+)\n+\n+deps += ['vfio_user']\n \n if cc.has_argument('-Wno-pointer-to-int-cast')\n         cflags += '-Wno-pointer-to-int-cast'\ndiff --git a/drivers/common/iavf/version.map b/drivers/common/iavf/version.map\nindex e0f117197c..8808779ab7 100644\n--- a/drivers/common/iavf/version.map\n+++ b/drivers/common/iavf/version.map\n@@ -7,6 +7,10 @@ INTERNAL {\n \tiavf_set_mac_type;\n \tiavf_shutdown_adminq;\n \tiavf_vf_parse_hw_config;\n+\tclient_vfio_user_setup;\n+\tclient_vfio_user_get_bar_addr;\n+\tiavf_write_addr;\n+\tiavf_read_addr;\n \n \tlocal: *;\n };\ndiff --git a/drivers/common/iavf/vfio_user/vfio_user_pci.c b/drivers/common/iavf/vfio_user/vfio_user_pci.c\nnew file mode 100644\nindex 0000000000..0ff2adeb40\n--- /dev/null\n+++ b/drivers/common/iavf/vfio_user/vfio_user_pci.c\n@@ -0,0 +1,517 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include <stdio.h>\n+#include <errno.h>\n+#include <stdint.h>\n+#include <string.h>\n+#include <unistd.h>\n+#include <stdbool.h>\n+#include <stdlib.h>\n+\n+#include <sys/queue.h>\n+#include <sys/mman.h>\n+#include <sys/eventfd.h>\n+\n+#include <rte_common.h>\n+#include <rte_memory.h>\n+#include <rte_malloc.h>\n+#include <rte_memcpy.h>\n+#include <rte_tailq.h>\n+#include <rte_errno.h>\n+#include <rte_vfio_user.h>\n+\n+#include \"vfio_user_pci.h\"\n+\n+#define IAVF_MEM_EVENT_CLB_NAME \"iavf_mem_event_clb\"\n+\n+/* buffer length for irq set */\n+#define MSIX_IRQ_SET_BUF_LEN (sizeof(struct vfio_irq_set) + \\\n+\t\t\t\tsizeof(int) * IAVF_CLIENT_MAX_VECTORS)\n+/* buffer length for region infor get */\n+#define REG_INFO_GET_BUF_LEN (sizeof(struct vfio_region_info) + \\\n+\t\t\tsizeof(struct vfio_region_info_cap_sparse_mmap) \\\n+\t\t\t+ 2 * sizeof(struct vfio_region_sparse_mmap_area))\n+\n+static inline int\n+vfio_add_mr(struct vfio_device *dev, struct vfio_memory_region *mr)\n+{\n+\tif (dev->nb_mrs == RTE_VUSER_MAX_DMA) {\n+\t\tCLIENT_LOG(ERR, \"Exceed Maximum supported memory regions %d\",\n+\t\t\tRTE_VUSER_MAX_DMA);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tTAILQ_INSERT_HEAD(&dev->mrs_list, mr, link);\n+\tdev->nb_mrs++;\n+\n+\tCLIENT_LOG(DEBUG, \"Add memory region: FD %d, VADDR 0x%lx,\"\n+\t\t\t  \" IOVA 0x%lx, Size 0x%lx\",\n+\t\t\t  mr->fd, mr->vaddr, mr->iova, mr->size);\n+\treturn 0;\n+}\n+\n+static inline void\n+vfio_remove_mr(struct vfio_device *dev, struct vfio_memory_region *mr)\n+{\n+\tif (dev->nb_mrs == 0)\n+\t\treturn;\n+\n+\tCLIENT_LOG(DEBUG, \"Remove memory region: FD %d, VADDR 0x%lx,\"\n+\t\t\t  \" IOVA 0x%lx, Size 0x%lx\",\n+\t\t\t  mr->fd, mr->vaddr, mr->iova, mr->size);\n+\tTAILQ_REMOVE(&dev->mrs_list, mr, link);\n+\tdev->nb_mrs--;\n+\trte_free(mr);\n+}\n+\n+static int\n+update_vfio_memory_region(const struct rte_memseg_list *msl __rte_unused,\n+\t\tconst struct rte_memseg *ms, void *arg)\n+{\n+\tint ret = 0;\n+\tstruct vfio_device *dev = arg;\n+\tstruct vfio_memory_region *mr;\n+\tstruct rte_vfio_user_mem_reg mem;\n+\tuint64_t offset;\n+\n+\tmr = rte_zmalloc_socket(\"iavf_client_vfio_user\", sizeof(*mr),\n+\t\t\t\t0, SOCKET_ID_ANY);\n+\tif (mr == NULL)\n+\t\treturn -ENOMEM;\n+\n+\tmr->vaddr = (uint64_t)(uintptr_t)ms->addr;\n+\tmr->iova = ms->iova;\n+\tmr->size = ms->len;\n+\tmr->fd = rte_memseg_get_fd_thread_unsafe(ms);\n+\tif (mr->fd == -1) {\n+\t\tCLIENT_LOG(ERR, \"Error to get the memory fd\");\n+\t\trte_free(mr);\n+\t\treturn -EFAULT;\n+\t}\n+\tif (rte_memseg_get_fd_offset_thread_unsafe(ms, &offset) < 0) {\n+\t\tCLIENT_LOG(ERR, \"Error to get the memory map offset\");\n+\t\trte_free(mr);\n+\t\treturn -EFAULT;\n+\t}\n+\tmr->offset = offset;\n+\n+\tret = vfio_add_mr(dev, mr);\n+\tif (ret) {\n+\t\tCLIENT_LOG(ERR, \"Error to add memory region\");\n+\t\trte_free(mr);\n+\t\treturn ret;\n+\t}\n+\n+\tmem.gpa = mr->iova;\n+\tmem.size = mr->size;\n+\tmem.fd_offset = mr->offset;\n+\tmem.protection = PROT_WRITE | PROT_READ;\n+\tmem.flags = RTE_VUSER_MEM_MAPPABLE;\n+\n+\tret = rte_vfio_user_dma_map(dev->dev_id, &mem, &mr->fd, 1);\n+\tif (ret) {\n+\t\tCLIENT_LOG(ERR, \"Error to send dma map request\");\n+\t\tvfio_remove_mr(dev, mr);\n+\t\trte_free(mr);\n+\t\treturn ret;\n+\t}\n+\treturn ret;\n+\n+}\n+\n+static int\n+vfio_device_dma_map(struct vfio_device *dev)\n+{\n+\tif (rte_memseg_walk_thread_unsafe(update_vfio_memory_region, dev) < 0)\n+\t\treturn -1;\n+\n+\treturn 0;\n+}\n+\n+\n+static void\n+vfio_device_dma_unmap(struct vfio_device *dev)\n+{\n+\tint ret;\n+\tstruct vfio_memory_region *mr;\n+\n+\tif (dev->nb_mrs == 0)\n+\t\treturn;\n+\n+\twhile ((mr = TAILQ_FIRST(&dev->mrs_list))) {\n+\t\tstruct rte_vfio_user_mem_reg mem;\n+\n+\t\tmem.gpa = mr->iova;\n+\t\tmem.size = mr->size;\n+\t\tmem.fd_offset = mr->offset;\n+\t\tmem.protection = PROT_WRITE | PROT_READ;\n+\t\tret = rte_vfio_user_dma_unmap(dev->dev_id, &mem, 1);\n+\t\tif (ret)\n+\t\t\tCLIENT_LOG(ERR, \"Error to send dma unmap request for\"\n+\t\t\t\t\" mr FD %d, VADDR 0x%lx, IOVA 0x%lx, Size 0x%lx\",\n+\t\t\t\t mr->fd, mr->vaddr, mr->iova, mr->size);\n+\t\tTAILQ_REMOVE(&dev->mrs_list, mr, link);\n+\t\tdev->nb_mrs--;\n+\t\trte_free(mr);\n+\t}\n+\treturn;\n+}\n+\n+static void\n+iavf_mem_event_cb(enum rte_mem_event type __rte_unused,\n+\t\t\t const void *addr,\n+\t\t\t size_t len __rte_unused,\n+\t\t\t void *arg)\n+{\n+\tstruct vfio_device *dev = arg;\n+\tstruct rte_memseg_list *msl;\n+\tuint16_t ret;\n+\n+\t/* ignore externally allocated memory */\n+\tmsl = rte_mem_virt2memseg_list(addr);\n+\tif (msl->external)\n+\t\treturn;\n+\tret = vfio_device_dma_map(dev);\n+\tif (ret)\n+\t\tCLIENT_LOG(ERR, \"DMA map failed\");\n+}\n+\n+static inline struct vfio_info_cap_header *\n+vfio_device_get_info_cap(struct vfio_region_info *info, int cap)\n+{\n+\tstruct vfio_info_cap_header *h;\n+\tsize_t offset;\n+\n+\toffset = info->cap_offset;\n+\twhile (offset != 0 && offset < info->argsz) {\n+\t\th = (struct vfio_info_cap_header *)((uintptr_t)info + offset);\n+\t\tif (h->id == cap) {\n+\t\t\treturn h;\n+\t\t}\n+\t\toffset = h->next;\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+static int\n+vfio_device_setup_sparse_mmaps(struct vfio_device *device, int index,\n+\t\t\t       struct vfio_region_info *info, int *fds)\n+{\n+\tstruct vfio_info_cap_header *hdr;\n+\tstruct vfio_region_info_cap_sparse_mmap *sparse;\n+\tstruct vfio_pci_region *region = &device->regions[index];\n+\tuint32_t i, j = 0;\n+\tint prot = 0;\n+\n+\thdr = vfio_device_get_info_cap(info, VFIO_REGION_INFO_CAP_SPARSE_MMAP);\n+\tif (!hdr) {\n+\t\tCLIENT_LOG(ERR, \"Device doesn't have sparse mmap\");\n+\t\treturn -EEXIST;\n+\t}\n+\n+\tsparse = container_of(hdr, struct vfio_region_info_cap_sparse_mmap, header);\n+\tfor (i = 0; i < sparse->nr_areas; i++) {\n+\t\tif (sparse->areas[i].size == 0)\n+\t\t\tcontinue;\n+\t\tregion->mmaps[j].offset = sparse->areas[i].offset;\n+\t\tregion->mmaps[j].size = sparse->areas[i].size;\n+\t\tprot |= info->flags & VFIO_REGION_INFO_FLAG_READ ? PROT_READ : 0;\n+\t\tprot |= info->flags & VFIO_REGION_INFO_FLAG_WRITE ? PROT_WRITE : 0;\n+\t\tif (*fds) {\n+\t\t\t/* Use single fd for now*/\n+\t\t\tregion->mmaps[j].mem = mmap(NULL, region->mmaps[j].size,\n+\t\t\t\t\t\tprot, MAP_SHARED, fds[0],\n+\t\t\t\t\t\tregion->offset + region->mmaps[j].offset);\n+\t\t\tif (region->mmaps[j].mem == MAP_FAILED) {\n+\t\t\t\tCLIENT_LOG(ERR, \"Device SPARSE MMAP failed\");\n+\t\t\t\treturn -EIO;\n+\t\t\t}\n+\t\t} else {\n+\t\t\tCLIENT_LOG(ERR, \"No valid fd, skip mmap for\"\n+\t\t\t\t\t\" bar %d region %u\", index, i);\n+\t\t}\n+\t\tCLIENT_LOG(DEBUG, \"Sparse region %u, Size 0x%llx,\"\n+\t\t\t\t  \" Offset 0x%llx, Map addr %p\",\n+\t\t\t\t  i, sparse->areas[i].size,\n+\t\t\t\t  sparse->areas[i].offset, region->mmaps[j].mem);\n+\t\tj++;\n+\t}\n+\tdevice->regions[index].nr_mmaps = j;\n+\n+\treturn 0;\n+}\n+\n+static int\n+vfio_device_map_region(struct vfio_device *device __rte_unused,\n+\t\t\tstruct vfio_pci_region *region, int fd)\n+{\n+\tint prot = 0;\n+\n+\tprot |= region->flags & VFIO_REGION_INFO_FLAG_READ ? PROT_READ : 0;\n+\tprot |= region->flags & VFIO_REGION_INFO_FLAG_WRITE ? PROT_WRITE : 0;\n+\n+\tregion->mmaps[0].offset = 0;\n+\tregion->mmaps[0].size = region->size;\n+\n+\tregion->mmaps[0].mem = mmap(NULL, region->size, prot, MAP_SHARED,\n+\t\t\t\t    fd, region->offset);\n+\tif (region->mmaps[0].mem == MAP_FAILED) {\n+\t\tCLIENT_LOG(ERR, \"Device Region MMAP failed\");\n+\t\treturn -EFAULT;\n+\t}\n+\tCLIENT_LOG(DEBUG, \"Memory mapped to %p\", region->mmaps[0].mem);\n+\tregion->nr_mmaps = 1;\n+\n+\treturn 0;\n+}\n+\n+static void\n+vfio_device_unmap_bars(struct vfio_device *dev)\n+{\n+\tuint32_t i, j;\n+\tstruct vfio_pci_region *region;\n+\n+\tfor (i = 0; i < dev->pci_regions; i++) {\n+\t\tregion = &dev->regions[i];\n+\t\tfor (j = 0; j < region->nr_mmaps; j++) {\n+\t\t\tif (region->mmaps[j].mem)\n+\t\t\t\tmunmap(region->mmaps[j].mem, region->mmaps[j].size);\n+\t\t}\n+\t}\n+\tmemset(dev->regions, 0, sizeof(dev->regions));\n+}\n+\n+static int\n+vfio_user_create_irqfd(struct vfio_device *device, uint32_t count)\n+{\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < count; i++) {\n+\t\tdevice->irqfds[i] = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);\n+\t\tif (device->irqfds[i] < 0) {\n+\t\t\tCLIENT_LOG(ERR, \"Failed to create irqfd\");\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+struct vfio_device *\n+client_vfio_user_setup(const char *path, int socket)\n+{\n+\tstruct vfio_device *device = NULL;\n+\tchar irq_set_buf[MSIX_IRQ_SET_BUF_LEN];\n+\tchar reg_get_buf[REG_INFO_GET_BUF_LEN];\n+\tint fds[VFIO_MAXIMUM_SPARSE_MMAP_REGISONS];\n+\tstruct vfio_device_info dev_info = {};\n+\tstruct vfio_irq_info irq_info = {};\n+\tstruct vfio_irq_set *irq_set;\n+\tstruct vfio_region_info *reg_info;\n+\tuint32_t i;\n+\tint dev_id;\n+\tint ret;\n+\n+\tdevice = rte_zmalloc_socket(\"iavf_client_vfio_user\",\n+\t\t\t\t    sizeof(struct vfio_device),\n+\t\t\t\t    0, socket);\n+\tif (!device)\n+\t\treturn NULL;\n+\n+\tTAILQ_INIT(&device->mrs_list);\n+\n+\tdev_id = rte_vfio_user_attach_dev(path);\n+\tif (dev_id < 0) {\n+\t\trte_free(device);\n+\t\tCLIENT_LOG(ERR, \"Error to setup vfio-user via path %s\", path);\n+\t\treturn NULL;\n+\t}\n+\n+\tdevice->dev_id = dev_id;\n+\tsnprintf(device->name, sizeof(device->name), \"vfio-user%u\", dev_id);\n+\tsnprintf(device->path, PATH_MAX, \"%s\", path);\n+\n+\tret = rte_vfio_user_get_dev_info(dev_id, &dev_info);\n+\tif (ret) {\n+\t\tCLIENT_LOG(ERR, \"Device get info failed\");\n+\t\tgoto cleanup;\n+\t}\n+\tdevice->pci_regions = dev_info.num_regions;\n+\tdevice->flags = dev_info.flags;\n+\n+\tirq_info.argsz = sizeof(struct vfio_irq_info);\n+\tirq_info.index = VFIO_PCI_MSIX_IRQ_INDEX;\n+\tret = rte_vfio_user_get_irq_info(dev_id, &irq_info);\n+\tif (ret) {\n+\t\tCLIENT_LOG(ERR, \"IRQ get info failed\");\n+\t\tgoto cleanup;\n+\t}\n+\n+\tif (irq_info.count) {\n+\t\tif (vfio_user_create_irqfd(device, irq_info.count))\n+\t\t\tgoto cleanup;\n+\n+\t\tirq_set = (struct vfio_irq_set *)irq_set_buf;\n+\t\tirq_set->argsz = sizeof(irq_set_buf);\n+\t\tirq_set->count = RTE_MIN(irq_info.count,\n+\t\t\t\t\t (uint32_t)IAVF_CLIENT_MAX_VECTORS);\n+\t\tirq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD |\n+\t\t\t\t VFIO_IRQ_SET_ACTION_TRIGGER;\n+\t\tirq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;\n+\t\tirq_set->start = 0;\n+\t\trte_memcpy(irq_set->data, device->irqfds,\n+\t\t\t   sizeof(int) * IAVF_CLIENT_MAX_VECTORS);\n+\t\tret = rte_vfio_user_set_irqs(dev_id, irq_set);\n+\t\tif (ret) {\n+\t\t\tCLIENT_LOG(ERR, \"IRQ set failed\");\n+\t\t\tgoto cleanup;\n+\t\t}\n+\t}\n+\n+\treg_info = (struct vfio_region_info *)reg_get_buf;\n+\n+\tfor (i = 0; i < device->pci_regions; i++) {\n+\t\tmemset(reg_info, 0, REG_INFO_GET_BUF_LEN);\n+\t\tmemset(fds, 0, sizeof(fds));\n+\n+\t\treg_info->index = i;\n+\t\treg_info->argsz = sizeof(struct vfio_region_info);\n+\t\tret = rte_vfio_user_get_reg_info(dev_id, reg_info, fds);\n+\t\tif (reg_info->argsz > sizeof(struct vfio_region_info))\n+\t\t\tret = rte_vfio_user_get_reg_info(dev_id, reg_info, fds);\n+\t\tif (ret) {\n+\t\t\tCLIENT_LOG(ERR, \"Device setup bar %d failed\", i);\n+\t\t\tgoto cleanup;\n+\t\t}\n+\n+\t\tdevice->regions[i].size = reg_info->size;\n+\t\tdevice->regions[i].offset = reg_info->offset;\n+\t\tdevice->regions[i].flags = reg_info->flags;\n+\n+\t\tCLIENT_LOG(DEBUG, \"Bar %d, Size 0x%llx, Offset 0x%llx,\"\n+\t\t\t\" Flags 0x%x, Cap offset %u\",\n+\t\t\ti, reg_info->size, reg_info->offset,\n+\t\t\treg_info->flags, reg_info->cap_offset);\n+\n+\t\t/* Setup MMAP if any */\n+\t\tif (reg_info->size &&\n+\t\t    (reg_info->flags & VFIO_REGION_INFO_FLAG_MMAP)) {\n+\t\t\t/* Try to map sparse region first */\n+\t\t\tif (reg_info->flags & VFIO_REGION_INFO_FLAG_CAPS)\n+\t\t\t\tret = vfio_device_setup_sparse_mmaps(device, i,\n+\t\t\t\t\t\t\t     reg_info, fds);\n+\t\t\telse\n+\t\t\t\tret = vfio_device_map_region(device,\n+\t\t\t\t\t\t&device->regions[i], fds[0]);\n+\n+\t\t\tif (ret != 0) {\n+\t\t\t\tCLIENT_LOG(ERR, \"Setup Device %s region %d failed\",\n+\t\t\t\t\t   device->name, i);\n+\t\t\t\tgoto cleanup;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\t/* Register DMA Region */\n+\tret = vfio_device_dma_map(device);\n+\tif (ret) {\n+\t\tCLIENT_LOG(ERR, \"Container DMA map failed\");\n+\t\tgoto cleanup;\n+\t}\n+\n+\tCLIENT_LOG(DEBUG, \"Device %s, Path %s Setup Successfully\",\n+\t\t   device->name, device->path);\n+\n+\tif (rte_mem_event_callback_register(IAVF_MEM_EVENT_CLB_NAME,\n+\t\t\t\tiavf_mem_event_cb, device)) {\n+\t\tif (rte_errno != ENOTSUP) {\n+\t\t\tCLIENT_LOG(ERR, \"Failed to register mem event\"\n+\t\t\t\t\t\" callback\");\n+\t\t\tgoto cleanup;\n+\t\t}\n+\t}\n+\n+\treturn device;\n+\n+cleanup:\n+\trte_vfio_user_detach_dev(dev_id);\n+\trte_free(device);\n+\treturn NULL;\n+}\n+\n+void\n+client_vfio_user_release(struct vfio_device *dev)\n+{\n+\tvfio_device_unmap_bars(dev);\n+\tvfio_device_dma_unmap(dev);\n+\trte_vfio_user_detach_dev(dev->dev_id);\n+\n+\trte_free(dev);\n+}\n+\n+void *\n+client_vfio_user_get_bar_addr(struct vfio_device *dev, uint32_t index,\n+\t\t\t      uint64_t offset, uint32_t len)\n+{\n+\tstruct vfio_pci_region *region = &dev->regions[index];\n+\tuint32_t i;\n+\n+\tif (!region->size || !(region->flags & VFIO_REGION_INFO_FLAG_MMAP))\n+\t\treturn NULL;\n+\n+\tfor (i = 0; i < region->nr_mmaps; i++) {\n+\t\tif (region->mmaps[i].mem &&\n+\t\t    (region->mmaps[i].offset <= offset) &&\n+\t\t    ((offset + len) <= (region->mmaps[i].offset + region->mmaps[i].size))) {\n+\t\t\treturn (void *)((uintptr_t)region->mmaps[i].mem + \\\n+\t\t\t\t\toffset - region->mmaps[i].offset);\n+\t\t}\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+int\n+client_vfio_user_pci_bar_access(struct vfio_device *dev, uint32_t index,\n+\t\t\t\tuint64_t offset, size_t len,\n+\t\t\t\tvoid *buf, bool is_write)\n+{\n+\tstruct vfio_pci_region *region = &dev->regions[index];\n+\tuint64_t sparse_size, sparse_offset, bar_addr;\n+\tuint32_t i;\n+\tint ret;\n+\n+\tif ((offset + len > region->size) ||\n+\t    (is_write && !(region->flags & VFIO_REGION_INFO_FLAG_WRITE)) ||\n+\t    (!is_write && !(region->flags & VFIO_REGION_INFO_FLAG_READ)))\n+\t\treturn -EINVAL;\n+\n+\t/* Read/write through MMAP */\n+\tfor (i = 0; i < region->nr_mmaps; i++) {\n+\t\tsparse_offset = region->mmaps[i].offset;\n+\t\tsparse_size = region->mmaps[i].offset + region->mmaps[i].size;\n+\n+\t\tif ((offset >= sparse_offset) &&\n+\t\t    (offset + len <= sparse_size)) {\n+\t\t\tbar_addr = (uint64_t)(uintptr_t)region->mmaps[i].mem +\n+\t\t\t\toffset - sparse_offset;\n+\t\t\tif (is_write)\n+\t\t\t\trte_memcpy((void *)bar_addr, buf, len);\n+\t\t\telse\n+\t\t\t\trte_memcpy(buf, (void *)bar_addr, len);\n+\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\n+\t/* Read/write through message */\n+\tif (is_write)\n+\t\tret = rte_vfio_user_region_write(dev->dev_id, index,\n+\t\t\t\t\t\t offset, len, buf);\n+\telse\n+\t\tret = rte_vfio_user_region_read(dev->dev_id, index,\n+\t\t\t\t\t\t offset, len, buf);\n+\treturn ret;\n+}\ndiff --git a/drivers/common/iavf/vfio_user/vfio_user_pci.h b/drivers/common/iavf/vfio_user/vfio_user_pci.h\nnew file mode 100644\nindex 0000000000..da2a67343a\n--- /dev/null\n+++ b/drivers/common/iavf/vfio_user/vfio_user_pci.h\n@@ -0,0 +1,66 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#ifndef _VFIO_USER_PCI_H\n+#define _VFIO_USER_PCI_H\n+\n+#include <linux/vfio.h>\n+#include <linux/limits.h>\n+\n+#define IAVF_CLIENT_MAX_VECTORS\t\t\t16\n+#define VFIO_MAXIMUM_SPARSE_MMAP_REGISONS\t8\n+\n+struct vfio_memory_region {\n+\tTAILQ_ENTRY(vfio_memory_region) link;\n+\tuint64_t iova;\n+\tuint64_t size; /* bytes */\n+\tuint64_t vaddr;\n+\tuint64_t offset;\n+\tint fd;\n+};\n+\n+struct vfio_sparse_mmaps {\n+\tvoid *mem;\n+\tuint64_t offset;\n+\tsize_t size;\n+};\n+\n+struct vfio_pci_region {\n+\tuint64_t offset;\n+\tsize_t size;\n+\tuint64_t flags;\n+\tuint32_t nr_mmaps;\n+\tstruct vfio_sparse_mmaps mmaps[VFIO_MAXIMUM_SPARSE_MMAP_REGISONS];\n+};\n+\n+TAILQ_HEAD(vfio_memory_region_list, vfio_memory_region);\n+\n+struct vfio_device {\n+\tint dev_id;\n+\tchar name[64];\n+\tchar path[PATH_MAX];\n+\tuint64_t flags;\n+\tuint32_t pci_regions;\n+\tuint32_t nb_mrs;\n+\tstruct vfio_pci_region regions[VFIO_PCI_NUM_REGIONS];\n+\tint irqfds[IAVF_CLIENT_MAX_VECTORS];\n+\tstruct vfio_memory_region_list mrs_list;\n+};\n+\n+extern int iavf_common_logger;\n+#define CLIENT_LOG(level, fmt, args...) \\\n+\trte_log(RTE_LOG_ ## level, iavf_common_logger, \"%s(): \" fmt \"\\n\", \\\n+\t\t__func__, ## args)\n+\n+__rte_internal\n+struct vfio_device *client_vfio_user_setup(const char *path, int socket);\n+void client_vfio_user_release(struct vfio_device *dev);\n+__rte_internal\n+void *client_vfio_user_get_bar_addr(struct vfio_device *dev, uint32_t index,\n+\t\t\t\t    uint64_t offset, uint32_t len);\n+int client_vfio_user_pci_bar_access(struct vfio_device *dev, uint32_t index,\n+\t\t\t\t    uint64_t offset, size_t len, void *buf,\n+\t\t\t\t    bool is_write);\n+\n+#endif\n",
    "prefixes": [
        "v1",
        "1/2"
    ]
}