get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 2484,
    "url": "https://patches.dpdk.org/api/patches/2484/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1421915771-10376-1-git-send-email-dan@kernelim.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": "<1421915771-10376-1-git-send-email-dan@kernelim.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1421915771-10376-1-git-send-email-dan@kernelim.com",
    "date": "2015-01-22T08:36:11",
    "name": "[dpdk-dev] eal/linux: allow to map BARs with MSI-X tables, around them",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "9d669e92a175e32517dcaf5aed9f32fcce98fbd0",
    "submitter": {
        "id": 160,
        "url": "https://patches.dpdk.org/api/people/160/?format=api",
        "name": "Dan Aloni",
        "email": "dan@kernelim.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1421915771-10376-1-git-send-email-dan@kernelim.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/2484/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/2484/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 [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id AF6495A74;\n\tThu, 22 Jan 2015 09:36:40 +0100 (CET)",
            "from mail-wi0-f174.google.com (mail-wi0-f174.google.com\n\t[209.85.212.174]) by dpdk.org (Postfix) with ESMTP id E6EA75A73\n\tfor <dev@dpdk.org>; Thu, 22 Jan 2015 09:36:36 +0100 (CET)",
            "by mail-wi0-f174.google.com with SMTP id n3so19702580wiv.1\n\tfor <dev@dpdk.org>; Thu, 22 Jan 2015 00:36:36 -0800 (PST)",
            "from carbon.home.aloni.org (bzq-187-168-31-120.red.bezeqint.net.\n\t[31.168.187.120]) by mx.google.com with ESMTPSA id\n\tjr4sm2978604wjc.20.2015.01.22.00.36.35\n\t(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tThu, 22 Jan 2015 00:36:36 -0800 (PST)"
        ],
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20130820;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id;\n\tbh=gxVVjTAQ8995I7UKFrYDsdWMc8L02aw2bAr0bCtPpNM=;\n\tb=hara9MzFHUwIEDlaHVH45XjNSZg5RjG/oAu/TQKoeB9dC/Ye3LHwGDmBjLPXNuc7Ch\n\tgiTdWn0ErTZri7SyGowN6NdVd/ODFP+VO9nz3jKCKdbU4N27hbyHSVWpwCdJkpKYTCBB\n\tmSp65hAA+4ldmzsKz1LSyzhAMqJJ8vsqXHN6ufVxwwkFCnJzVdtEWK0vSYm9IG0/S05x\n\tuWI1rb1urSdfxUv3XHixhU+pyx4mqoY/mmjgsR4Z8DOEqBKKqPFu4v9zAkCIb5VrHUM1\n\tDyaSrIM7RVJZtf1oZ0pHiqPJ84OSkY0+YMV6dpnxv8c6JVTZIhUlcVTXf/h83ZPJ6g/B\n\t2wSg==",
        "X-Gm-Message-State": "ALoCoQmHPDAzw3HSke0WXPLK6SfKXs1f41Yopve34DNzZY/xFTbkDLZy/B+NVFL3g02xZ6GXoKJM",
        "X-Received": "by 10.180.74.15 with SMTP id p15mr2788063wiv.29.1421915796690;\n\tThu, 22 Jan 2015 00:36:36 -0800 (PST)",
        "From": "Dan Aloni <dan@kernelim.com>",
        "To": "dev@dpdk.org",
        "Date": "Thu, 22 Jan 2015 10:36:11 +0200",
        "Message-Id": "<1421915771-10376-1-git-send-email-dan@kernelim.com>",
        "X-Mailer": "git-send-email 1.9.3",
        "Subject": "[dpdk-dev] [PATCH] eal/linux: allow to map BARs with MSI-X tables, \n\taround them",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "While VFIO doesn't allow us to map complete BARs with MSI-X tables,\nit does allow us to map around them in PAGE_SIZE granularity. There\nmight be adapters that provide their registers in the same BAR\nbut on a different page. For example, Intel's NVME adapter, though\nnot a network adapter, provides only one MMIO BAR that contains\nthe MSI-X table.\n\nSigned-off-by: Dan Aloni <dan@kernelim.com>\nCC: Anatoly Burakov <anatoly.burakov@intel.com>\n---\n lib/librte_eal/linuxapp/eal/eal_pci.c      |  5 +-\n lib/librte_eal/linuxapp/eal/eal_pci_init.h |  2 +-\n lib/librte_eal/linuxapp/eal/eal_pci_uio.c  |  4 +-\n lib/librte_eal/linuxapp/eal/eal_pci_vfio.c | 99 +++++++++++++++++++++++++++---\n lib/librte_eal/linuxapp/eal/eal_vfio.h     |  8 ++-\n 5 files changed, 101 insertions(+), 17 deletions(-)",
    "diff": "diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c\nindex b5f54101e8aa..4a74a9372a15 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_pci.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c\n@@ -118,13 +118,14 @@ pci_find_max_end_va(void)\n \n /* map a particular resource from a file */\n void *\n-pci_map_resource(void *requested_addr, int fd, off_t offset, size_t size)\n+pci_map_resource(void *requested_addr, int fd, off_t offset, size_t size,\n+\t\t int additional_flags)\n {\n \tvoid *mapaddr;\n \n \t/* Map the PCI memory resource of device */\n \tmapaddr = mmap(requested_addr, size, PROT_READ | PROT_WRITE,\n-\t\t\tMAP_SHARED, fd, offset);\n+\t\t\tMAP_SHARED | additional_flags, fd, offset);\n \tif (mapaddr == MAP_FAILED) {\n \t\tRTE_LOG(ERR, EAL, \"%s(): cannot mmap(%d, %p, 0x%lx, 0x%lx): %s (%p)\\n\",\n \t\t\t__func__, fd, requested_addr,\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_pci_init.h b/lib/librte_eal/linuxapp/eal/eal_pci_init.h\nindex 1070eb88fe0a..0a0853d4c4df 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_pci_init.h\n+++ b/lib/librte_eal/linuxapp/eal/eal_pci_init.h\n@@ -66,7 +66,7 @@ extern void *pci_map_addr;\n void *pci_find_max_end_va(void);\n \n void *pci_map_resource(void *requested_addr, int fd, off_t offset,\n-\t\tsize_t size);\n+\t       size_t size, int additional_flags);\n \n /* map IGB_UIO resource prototype */\n int pci_uio_map_resource(struct rte_pci_device *dev);\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c\nindex e53f06b82430..eaa2e36f643e 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_pci_uio.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_pci_uio.c\n@@ -139,7 +139,7 @@ pci_uio_map_secondary(struct rte_pci_device *dev)\n \n \t\t\tif (pci_map_resource(uio_res->maps[i].addr, fd,\n \t\t\t\t\t     (off_t)uio_res->maps[i].offset,\n-\t\t\t\t\t     (size_t)uio_res->maps[i].size)\n+\t\t\t\t\t     (size_t)uio_res->maps[i].size, 0)\n \t\t\t    != uio_res->maps[i].addr) {\n \t\t\t\tRTE_LOG(ERR, EAL,\n \t\t\t\t\t\"Cannot mmap device resource\\n\");\n@@ -379,7 +379,7 @@ pci_uio_map_resource(struct rte_pci_device *dev)\n \t\t\t\t\tpci_map_addr = pci_find_max_end_va();\n \n \t\t\t\tmapaddr = pci_map_resource(pci_map_addr, fd, (off_t)offset,\n-\t\t\t\t\t\t(size_t)maps[j].size);\n+\t\t\t\t\t\t(size_t)maps[j].size, 0);\n \t\t\t\tif (mapaddr == MAP_FAILED)\n \t\t\t\t\tfail = 1;\n \ndiff --git a/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c b/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c\nindex 20e097727f80..f6542a1f1464 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_pci_vfio.c\n@@ -62,6 +62,9 @@\n \n #ifdef VFIO_PRESENT\n \n+#define PAGE_SIZE   (sysconf(_SC_PAGESIZE))\n+#define PAGE_MASK   (~(PAGE_SIZE - 1))\n+\n #define VFIO_DIR \"/dev/vfio\"\n #define VFIO_CONTAINER_PATH \"/dev/vfio/vfio\"\n #define VFIO_GROUP_FMT \"/dev/vfio/%u\"\n@@ -72,10 +75,12 @@ static struct vfio_config vfio_cfg;\n \n /* get PCI BAR number where MSI-X interrupts are */\n static int\n-pci_vfio_get_msix_bar(int fd, int *msix_bar)\n+pci_vfio_get_msix_bar(int fd, int *msix_bar, uint32_t *msix_table_offset,\n+\t\t      uint32_t *msix_table_size)\n {\n \tint ret;\n \tuint32_t reg;\n+\tuint16_t flags;\n \tuint8_t cap_id, cap_offset;\n \n \t/* read PCI capability pointer from config space */\n@@ -134,7 +139,18 @@ pci_vfio_get_msix_bar(int fd, int *msix_bar)\n \t\t\t\treturn -1;\n \t\t\t}\n \n+\t\t\tret = pread64(fd, &flags, sizeof(flags),\n+\t\t\t\t\tVFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +\n+\t\t\t\t\tcap_offset + 2);\n+\t\t\tif (ret != sizeof(flags)) {\n+\t\t\t\tRTE_LOG(ERR, EAL, \"Cannot read table flags from PCI config \"\n+\t\t\t\t\t\t\"space!\\n\");\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\n \t\t\t*msix_bar = reg & RTE_PCI_MSIX_TABLE_BIR;\n+\t\t\t*msix_table_offset = reg & RTE_PCI_MSIX_TABLE_OFFSET;\n+\t\t\t*msix_table_size = 16 * (1 + (flags & RTE_PCI_MSIX_FLAGS_QSIZE));\n \n \t\t\treturn 0;\n \t\t}\n@@ -532,6 +548,8 @@ pci_vfio_map_resource(struct rte_pci_device *dev)\n \tint i, ret, msix_bar;\n \tstruct mapped_pci_resource *vfio_res = NULL;\n \tstruct pci_map *maps;\n+\tuint32_t msix_table_offset = 0;\n+\tuint32_t msix_table_size = 0;\n \n \tdev->intr_handle.fd = -1;\n \tdev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;\n@@ -657,9 +675,10 @@ pci_vfio_map_resource(struct rte_pci_device *dev)\n \t}\n \n \t/* get MSI-X BAR, if any (we have to know where it is because we can't\n-\t * mmap it when using VFIO) */\n+\t * easily mmap it when using VFIO) */\n \tmsix_bar = -1;\n-\tret = pci_vfio_get_msix_bar(vfio_dev_fd, &msix_bar);\n+\tret = pci_vfio_get_msix_bar(vfio_dev_fd, &msix_bar,\n+\t\t\t\t    &msix_table_offset, &msix_table_size);\n \tif (ret < 0) {\n \t\tRTE_LOG(ERR, EAL, \"  %s cannot get MSI-X BAR number!\\n\", pci_addr);\n \t\tclose(vfio_dev_fd);\n@@ -702,6 +721,9 @@ pci_vfio_map_resource(struct rte_pci_device *dev)\n \tfor (i = 0; i < (int) vfio_res->nb_maps; i++) {\n \t\tstruct vfio_region_info reg = { .argsz = sizeof(reg) };\n \t\tvoid *bar_addr;\n+\t\tstruct memreg {\n+\t\t\tuint32_t offset, size;\n+\t\t} memreg[2] = {};\n \n \t\treg.index = i;\n \n@@ -720,21 +742,78 @@ pci_vfio_map_resource(struct rte_pci_device *dev)\n \t\tif ((reg.flags & VFIO_REGION_INFO_FLAG_MMAP) == 0)\n \t\t\tcontinue;\n \n-\t\t/* skip MSI-X BAR */\n-\t\tif (i == msix_bar)\n-\t\t\tcontinue;\n+\t\tif (i == msix_bar) {\n+\t\t\t/*\n+\t\t\t * VFIO will not let us map the MSI-X table,\n+\t\t\t * but we can map around it.\n+\t\t\t */\n+\t\t\tuint32_t table_start = msix_table_offset;\n+\t\t\tuint32_t table_end = table_start + msix_table_size;\n+\t\t\ttable_end = (table_end + ~PAGE_MASK) & PAGE_MASK;\n+\t\t\ttable_start &= PAGE_MASK;\n+\n+\t\t\tif (table_start == 0  &&  table_end >= reg.size) {\n+\t\t\t\t/* Cannot map this BAR */\n+\t\t\t\tRTE_LOG(DEBUG, EAL, \"Skipping BAR %d\\n\", i);\n+\t\t\t\tcontinue;\n+\t\t\t} else {\n+\t\t\t\tmemreg[0].offset = reg.offset;\n+\t\t\t\tmemreg[0].size = table_start;\n+\t\t\t\tmemreg[1].offset = table_end;\n+\t\t\t\tmemreg[1].size = reg.size - table_end;\n+\n+\t\t\t\tRTE_LOG(DEBUG, EAL,\n+\t\t\t\t\t\"Trying to map BAR %d that contains the MSI-X \"\n+\t\t\t\t\t\"table. Trying offsets: \"\n+\t\t\t\t\t\"%04x:%04x, %04x:%04x\\n\", i,\n+\t\t\t\t\tmemreg[0].offset, memreg[0].size,\n+\t\t\t\t\tmemreg[1].offset, memreg[1].size);\n+\t\t\t}\n+\t\t} else {\n+\t\t\tmemreg[0].offset = reg.offset;\n+\t\t\tmemreg[0].size = reg.size;\n+\t\t}\n \n+\t\t/* try to figure out an address */\n \t\tif (internal_config.process_type == RTE_PROC_PRIMARY) {\n \t\t\t/* try mapping somewhere close to the end of hugepages */\n \t\t\tif (pci_map_addr == NULL)\n \t\t\t\tpci_map_addr = pci_find_max_end_va();\n \n-\t\t\tbar_addr = pci_map_resource(pci_map_addr, vfio_dev_fd, reg.offset,\n-\t\t\t\t\treg.size);\n+\t\t\tbar_addr = pci_map_addr;\n \t\t\tpci_map_addr = RTE_PTR_ADD(bar_addr, (size_t) reg.size);\n \t\t} else {\n-\t\t\tbar_addr = pci_map_resource(maps[i].addr, vfio_dev_fd, reg.offset,\n-\t\t\t\t\treg.size);\n+\t\t\tbar_addr = maps[i].addr;\n+\t\t}\n+\n+\t\t/* reserve the address using an inaccessible mapping */\n+\t\tbar_addr = mmap(bar_addr, reg.size, 0, MAP_PRIVATE |\n+\t\t\t\tMAP_ANONYMOUS, -1, 0);\n+\t\tif (bar_addr != MAP_FAILED) {\n+\t\t\tvoid *map_addr = NULL;\n+\t\t\tif (memreg[0].size) {\n+\t\t\t\t/* actual map of first part */\n+\t\t\t\tmap_addr = pci_map_resource(bar_addr, vfio_dev_fd,\n+\t\t\t\t\t\t\t    memreg[0].offset,\n+\t\t\t\t\t\t\t    memreg[0].size,\n+\t\t\t\t\t\t\t    MAP_FIXED);\n+\t\t\t}\n+\n+\t\t\t/* if there's a second part, try to map it */\n+\t\t\tif (map_addr != MAP_FAILED\n+\t\t\t    &&  memreg[1].offset  &&  memreg[1].size) {\n+\t\t\t\tuint8_t *second_addr =\n+\t\t\t\t\t((uint8_t *)bar_addr + memreg[1].offset);\n+\t\t\t\tmap_addr = pci_map_resource((void *)second_addr,\n+\t\t\t\t\t\t\t    vfio_dev_fd, memreg[1].offset,\n+\t\t\t\t\t\t\t    memreg[1].size,\n+\t\t\t\t\t\t\t    MAP_FIXED);\n+\t\t\t}\n+\n+\t\t\tif (map_addr == MAP_FAILED  ||  !map_addr) {\n+\t\t\t\tmunmap(bar_addr, reg.size);\n+\t\t\t\tbar_addr = MAP_FAILED;\n+\t\t\t}\n \t\t}\n \n \t\tif (bar_addr == MAP_FAILED ||\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_vfio.h b/lib/librte_eal/linuxapp/eal/eal_vfio.h\nindex 03e693e01bf0..72ec3f62a3d8 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_vfio.h\n+++ b/lib/librte_eal/linuxapp/eal/eal_vfio.h\n@@ -43,9 +43,13 @@\n #include <linux/vfio.h>\n \n #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)\n-#define RTE_PCI_MSIX_TABLE_BIR 0x7\n+#define RTE_PCI_MSIX_TABLE_BIR    0x7\n+#define RTE_PCI_MSIX_TABLE_OFFSET 0xfffffff8\n+#define RTE_PCI_MSIX_FLAGS_QSIZE  0x07ff\n #else\n-#define RTE_PCI_MSIX_TABLE_BIR PCI_MSIX_TABLE_BIR\n+#define RTE_PCI_MSIX_TABLE_BIR    PCI_MSIX_TABLE_BIR\n+#define RTE_PCI_MSIX_TABLE_OFFSET PCI_MSIX_TABLE_OFFSET\n+#define RTE_PCI_MSIX_FLAGS_QSIZE  PCI_MSIX_FLAGS_QSIZE\n #endif\n \n #define VFIO_PRESENT\n",
    "prefixes": [
        "dpdk-dev"
    ]
}