get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 85397,
    "url": "https://patches.dpdk.org/api/patches/85397/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20201218073851.93609-9-chenbo.xia@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": "<20201218073851.93609-9-chenbo.xia@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20201218073851.93609-9-chenbo.xia@intel.com",
    "date": "2020-12-18T07:38:50",
    "name": "[8/9] test/vfio_user: introduce functional test",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "1ad991c1c932ad73c3d8088e6b178c621beb74b2",
    "submitter": {
        "id": 1276,
        "url": "https://patches.dpdk.org/api/people/1276/?format=api",
        "name": "Chenbo Xia",
        "email": "chenbo.xia@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20201218073851.93609-9-chenbo.xia@intel.com/mbox/",
    "series": [
        {
            "id": 14361,
            "url": "https://patches.dpdk.org/api/series/14361/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=14361",
            "date": "2020-12-18T07:38:42",
            "name": "Introduce vfio-user library",
            "version": 1,
            "mbox": "https://patches.dpdk.org/series/14361/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/85397/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/85397/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 05F3CA09F6;\n\tFri, 18 Dec 2020 08:56:57 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 6001FCACA;\n\tFri, 18 Dec 2020 08:54:39 +0100 (CET)",
            "from mga05.intel.com (mga05.intel.com [192.55.52.43])\n by dpdk.org (Postfix) with ESMTP id A7C01CAC0\n for <dev@dpdk.org>; Fri, 18 Dec 2020 08:54:37 +0100 (CET)",
            "from fmsmga008.fm.intel.com ([10.253.24.58])\n by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 17 Dec 2020 23:54:37 -0800",
            "from npg-dpdk-virtio-xiachenbo-nw.sh.intel.com ([10.67.119.123])\n by fmsmga008.fm.intel.com with ESMTP; 17 Dec 2020 23:54:34 -0800"
        ],
        "IronPort-SDR": [
            "\n lXXlTbwyqToM1n/kPU3DEdxCt2BKk4ivlpvOJmFPKHmYX9jPVJWVn/aKJc0nu/Qhf0uVGR8wnt\n S6nKzRDNBhzA==",
            "\n oaRW4y5YdE5Jqwcd4+FZzCYFuzM+kUjLHCxv9ZvQyjlp+n5CX+QsXmnuiyH+4wEFDRwgz7Amrd\n /EiwukquuZ4Q=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9838\"; a=\"260126198\"",
            "E=Sophos;i=\"5.78,429,1599548400\"; d=\"scan'208\";a=\"260126198\"",
            "E=Sophos;i=\"5.78,429,1599548400\"; d=\"scan'208\";a=\"340270453\""
        ],
        "X-ExtLoop1": "1",
        "From": "Chenbo Xia <chenbo.xia@intel.com>",
        "To": "dev@dpdk.org,\n\tthomas@monjalon.net,\n\tdavid.marchand@redhat.com",
        "Cc": "stephen@networkplumber.org, cunming.liang@intel.com, xiuchun.lu@intel.com,\n miao.li@intel.com, jingjing.wu@intel.com",
        "Date": "Fri, 18 Dec 2020 15:38:50 +0800",
        "Message-Id": "<20201218073851.93609-9-chenbo.xia@intel.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20201218073851.93609-1-chenbo.xia@intel.com>",
        "References": "<20201218073851.93609-1-chenbo.xia@intel.com>",
        "Subject": "[dpdk-dev] [PATCH 8/9] test/vfio_user: introduce functional test",
        "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 introduces functional test for vfio_user client and\nserver. Note that the test can only be run with server and client\nboth started and server should be started first.\n\nSigned-off-by: Chenbo Xia <chenbo.xia@intel.com>\nSigned-off-by: Xiuchun Lu <xiuchun.lu@intel.com>\n---\n app/test/meson.build      |   4 +\n app/test/test_vfio_user.c | 646 ++++++++++++++++++++++++++++++++++++++\n 2 files changed, 650 insertions(+)\n create mode 100644 app/test/test_vfio_user.c",
    "diff": "diff --git a/app/test/meson.build b/app/test/meson.build\nindex 94fd39fecb..f5b15ac44c 100644\n--- a/app/test/meson.build\n+++ b/app/test/meson.build\n@@ -138,6 +138,7 @@ test_sources = files('commands.c',\n \t'test_trace.c',\n \t'test_trace_register.c',\n \t'test_trace_perf.c',\n+\t'test_vfio_user.c',\n \t'test_version.c',\n \t'virtual_pmd.c'\n )\n@@ -173,6 +174,7 @@ test_deps = ['acl',\n \t'ring',\n \t'security',\n \t'stack',\n+\t'vfio_user',\n \t'telemetry',\n \t'timer'\n ]\n@@ -266,6 +268,8 @@ fast_tests = [\n         ['service_autotest', true],\n         ['thash_autotest', true],\n         ['trace_autotest', true],\n+        ['vfio_user_autotest_client', false],\n+        ['vfio_user_autotest_server', false],\n ]\n \n perf_test_names = [\ndiff --git a/app/test/test_vfio_user.c b/app/test/test_vfio_user.c\nnew file mode 100644\nindex 0000000000..ee245e437d\n--- /dev/null\n+++ b/app/test/test_vfio_user.c\n@@ -0,0 +1,646 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2020 Intel Corporation\n+ */\n+\n+#include <inttypes.h>\n+#include <limits.h>\n+#include <stdatomic.h>\n+#include <sys/eventfd.h>\n+#include <sys/mman.h>\n+\n+#include <rte_vfio_user.h>\n+#include <rte_malloc.h>\n+#include <rte_hexdump.h>\n+#include <rte_pause.h>\n+#include <rte_log.h>\n+\n+#include \"test.h\"\n+\n+#define REGION_SIZE 0x100\n+\n+struct server_mem_tb {\n+\tuint32_t entry_num;\n+\tstruct rte_vfio_user_mtb_entry entry[];\n+};\n+\n+static const char test_sock[] = \"/tmp/dpdk_vfio_test\";\n+struct server_mem_tb *server_mem;\n+int server_irqfd;\n+atomic_uint test_failed;\n+atomic_uint server_destroyed;\n+\n+static int test_set_dev_info(const char *sock,\n+\tstruct vfio_device_info *info)\n+{\n+\tint ret;\n+\n+\tinfo->argsz = sizeof(*info);\n+\tinfo->flags = VFIO_DEVICE_FLAGS_RESET | VFIO_DEVICE_FLAGS_PCI;\n+\tinfo->num_irqs = VFIO_PCI_NUM_IRQS;\n+\tinfo->num_regions = VFIO_PCI_NUM_REGIONS;\n+\tret = rte_vfio_user_set_dev_info(sock, info);\n+\tif (ret) {\n+\t\tprintf(\"Failed to set device info\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static ssize_t test_dev_cfg_rw(struct rte_vfio_user_reg_info *reg, char *buf,\n+\tsize_t count, loff_t pos, bool iswrite)\n+{\n+\tchar *loc = (char *)reg->base + pos;\n+\n+\tif (!iswrite) {\n+\t\tif (pos + count > reg->info->size)\n+\t\t\treturn -1;\n+\t\tmemcpy(buf, loc, count);\n+\t\treturn count;\n+\t}\n+\n+\tmemcpy(loc, buf, count);\n+\treturn count;\n+}\n+\n+static int test_set_reg_info(const char *sock_addr,\n+\tstruct rte_vfio_user_regions *reg)\n+{\n+\tstruct rte_vfio_user_reg_info *reg_info;\n+\tvoid *cfg_base = NULL;\n+\tuint32_t i, j, sz = 0, reg_sz = REGION_SIZE;\n+\tint ret;\n+\n+\treg->reg_num = VFIO_PCI_NUM_REGIONS;\n+\tsz = sizeof(struct vfio_region_info);\n+\n+\tfor (i = 0; i < reg->reg_num; i++) {\n+\t\treg_info = &reg->reg_info[i];\n+\n+\t\treg_info->info = rte_zmalloc(NULL, sz, 0);\n+\t\tif (!reg_info->info) {\n+\t\t\tprintf(\"Failed to alloc vfio region info\\n\");\n+\t\t\tgoto err;\n+\t\t}\n+\n+\t\treg_info->priv = NULL;\n+\t\treg_info->fd = -1;\n+\t\treg_info->info->argsz = sz;\n+\t\treg_info->info->cap_offset = sz;\n+\t\treg_info->info->index = i;\n+\t\treg_info->info->offset = 0;\n+\t\treg_info->info->flags = VFIO_REGION_INFO_FLAG_READ |\n+\t\t\tVFIO_REGION_INFO_FLAG_WRITE;\n+\n+\t\tif (i == VFIO_PCI_CONFIG_REGION_INDEX) {\n+\t\t\tcfg_base = rte_zmalloc(NULL, reg_sz, 0);\n+\t\t\tif (!cfg_base) {\n+\t\t\t\tprintf(\"Failed to alloc cfg space\\n\");\n+\t\t\t\tgoto err;\n+\t\t\t}\n+\t\t\treg_info->base = cfg_base;\n+\t\t\treg_info->rw = test_dev_cfg_rw;\n+\t\t\treg_info->info->size = reg_sz;\n+\t\t} else {\n+\t\t\treg_info->base = NULL;\n+\t\t\treg_info->rw = NULL;\n+\t\t\treg_info->info->size = 0;\n+\t\t}\n+\t}\n+\n+\tret = rte_vfio_user_set_reg_info(sock_addr, reg);\n+\tif (ret) {\n+\t\tprintf(\"Failed to set region info\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+err:\n+\tfor (j = 0; j < i; j++)\n+\t\trte_free(reg->reg_info[i].info);\n+\trte_free(cfg_base);\n+\treturn -1;\n+}\n+\n+static void cleanup_reg(struct rte_vfio_user_regions *reg)\n+{\n+\tstruct rte_vfio_user_reg_info *reg_info;\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < reg->reg_num; i++) {\n+\t\treg_info = &reg->reg_info[i];\n+\n+\t\trte_free(reg_info->info);\n+\n+\t\tif (i == VFIO_PCI_CONFIG_REGION_INDEX)\n+\t\t\trte_free(reg_info->base);\n+\t}\n+}\n+\n+static int test_set_irq_info(const char *sock,\n+\tstruct rte_vfio_user_irq_info *info)\n+{\n+\tstruct vfio_irq_info *irq_info;\n+\tint ret;\n+\tuint32_t i;\n+\n+\tinfo->irq_num = VFIO_PCI_NUM_IRQS;\n+\tfor (i = 0; i < info->irq_num; i++) {\n+\t\tirq_info = &info->irq_info[i];\n+\t\tirq_info->argsz = sizeof(irq_info);\n+\t\tirq_info->index = i;\n+\n+\t\tif (i == VFIO_PCI_MSIX_IRQ_INDEX) {\n+\t\t\tirq_info->flags = VFIO_IRQ_INFO_EVENTFD |\n+\t\t\t\tVFIO_IRQ_INFO_NORESIZE;\n+\t\t\tirq_info->count = 1;\n+\t\t} else {\n+\t\t\tirq_info->flags = 0;\n+\t\t\tirq_info->count = 0;\n+\t\t}\n+\t}\n+\n+\tret = rte_vfio_user_set_irq_info(sock, info);\n+\tif (ret) {\n+\t\tprintf(\"Failed to set irq info\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int test_get_mem(int dev_id)\n+{\n+\tconst struct rte_vfio_user_mem *mem;\n+\tuint32_t entry_sz;\n+\n+\tmem = rte_vfio_user_get_mem_table(dev_id);\n+\tif (!mem) {\n+\t\tprintf(\"Failed to get memory table\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tentry_sz = sizeof(struct rte_vfio_user_mtb_entry) * mem->entry_num;\n+\tserver_mem = rte_zmalloc(NULL, sizeof(*server_mem) + entry_sz, 0);\n+\n+\tmemcpy(server_mem->entry, mem->entry, entry_sz);\n+\tserver_mem->entry_num = mem->entry_num;\n+\n+\treturn 0;\n+}\n+\n+static int test_get_irq(int dev_id)\n+{\n+\tint ret;\n+\n+\tserver_irqfd = -1;\n+\tret = rte_vfio_user_get_irq(dev_id, VFIO_PCI_MSIX_IRQ_INDEX, 1,\n+\t\t&server_irqfd);\n+\tif (ret) {\n+\t\tprintf(\"Failed to get IRQ\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int test_create_device(int dev_id)\n+{\n+\tchar sock[PATH_MAX];\n+\n+\tRTE_LOG(DEBUG, USER1, \"Device created\\n\");\n+\n+\tif (rte_vfio_get_sock_addr(dev_id, sock, sizeof(sock))) {\n+\t\tprintf(\"Failed to get socket addr\\n\");\n+\t\tgoto err;\n+\t}\n+\n+\tif (strcmp(sock, test_sock)) {\n+\t\tprintf(\"Wrong socket addr\\n\");\n+\t\tgoto err;\n+\t}\n+\n+\tprintf(\"Get socket address: TEST OK\\n\");\n+\n+\treturn 0;\n+err:\n+\tatomic_store(&test_failed, 1);\n+\treturn -1;\n+}\n+\n+static void test_destroy_device(int dev_id __rte_unused)\n+{\n+\tint ret;\n+\n+\tRTE_LOG(DEBUG, USER1, \"Device destroyed\\n\");\n+\n+\tret = test_get_mem(dev_id);\n+\tif (ret)\n+\t\tgoto err;\n+\n+\tprintf(\"Get memory table: TEST OK\\n\");\n+\n+\tret = test_get_irq(dev_id);\n+\tif (ret)\n+\t\tgoto err;\n+\n+\tprintf(\"Get IRQ: TEST OK\\n\");\n+\n+\tatomic_store(&server_destroyed, 1);\n+\treturn;\n+err:\n+\tatomic_store(&test_failed, 1);\n+}\n+\n+static int test_update_device(int dev_id __rte_unused)\n+{\n+\tRTE_LOG(DEBUG, USER1, \"Device updated\\n\");\n+\n+\treturn 0;\n+}\n+\n+static int test_lock_dp(int dev_id __rte_unused, int lock)\n+{\n+\tRTE_LOG(DEBUG, USER1, \"Device data path %slocked\\n\", lock ? \"\" : \"un\");\n+\treturn 0;\n+}\n+\n+static int test_reset_device(int dev_id __rte_unused)\n+{\n+\tRTE_LOG(DEBUG, USER1, \"Device reset\\n\");\n+\treturn 0;\n+}\n+\n+const struct rte_vfio_user_notify_ops test_vfio_ops = {\n+\t.new_device = test_create_device,\n+\t.destroy_device = test_destroy_device,\n+\t.update_status = test_update_device,\n+\t.lock_dp = test_lock_dp,\n+\t.reset_device = test_reset_device,\n+};\n+\n+static int\n+test_vfio_user_server(void)\n+{\n+\tstruct vfio_device_info dev_info;\n+\tstruct rte_vfio_user_regions *reg;\n+\tstruct rte_vfio_user_reg_info *reg_info;\n+\tstruct vfio_region_info *info;\n+\tstruct rte_vfio_user_irq_info *irq_info;\n+\tstruct rte_vfio_user_mtb_entry *ent;\n+\tint ret, err;\n+\tuint32_t i;\n+\n+\tatomic_init(&test_failed, 0);\n+\tatomic_init(&server_destroyed, 0);\n+\n+\tret = rte_vfio_user_register(test_sock, &test_vfio_ops);\n+\tif (ret) {\n+\t\tprintf(\"Failed to register\\n\");\n+\t\tret = TEST_FAILED;\n+\t\tgoto err_regis;\n+\t}\n+\n+\tprintf(\"Register device: TEST OK\\n\");\n+\n+\treg = rte_zmalloc(NULL, sizeof(*reg) + VFIO_PCI_NUM_REGIONS *\n+\t\tsizeof(struct rte_vfio_user_reg_info), 0);\n+\tif (!reg) {\n+\t\tprintf(\"Failed to alloc regions\\n\");\n+\t\tret = TEST_FAILED;\n+\t\tgoto err_reg;\n+\t}\n+\n+\tirq_info = rte_zmalloc(NULL, sizeof(*irq_info) + VFIO_PCI_NUM_IRQS *\n+\t\tsizeof(struct vfio_irq_info), 0);\n+\tif (!irq_info) {\n+\t\tprintf(\"Failed to alloc irq info\\n\");\n+\t\tret = TEST_FAILED;\n+\t\tgoto err_irq;\n+\t}\n+\n+\tif (test_set_dev_info(test_sock, &dev_info)) {\n+\t\tret = TEST_FAILED;\n+\t\tgoto err_set;\n+\t}\n+\n+\tprintf(\"Set device info: TEST OK\\n\");\n+\n+\tif (test_set_reg_info(test_sock, reg)) {\n+\t\tret = TEST_FAILED;\n+\t\tgoto err_set;\n+\t}\n+\n+\tprintf(\"Set device info: TEST OK\\n\");\n+\n+\tif (test_set_irq_info(test_sock, irq_info)) {\n+\t\tret = TEST_FAILED;\n+\t\tgoto err;\n+\t}\n+\n+\tprintf(\"Set irq info: TEST OK\\n\");\n+\n+\tret = rte_vfio_user_start(test_sock);\n+\tif (ret) {\n+\t\tprintf(\"Failed to start\\n\");\n+\t\tret = TEST_FAILED;\n+\t\tgoto err;\n+\t}\n+\n+\tprintf(\"Start device: TEST OK\\n\");\n+\n+\twhile (atomic_load(&test_failed) == 0 &&\n+\t\tatomic_load(&server_destroyed) == 0)\n+\t\trte_pause();\n+\n+\tif (atomic_load(&test_failed) == 1) {\n+\t\tprintf(\"Test failed during device running\\n\");\n+\t\tret = TEST_FAILED;\n+\t\tgoto err;\n+\t}\n+\n+\tprintf(\"=================================\\n\");\n+\tprintf(\"Device layout:\\n\");\n+\tprintf(\"=================================\\n\");\n+\tprintf(\"%u regions, %u IRQs\\n\", dev_info.num_regions,\n+\t\tdev_info.num_irqs);\n+\tprintf(\"=================================\\n\");\n+\n+\treg_info = &reg->reg_info[VFIO_PCI_CONFIG_REGION_INDEX];\n+\tinfo = reg_info->info;\n+\tprintf(\"Configuration Space:\\nsize : 0x%llx, prot: %s%s\\n\",\n+\t\tinfo->size,\n+\t\t(info->flags & VFIO_REGION_INFO_FLAG_READ) ? \"read/\" : \"\",\n+\t\t(info->flags & VFIO_REGION_INFO_FLAG_WRITE) ? \"write\" : \"\");\n+\trte_hexdump(stdout, \"Content\", (const void *)reg_info->base,\n+\t\tinfo->size);\n+\n+\tprintf(\"=================================\\n\");\n+\tprintf(\"DMA memory table (Entry num: %u):\\n\", server_mem->entry_num);\n+\n+\tfor (i = 0; i < server_mem->entry_num; i++) {\n+\t\tent = &server_mem->entry[i];\n+\t\tprintf(\"(Entry %u) gpa: 0x%\" PRIx64\n+\t\t\t\", size: 0x%\" PRIx64 \", hva: 0x%\" PRIx64 \"\\n\"\n+\t\t\t\", mmap_addr: 0x%\" PRIx64 \", mmap_size: 0x%\" PRIx64\n+\t\t\t\", fd: %d\\n\", i, ent->gpa, ent->size,\n+\t\t\tent->host_user_addr, (uint64_t)ent->mmap_addr,\n+\t\t\tent->mmap_size, ent->fd);\n+\t}\n+\n+\tprintf(\"=================================\\n\");\n+\tprintf(\"MSI-X Interrupt:\\nNumber: %u, irqfd: %s\\n\",\n+\t\tirq_info->irq_info[VFIO_PCI_MSIX_IRQ_INDEX].count,\n+\t\tserver_irqfd == -1 ? \"Invalid\" : \"Valid\");\n+\n+\tret = TEST_SUCCESS;\n+\n+err:\n+\tcleanup_reg(reg);\n+err_set:\n+\trte_free(irq_info);\n+err_irq:\n+\trte_free(reg);\n+err_reg:\n+\terr = rte_vfio_user_unregister(test_sock);\n+\tif (err)\n+\t\tret = TEST_FAILED;\n+\telse\n+\t\tprintf(\"Unregister device: TEST OK\\n\");\n+err_regis:\n+\treturn ret;\n+}\n+\n+static int test_get_dev_info(int dev_id, struct vfio_device_info *info)\n+{\n+\tint ret;\n+\n+\tret = rte_vfio_user_get_dev_info(dev_id, info);\n+\tif (ret) {\n+\t\tprintf(\"Failed to get device info\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int test_get_reg_info(int dev_id, struct vfio_region_info *info)\n+{\n+\tint ret, fd = -1;\n+\n+\tinfo->index = VFIO_PCI_CONFIG_REGION_INDEX;\n+\tinfo->argsz = sizeof(*info);\n+\tret = rte_vfio_user_get_reg_info(dev_id, info, &fd);\n+\tif (ret) {\n+\t\tprintf(\"Failed to get region info\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int test_get_irq_info(int dev_id, struct vfio_irq_info *info)\n+{\n+\tint ret;\n+\n+\tinfo->index = VFIO_PCI_MSIX_IRQ_INDEX;\n+\tret = rte_vfio_user_get_irq_info(dev_id, info);\n+\tif (ret) {\n+\t\tprintf(\"Failed to get irq info\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int test_set_irqs(int dev_id, struct vfio_irq_set *set, int *fd)\n+{\n+\tint ret;\n+\n+\t*fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);\n+\tif (*fd < 0) {\n+\t\tprintf(\"Failed to create eventfd\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tset->argsz = sizeof(*set) + sizeof(int);\n+\tset->count = 1;\n+\tset->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER;\n+\tset->index = VFIO_PCI_MSIX_IRQ_INDEX;\n+\tset->start = 0;\n+\tmemcpy(set->data, fd, sizeof(*fd));\n+\n+\tret = rte_vfio_user_set_irqs(dev_id, set);\n+\tif (ret) {\n+\t\tprintf(\"Failed to set irqs\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int test_dma_map_unmap(int dev_id, struct rte_vfio_user_mem_reg *mem)\n+{\n+\tint ret, fd = -1;\n+\n+\tmem->fd_offset = 0;\n+\tmem->flags = 0;\n+\tmem->gpa = 0x12345678;\n+\tmem->protection = PROT_READ | PROT_WRITE;\n+\tmem->size = 0x10000;\n+\n+\t/* Map -> Unmap -> Map */\n+\tret = rte_vfio_user_dma_map(dev_id, mem, &fd, 1);\n+\tif (ret) {\n+\t\tprintf(\"Failed to dma map\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tret = rte_vfio_user_dma_unmap(dev_id, mem, 1);\n+\tif (ret) {\n+\t\tprintf(\"Failed to dma unmap\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tret = rte_vfio_user_dma_map(dev_id, mem, &fd, 1);\n+\tif (ret) {\n+\t\tprintf(\"Failed to dma re-map\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int test_region_read_write(int dev_id, void *read_data, uint64_t sz)\n+{\n+\tint ret;\n+\tuint32_t data = 0x1A2B3C4D, idx = VFIO_PCI_CONFIG_REGION_INDEX;\n+\n+\tret = rte_vfio_user_region_write(dev_id, idx, 0, 4, (void *)&data);\n+\tif (ret) {\n+\t\tprintf(\"Failed to write region\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tret = rte_vfio_user_region_read(dev_id, idx, 0, sz, read_data);\n+\tif (ret) {\n+\t\tprintf(\"Failed to read region\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+static int\n+test_vfio_user_client(void)\n+{\n+\tint ret = 0, dev_id, fd = -1;\n+\tstruct vfio_device_info dev_info;\n+\tstruct vfio_irq_info irq_info;\n+\tstruct rte_vfio_user_mem_reg mem;\n+\tstruct vfio_irq_set *set;\n+\tstruct vfio_region_info reg_info;\n+\tvoid *data;\n+\n+\tret = rte_vfio_user_attach_dev(test_sock);\n+\tif (ret) {\n+\t\tprintf(\"Failed to attach device\\n\");\n+\t\treturn TEST_FAILED;\n+\t}\n+\n+\tprintf(\"Attach device: TEST OK\\n\");\n+\n+\tdev_id = ret;\n+\tret = rte_vfio_user_reset(dev_id);\n+\tif (ret) {\n+\t\tprintf(\"Failed to reset device\\n\");\n+\t\treturn TEST_FAILED;\n+\t}\n+\n+\tprintf(\"Reset device: TEST OK\\n\");\n+\n+\tif (test_get_dev_info(dev_id, &dev_info))\n+\t\treturn TEST_FAILED;\n+\n+\tprintf(\"Get device info: TEST OK\\n\");\n+\n+\tif (test_get_reg_info(dev_id, &reg_info))\n+\t\treturn TEST_FAILED;\n+\n+\tprintf(\"Get region info: TEST OK\\n\");\n+\n+\tif (test_get_irq_info(dev_id, &irq_info))\n+\t\treturn TEST_FAILED;\n+\n+\tprintf(\"Get irq info: TEST OK\\n\");\n+\n+\tset = rte_zmalloc(NULL, sizeof(*set) + sizeof(int), 0);\n+\tif (!set) {\n+\t\tprintf(\"Failed to allocate irq set\\n\");\n+\t\treturn TEST_FAILED;\n+\t}\n+\n+\tdata = rte_zmalloc(NULL, reg_info.size, 0);\n+\tif (!data) {\n+\t\tprintf(\"Failed to allcate data\\n\");\n+\t\tret = TEST_FAILED;\n+\t\tgoto err_data;\n+\t}\n+\n+\tif (test_set_irqs(dev_id, set, &fd)) {\n+\t\tret = TEST_FAILED;\n+\t\tgoto err;\n+\t}\n+\n+\tprintf(\"Set irqs: TEST OK\\n\");\n+\n+\tif (test_dma_map_unmap(dev_id, &mem)) {\n+\t\tret = TEST_FAILED;\n+\t\tgoto err;\n+\t}\n+\n+\tprintf(\"DMA map/unmap: TEST OK\\n\");\n+\n+\tif (test_region_read_write(dev_id, data, reg_info.size)) {\n+\t\tret = TEST_FAILED;\n+\t\tgoto err;\n+\t}\n+\n+\tprintf(\"Region read/write: TEST OK\\n\");\n+\n+\tprintf(\"=================================\\n\");\n+\tprintf(\"Device layout:\\n\");\n+\tprintf(\"=================================\\n\");\n+\tprintf(\"%u regions, %u IRQs\\n\", dev_info.num_regions,\n+\t\tdev_info.num_irqs);\n+\tprintf(\"=================================\\n\");\n+\tprintf(\"Configuration Space:\\nsize : 0x%llx, prot: %s%s\\n\",\n+\t\treg_info.size,\n+\t\t(reg_info.flags & VFIO_REGION_INFO_FLAG_READ) ? \"read/\" : \"\",\n+\t\t(reg_info.flags & VFIO_REGION_INFO_FLAG_WRITE) ? \"write\" : \"\");\n+\trte_hexdump(stdout, \"Content\", (const void *)data, reg_info.size);\n+\n+\tprintf(\"=================================\\n\");\n+\tprintf(\"DMA memory table (Entry num: 1):\\ngpa: 0x%\" PRIx64\n+\t\t\", size: 0x%\" PRIx64 \", fd: -1, fd_offset:0x%\" PRIx64 \"\\n\",\n+\t\tmem.gpa, mem.size, mem.fd_offset);\n+\tprintf(\"=================================\\n\");\n+\tprintf(\"MSI-X Interrupt:\\nNumber: %u, irqfd: %s\\n\", irq_info.count,\n+\t\tfd == -1 ? \"Invalid\" : \"Valid\");\n+\n+\tret = rte_vfio_user_detach_dev(dev_id);\n+\tif (ret) {\n+\t\tprintf(\"Failed to detach device\\n\");\n+\t\tret = TEST_FAILED;\n+\t\tgoto err;\n+\t}\n+\n+\tprintf(\"Device detach: TEST OK\\n\");\n+err:\n+\trte_free(data);\n+err_data:\n+\trte_free(set);\n+\treturn ret;\n+}\n+\n+REGISTER_TEST_COMMAND(vfio_user_autotest_client, test_vfio_user_client);\n+REGISTER_TEST_COMMAND(vfio_user_autotest_server, test_vfio_user_server);\n",
    "prefixes": [
        "8/9"
    ]
}