get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 54727,
    "url": "https://patches.dpdk.org/api/patches/54727/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20190612063313.2729-1-tyos@jp.ibm.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": "<20190612063313.2729-1-tyos@jp.ibm.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20190612063313.2729-1-tyos@jp.ibm.com",
    "date": "2019-06-12T06:33:12",
    "name": "vfio: fix expanding DMA area in ppc64le",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "0bfcbed67ad89f0a71947939bbbff9f5acf24499",
    "submitter": {
        "id": 1099,
        "url": "https://patches.dpdk.org/api/people/1099/?format=api",
        "name": "Takeshi Yoshimura",
        "email": "tyos@jp.ibm.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/20190612063313.2729-1-tyos@jp.ibm.com/mbox/",
    "series": [
        {
            "id": 4985,
            "url": "https://patches.dpdk.org/api/series/4985/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=4985",
            "date": "2019-06-12T06:33:12",
            "name": "vfio: fix expanding DMA area in ppc64le",
            "version": 1,
            "mbox": "https://patches.dpdk.org/series/4985/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/54727/comments/",
    "check": "fail",
    "checks": "https://patches.dpdk.org/api/patches/54727/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 08F671D13E;\n\tWed, 12 Jun 2019 08:33:23 +0200 (CEST)",
            "from nh602-vm9.bullet.mail.ssk.yahoo.co.jp\n\t(nh602-vm9.bullet.mail.ssk.yahoo.co.jp [182.22.90.34])\n\tby dpdk.org (Postfix) with SMTP id 7768C1D139\n\tfor <dev@dpdk.org>; Wed, 12 Jun 2019 08:33:19 +0200 (CEST)",
            "from [182.22.66.106] by nh602.bullet.mail.ssk.yahoo.co.jp with\n\tNNFMP; 12 Jun 2019 06:33:18 -0000",
            "from [182.22.91.129] by t604.bullet.mail.ssk.yahoo.co.jp with\n\tNNFMP; 12 Jun 2019 06:33:17 -0000",
            "from [127.0.0.1] by omp602.mail.ssk.yahoo.co.jp with NNFMP;\n\t12 Jun 2019 06:33:17 -0000",
            "(qmail 32400 invoked by alias); 12 Jun 2019 06:33:17 -0000",
            "from unknown (HELO TakeshinoMacBook-puro.local.ibmmobiledemo.com)\n\t(203.141.91.43 with login)\n\tby ymobsmtp6007.mail.ssk.ynwp.yahoo.co.jp with SMTP;\n\t12 Jun 2019 06:33:17 -0000"
        ],
        "X-Yahoo-Newman-Property": "ymail-3",
        "X-Yahoo-Newman-Id": "943575.44599.bm@omp602.mail.ssk.yahoo.co.jp",
        "X-YMail-JAS": "7w9BJnUVM1mMEGAtAQPwcNPV8ltAizya7XWqjJfRIVgmHNpjW7yp5h0RwrBjsOXwK3WQwLKnDrkysotsZ1Y_9Wm8NdV73_3wPXmlZ7a3xOFtqC_xnS3.rMdCC1sm1BqTyQrkxa8ez8qHEjo-",
        "X-Apparently-From": "<endliner2000@yahoo.co.jp>",
        "X-YMail-OSG": "8woC.tEVM1mKbapj9biulwiu19ik.s4J7uTnuiJESsrrBOj\n\thVxOFsMLyRyi229XDd3CkeATQTQG0WOSFCcRCq0qu1yRJmxCpzIrvgquXyR7\n\tD.05BHTuEkzNjfq7sM2NmXNSHDseGkjsd8cB514c2mw.b1.nINpvjaGV1jfG\n\tAEuFLMwk9MDduKZKFKmjz2BrOqW1mxnWEodFEv_VQ07kxrbX9G5RnSirtB2w\n\tZv_gUOUkVNTxdZGGT9zKqExNG4LCZZeqzSWdcJx.FIeUf3qpe5Hy1ap3kGnV\n\tGspQOEOGF.jOs7bIZcKLPk6wad2DVUJK3NpaP.ATRhPGjVHHVZ56T211aPTv\n\tSXH2fnC0P.oS_7lUS4eBd3fg6oI39SbQMZlY8McY497SCQdTDutYNZnDqJqp\n\tZUK.eSyJhEXr_FsoAgVV8PIyevy3eCPkseNVI4tr69MTlDNMwSgHQGktSQFB\n\tsfVFyFdtMZDkTNJnhzJVgAkRyd2qecsOoZqSwWByWnoaWHZMCihed3XuuyIp\n\tUttwpk_5gkjv_qm67l__mZavSHFlZHcAVfdlH6TtzNABA5w0w6uMb13Y1O9n\n\t52vPJieuRgHT4KOaIqvlWXWNCoMo-",
        "From": "Takeshi Yoshimura <tyos@jp.ibm.com>",
        "To": "dev@dpdk.org",
        "Cc": "Takeshi Yoshimura <tyos@jp.ibm.com>",
        "Date": "Wed, 12 Jun 2019 15:33:12 +0900",
        "Message-Id": "<20190612063313.2729-1-tyos@jp.ibm.com>",
        "X-Mailer": "git-send-email 2.17.2 (Apple Git-113)",
        "Subject": "[dpdk-dev] [PATCH] vfio: fix expanding DMA area in ppc64le",
        "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 ppc64le, expanding DMA areas always fail because we cannot remove\na DMA window. As a result, we cannot allocate more than one memseg in\nppc64le. This is because vfio_spapr_dma_mem_map() doesn't unmap all\nthe mapped DMA before removing the window. This patch fixes this\nincorrect behavior.\n\nI added a global variable to track current window size since we do\nnot have better ways to get exact size of it than doing so. sPAPR\nIOMMU seems not to provide any ways to get window size with ioctl\ninterfaces. rte_memseg_walk*() is currently used to calculate window\nsize, but it walks memsegs that are marked as used, not mapped. So,\nwe need to determine if a given memseg is mapped or not, otherwise\nthe ioctl reports errors due to attempting to unregister memory\naddresses that are not registered. The global variable is excluded\nin non-ppc64le binaries.\n\nSimilar problems happen in user maps. We need to avoid attempting to\nunmap the address that is given as the function's parameter. The\ncompaction of user maps prevents us from passing correct length for\nunmapping DMA at the window recreation. So, I removed it in ppc64le.\n\nI also fixed the order of ioctl for unregister and unmap. The ioctl\nfor unregister sometimes report device busy errors due to the\nexistence of mapped area.\n\nSigned-off-by: Takeshi Yoshimura <tyos@jp.ibm.com>\n---\n lib/librte_eal/linux/eal/eal_vfio.c | 154 +++++++++++++++++++---------\n 1 file changed, 103 insertions(+), 51 deletions(-)",
    "diff": "diff --git a/lib/librte_eal/linux/eal/eal_vfio.c b/lib/librte_eal/linux/eal/eal_vfio.c\nindex f16c5c3c0..6edbaaff5 100644\n--- a/lib/librte_eal/linux/eal/eal_vfio.c\n+++ b/lib/librte_eal/linux/eal/eal_vfio.c\n@@ -93,6 +93,7 @@ is_null_map(const struct user_mem_map *map)\n \treturn map->addr == 0 && map->iova == 0 && map->len == 0;\n }\n \n+#ifndef RTE_ARCH_PPC_64\n /* we may need to merge user mem maps together in case of user mapping/unmapping\n  * chunks of memory, so we'll need a comparator function to sort segments.\n  */\n@@ -126,6 +127,7 @@ user_mem_map_cmp(const void *a, const void *b)\n \n \treturn 0;\n }\n+#endif\n \n /* adjust user map entry. this may result in shortening of existing map, or in\n  * splitting existing map in two pieces.\n@@ -162,6 +164,7 @@ adjust_map(struct user_mem_map *src, struct user_mem_map *end,\n \t}\n }\n \n+#ifndef RTE_ARCH_PPC_64\n /* try merging two maps into one, return 1 if succeeded */\n static int\n merge_map(struct user_mem_map *left, struct user_mem_map *right)\n@@ -177,6 +180,7 @@ merge_map(struct user_mem_map *left, struct user_mem_map *right)\n \n \treturn 1;\n }\n+#endif\n \n static struct user_mem_map *\n find_user_mem_map(struct user_mem_maps *user_mem_maps, uint64_t addr,\n@@ -211,6 +215,16 @@ find_user_mem_map(struct user_mem_maps *user_mem_maps, uint64_t addr,\n \treturn NULL;\n }\n \n+#ifdef RTE_ARCH_PPC_64\n+/* Recreation of DMA window requires unregistering DMA memory.\n+ * Compaction confuses the logic and causes false reports in the recreation.\n+ * For now, we do not compact user maps in ppc64le.\n+ */\n+static void\n+compact_user_maps(__rte_unused struct user_mem_maps *user_mem_maps)\n+{\n+}\n+#else\n /* this will sort all user maps, and merge/compact any adjacent maps */\n static void\n compact_user_maps(struct user_mem_maps *user_mem_maps)\n@@ -256,6 +270,7 @@ compact_user_maps(struct user_mem_maps *user_mem_maps)\n \t\tuser_mem_maps->n_maps = cur_idx;\n \t}\n }\n+#endif\n \n static int\n vfio_open_group_fd(int iommu_group_num)\n@@ -1357,14 +1372,6 @@ vfio_spapr_dma_do_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova,\n \t\t}\n \n \t} else {\n-\t\tret = ioctl(vfio_container_fd,\n-\t\t\t\tVFIO_IOMMU_SPAPR_UNREGISTER_MEMORY, &reg);\n-\t\tif (ret) {\n-\t\t\tRTE_LOG(ERR, EAL, \"  cannot unregister vaddr for IOMMU, error %i (%s)\\n\",\n-\t\t\t\t\terrno, strerror(errno));\n-\t\t\treturn -1;\n-\t\t}\n-\n \t\tmemset(&dma_unmap, 0, sizeof(dma_unmap));\n \t\tdma_unmap.argsz = sizeof(struct vfio_iommu_type1_dma_unmap);\n \t\tdma_unmap.size = len;\n@@ -1377,24 +1384,50 @@ vfio_spapr_dma_do_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova,\n \t\t\t\t\terrno, strerror(errno));\n \t\t\treturn -1;\n \t\t}\n+\n+\t\tret = ioctl(vfio_container_fd,\n+\t\t\t\tVFIO_IOMMU_SPAPR_UNREGISTER_MEMORY, &reg);\n+\t\tif (ret) {\n+\t\t\tRTE_LOG(ERR, EAL, \"  cannot unregister vaddr for IOMMU, error %i (%s)\\n\",\n+\t\t\t\t\terrno, strerror(errno));\n+\t\t\treturn -1;\n+\t\t}\n \t}\n \n \treturn 0;\n }\n \n+struct spapr_remap_walk_param {\n+\tint vfio_container_fd;\n+\tuint64_t window_size;\n+};\n+\n static int\n vfio_spapr_map_walk(const struct rte_memseg_list *msl,\n \t\tconst struct rte_memseg *ms, void *arg)\n {\n-\tint *vfio_container_fd = arg;\n+\tstruct spapr_remap_walk_param *p = arg;\n \n-\tif (msl->external)\n+\tif (msl->external || ms->iova >= p->window_size)\n \t\treturn 0;\n \n-\treturn vfio_spapr_dma_do_map(*vfio_container_fd, ms->addr_64, ms->iova,\n+\treturn vfio_spapr_dma_do_map(p->vfio_container_fd, ms->addr_64, ms->iova,\n \t\t\tms->len, 1);\n }\n \n+static int\n+vfio_spapr_unmap_walk(const struct rte_memseg_list *msl,\n+\t\tconst struct rte_memseg *ms, void *arg)\n+{\n+\tstruct spapr_remap_walk_param *p = arg;\n+\n+\tif (msl->external || ms->iova >= p->window_size)\n+\t\treturn 0;\n+\n+\treturn vfio_spapr_dma_do_map(p->vfio_container_fd, ms->addr_64, ms->iova,\n+\t\t\tms->len, 0);\n+}\n+\n struct spapr_walk_param {\n \tuint64_t window_size;\n \tuint64_t hugepage_sz;\n@@ -1481,14 +1514,14 @@ vfio_spapr_create_new_dma_window(int vfio_container_fd,\n \treturn 0;\n }\n \n+#ifdef RTE_ARCH_PPC_64\n+static struct vfio_iommu_spapr_tce_create prev_create;\n+\n static int\n vfio_spapr_dma_mem_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova,\n \t\tuint64_t len, int do_map)\n {\n-\tstruct spapr_walk_param param;\n-\tstruct vfio_iommu_spapr_tce_create create = {\n-\t\t.argsz = sizeof(create),\n-\t};\n+\tstruct vfio_iommu_spapr_tce_create create;\n \tstruct vfio_config *vfio_cfg;\n \tstruct user_mem_maps *user_mem_maps;\n \tint i, ret = 0;\n@@ -1502,43 +1535,59 @@ vfio_spapr_dma_mem_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova,\n \tuser_mem_maps = &vfio_cfg->mem_maps;\n \trte_spinlock_recursive_lock(&user_mem_maps->lock);\n \n-\t/* check if window size needs to be adjusted */\n-\tmemset(&param, 0, sizeof(param));\n-\n-\t/* we're inside a callback so use thread-unsafe version */\n-\tif (rte_memseg_walk_thread_unsafe(vfio_spapr_window_size_walk,\n-\t\t\t\t&param) < 0) {\n-\t\tRTE_LOG(ERR, EAL, \"Could not get window size\\n\");\n-\t\tret = -1;\n-\t\tgoto out;\n-\t}\n+\tmemcpy(&create, &prev_create, sizeof(create));\n \n \t/* also check user maps */\n \tfor (i = 0; i < user_mem_maps->n_maps; i++) {\n-\t\tuint64_t max = user_mem_maps->maps[i].iova +\n-\t\t\t\tuser_mem_maps->maps[i].len;\n-\t\tcreate.window_size = RTE_MAX(create.window_size, max);\n+\t\tstruct user_mem_map *map = &user_mem_maps->maps[i];\n+\n+\t\tif (vaddr == map->addr && len == map->len)\n+\t\t\tcontinue;\n+\t\tcreate.window_size = RTE_MAX(create.window_size, map->iova + map->len);\n \t}\n \n \t/* sPAPR requires window size to be a power of 2 */\n-\tcreate.window_size = rte_align64pow2(param.window_size);\n-\tcreate.page_shift = __builtin_ctzll(param.hugepage_sz);\n-\tcreate.levels = 1;\n+\tcreate.window_size = rte_align64pow2(create.window_size);\n \n \tif (do_map) {\n-\t\tvoid *addr;\n \t\t/* re-create window and remap the entire memory */\n-\t\tif (iova > create.window_size) {\n+\t\tif (iova + len > create.window_size) {\n+\t\t\tstruct spapr_remap_walk_param param = {\n+\t\t\t\t.vfio_container_fd = vfio_container_fd,\n+\t\t\t    .window_size = create.window_size,\n+\t\t\t};\n+\n+\t\t\t/* we're inside a callback, so use thread-unsafe version\n+\t\t\t */\n+\t\t\trte_memseg_walk_thread_unsafe(vfio_spapr_unmap_walk,\n+\t\t\t\t\t&param);\n+\t\t\t/* destruct all user maps */\n+\t\t\tfor (i = 0; i < user_mem_maps->n_maps; i++) {\n+\t\t\t\tstruct user_mem_map *map =\n+\t\t\t\t\t\t&user_mem_maps->maps[i];\n+\t\t\t\tif (vaddr == map->addr && len == map->len)\n+\t\t\t\t\tcontinue;\n+\t\t\t\tif (vfio_spapr_dma_do_map(vfio_container_fd,\n+\t\t\t\t\t\tmap->addr, map->iova, map->len,\n+\t\t\t\t\t\t0)) {\n+\t\t\t\t\tRTE_LOG(ERR, EAL, \"Could not destruct user DMA maps\\n\");\n+\t\t\t\t\tret = -1;\n+\t\t\t\t\tgoto out;\n+\t\t\t\t}\n+\t\t\t}\n+\n+\t\t\tcreate.window_size = rte_align64pow2(iova + len);\n \t\t\tif (vfio_spapr_create_new_dma_window(vfio_container_fd,\n \t\t\t\t\t&create) < 0) {\n \t\t\t\tRTE_LOG(ERR, EAL, \"Could not create new DMA window\\n\");\n \t\t\t\tret = -1;\n \t\t\t\tgoto out;\n \t\t\t}\n+\t\t\tmemcpy(&prev_create, &create, sizeof(create));\n \t\t\t/* we're inside a callback, so use thread-unsafe version\n \t\t\t */\n \t\t\tif (rte_memseg_walk_thread_unsafe(vfio_spapr_map_walk,\n-\t\t\t\t\t&vfio_container_fd) < 0) {\n+\t\t\t\t\t&param) < 0) {\n \t\t\t\tRTE_LOG(ERR, EAL, \"Could not recreate DMA maps\\n\");\n \t\t\t\tret = -1;\n \t\t\t\tgoto out;\n@@ -1547,6 +1596,8 @@ vfio_spapr_dma_mem_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova,\n \t\t\tfor (i = 0; i < user_mem_maps->n_maps; i++) {\n \t\t\t\tstruct user_mem_map *map =\n \t\t\t\t\t\t&user_mem_maps->maps[i];\n+\t\t\t\tif (vaddr == map->addr && len == map->len)\n+\t\t\t\t\tcontinue;\n \t\t\t\tif (vfio_spapr_dma_do_map(vfio_container_fd,\n \t\t\t\t\t\tmap->addr, map->iova, map->len,\n \t\t\t\t\t\t1)) {\n@@ -1556,23 +1607,8 @@ vfio_spapr_dma_mem_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova,\n \t\t\t\t}\n \t\t\t}\n \t\t}\n-\n-\t\t/* now that we've remapped all of the memory that was present\n-\t\t * before, map the segment that we were requested to map.\n-\t\t *\n-\t\t * however, if we were called by the callback, the memory we\n-\t\t * were called with was already in the memseg list, so previous\n-\t\t * mapping should've mapped that segment already.\n-\t\t *\n-\t\t * virt2memseg_list is a relatively cheap check, so use that. if\n-\t\t * memory is within any memseg list, it's a memseg, so it's\n-\t\t * already mapped.\n-\t\t */\n-\t\taddr = (void *)(uintptr_t)vaddr;\n-\t\tif (rte_mem_virt2memseg_list(addr) == NULL &&\n-\t\t\t\tvfio_spapr_dma_do_map(vfio_container_fd,\n-\t\t\t\t\tvaddr, iova, len, 1) < 0) {\n-\t\t\tRTE_LOG(ERR, EAL, \"Could not map segment\\n\");\n+\t\tif (vfio_spapr_dma_do_map(vfio_container_fd, vaddr, iova, len, 1)) {\n+\t\t\tRTE_LOG(ERR, EAL, \"Failed to map DMA\\n\");\n \t\t\tret = -1;\n \t\t\tgoto out;\n \t\t}\n@@ -1613,6 +1649,7 @@ vfio_spapr_dma_map(int vfio_container_fd)\n \t\tRTE_LOG(ERR, EAL, \"Could not create new DMA window\\n\");\n \t\treturn -1;\n \t}\n+\tmemcpy(&prev_create, &create, sizeof(create));\n \n \t/* map all DPDK segments for DMA. use 1:1 PA to IOVA mapping */\n \tif (rte_memseg_walk(vfio_spapr_map_walk, &vfio_container_fd) < 0)\n@@ -1620,6 +1657,21 @@ vfio_spapr_dma_map(int vfio_container_fd)\n \n \treturn 0;\n }\n+#else\n+static int\n+vfio_spapr_dma_mem_map(int __rte_unused vfio_container_fd,\n+\t\t\tuint64_t __rte_unused vaddr,\n+\t\t\tuint64_t __rte_unused iova, uint64_t __rte_unused len,\n+\t\t\tint __rte_unused do_map)\n+{\n+\treturn 0;\n+}\n+static int\n+vfio_spapr_dma_map(int __rte_unused vfio_container_fd)\n+{\n+\treturn 0;\n+}\n+#endif\n \n static int\n vfio_noiommu_dma_map(int __rte_unused vfio_container_fd)\n",
    "prefixes": []
}