From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by dpdk.org (Postfix) with ESMTP id EDD9B2A6A; Thu, 17 Jan 2019 18:31:03 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 17 Jan 2019 09:31:02 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,489,1539673200"; d="scan'208";a="311288614" Received: from irvmail001.ir.intel.com ([163.33.26.43]) by fmsmga006.fm.intel.com with ESMTP; 17 Jan 2019 09:31:00 -0800 Received: from sivswdev05.ir.intel.com (sivswdev05.ir.intel.com [10.243.17.64]) by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id x0HHV0JW020700; Thu, 17 Jan 2019 17:31:00 GMT Received: from sivswdev05.ir.intel.com (localhost [127.0.0.1]) by sivswdev05.ir.intel.com with ESMTP id x0HHV02t000322; Thu, 17 Jan 2019 17:31:00 GMT Received: (from aburakov@localhost) by sivswdev05.ir.intel.com with LOCAL id x0HHUxS2000317; Thu, 17 Jan 2019 17:30:59 GMT From: Anatoly Burakov To: dev@dpdk.org Cc: xiao.w.wang@intel.com, qi.z.zhang@intel.com, qingfu.cqf@alibaba-inc.com, thomas@monjalon.net, dariusz.stojaczyk@intel.com, stable@dpdk.org Date: Thu, 17 Jan 2019 17:30:59 +0000 Message-Id: X-Mailer: git-send-email 1.7.0.7 Subject: [dpdk-stable] [PATCH] vfio: allow secondary process to query IOMMU type X-BeenThere: stable@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches for DPDK stable branches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Jan 2019 17:31:04 -0000 It is only possible to know IOMMU type of a given VFIO container by attempting to initialize it. Since secondary process never attempts to set up VFIO container itself (because they're shared between primary and secondary), it never knows which IOMMU type the container is using, and never sets up the appropriate config structures. This results in inability to perform DMA mappings in secondary process. Fix this by allowing secondary process to query IOMMU type of primary's default container at device initialization. Note that this fix is assuming we're only interested in default container. Bugzilla ID: 174 Fixes: 6bcb7c95fe14 ("vfio: share default container in multi-process") Cc: dariusz.stojaczyk@intel.com Cc: stable@dpdk.org Signed-off-by: Anatoly Burakov --- lib/librte_eal/linuxapp/eal/eal_vfio.c | 89 +++++++++++++++++++ lib/librte_eal/linuxapp/eal/eal_vfio.h | 12 ++- .../linuxapp/eal/eal_vfio_mp_sync.c | 16 ++++ 3 files changed, 116 insertions(+), 1 deletion(-) diff --git a/lib/librte_eal/linuxapp/eal/eal_vfio.c b/lib/librte_eal/linuxapp/eal/eal_vfio.c index 72cc65151..17648b1ae 100644 --- a/lib/librte_eal/linuxapp/eal/eal_vfio.c +++ b/lib/librte_eal/linuxapp/eal/eal_vfio.c @@ -549,6 +549,66 @@ vfio_mem_event_callback(enum rte_mem_event type, const void *addr, size_t len, } } +static int +vfio_sync_default_container(void) +{ + struct rte_mp_msg mp_req, *mp_rep; + struct rte_mp_reply mp_reply; + struct timespec ts = {.tv_sec = 5, .tv_nsec = 0}; + struct vfio_mp_param *p = (struct vfio_mp_param *)mp_req.param; + int vfio_container_fd, iommu_type_id; + unsigned int i; + + /* cannot be called from primary */ + if (rte_eal_process_type() != RTE_PROC_SECONDARY) + return -1; + + /* get default container from the primary */ + vfio_container_fd = vfio_get_default_container_fd(); + if (vfio_container_fd < 0) { + RTE_LOG(ERR, EAL, "Cannot get default container fd\n"); + return -1; + } + + /* find default container's IOMMU type */ + p->req = SOCKET_REQ_IOMMU_TYPE; + strcpy(mp_req.name, EAL_VFIO_MP); + mp_req.len_param = sizeof(*p); + mp_req.num_fds = 0; + + iommu_type_id = -1; + if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 && + mp_reply.nb_received == 1) { + mp_rep = &mp_reply.msgs[0]; + p = (struct vfio_mp_param *)mp_rep->param; + if (p->result == SOCKET_OK) + iommu_type_id = p->iommu_type_id; + free(mp_reply.msgs); + } + if (iommu_type_id < 0) { + RTE_LOG(ERR, EAL, "Could not get IOMMU type for default container\n"); + close(vfio_container_fd); + return -1; + } + + /* we now have an fd for default container, as well as its IOMMU type. + * now, set up default VFIO container config to match. + */ + for (i = 0; i < RTE_DIM(iommu_types); i++) { + const struct vfio_iommu_type *t = &iommu_types[i]; + if (t->type_id != iommu_type_id) + continue; + + /* we found our IOMMU type */ + default_vfio_cfg->vfio_enabled = 1; + default_vfio_cfg->vfio_container_fd = vfio_container_fd; + default_vfio_cfg->vfio_iommu_type = t; + break; + } + + return 0; +} + int rte_vfio_clear_group(int vfio_group_fd) { @@ -745,6 +805,26 @@ rte_vfio_setup_device(const char *sysfs_base, const char *dev_addr, else RTE_LOG(DEBUG, EAL, "Installed memory event callback for VFIO\n"); } + } else if (rte_eal_process_type() != RTE_PROC_PRIMARY && + vfio_cfg == default_vfio_cfg && + vfio_cfg->vfio_iommu_type == NULL) { + /* if we're not a primary process, we do not set up the VFIO + * container because it's already been set up by the primary + * process. instead, we simply ask the primary about VFIO type + * we are using, and set the VFIO config up appropriately. + */ + ret = vfio_sync_default_container(); + if (ret < 0) { + RTE_LOG(ERR, EAL, "Could not sync default VFIO container\n"); + close(vfio_group_fd); + rte_vfio_clear_group(vfio_group_fd); + return -1; + } + /* we have successfully initialized VFIO, notify user */ + const struct vfio_iommu_type *t = + default_vfio_cfg->vfio_iommu_type; + RTE_LOG(NOTICE, EAL, " using IOMMU type %d (%s)\n", + t->type_id, t->name); } /* get a file descriptor for the device */ @@ -978,6 +1058,15 @@ vfio_get_default_container_fd(void) return -1; } +int +vfio_get_iommu_type(void) +{ + if (default_vfio_cfg->vfio_iommu_type == NULL) + return -1; + + return default_vfio_cfg->vfio_iommu_type->type_id; +} + const struct vfio_iommu_type * vfio_set_iommu_type(int vfio_container_fd) { diff --git a/lib/librte_eal/linuxapp/eal/eal_vfio.h b/lib/librte_eal/linuxapp/eal/eal_vfio.h index 63ae115c3..cb2d35fb1 100644 --- a/lib/librte_eal/linuxapp/eal/eal_vfio.h +++ b/lib/librte_eal/linuxapp/eal/eal_vfio.h @@ -5,6 +5,8 @@ #ifndef EAL_VFIO_H_ #define EAL_VFIO_H_ +#include + /* * determine if VFIO is present on the system */ @@ -122,6 +124,9 @@ int vfio_get_default_container_fd(void); const struct vfio_iommu_type * vfio_set_iommu_type(int vfio_container_fd); +int +vfio_get_iommu_type(void); + /* check if we have any supported extensions */ int vfio_has_supported_extensions(int vfio_container_fd); @@ -133,6 +138,7 @@ int vfio_mp_sync_setup(void); #define SOCKET_REQ_CONTAINER 0x100 #define SOCKET_REQ_GROUP 0x200 #define SOCKET_REQ_DEFAULT_CONTAINER 0x400 +#define SOCKET_REQ_IOMMU_TYPE 0x800 #define SOCKET_OK 0x0 #define SOCKET_NO_FD 0x1 #define SOCKET_ERR 0xFF @@ -140,7 +146,11 @@ int vfio_mp_sync_setup(void); struct vfio_mp_param { int req; int result; - int group_num; + RTE_STD_C11 + union { + int group_num; + int iommu_type_id; + }; }; #endif /* VFIO_PRESENT */ diff --git a/lib/librte_eal/linuxapp/eal/eal_vfio_mp_sync.c b/lib/librte_eal/linuxapp/eal/eal_vfio_mp_sync.c index a1e8c834f..2a47f29d5 100644 --- a/lib/librte_eal/linuxapp/eal/eal_vfio_mp_sync.c +++ b/lib/librte_eal/linuxapp/eal/eal_vfio_mp_sync.c @@ -77,6 +77,22 @@ vfio_mp_primary(const struct rte_mp_msg *msg, const void *peer) reply.fds[0] = fd; } break; + case SOCKET_REQ_IOMMU_TYPE: + { + int iommu_type_id; + + r->req = SOCKET_REQ_IOMMU_TYPE; + + iommu_type_id = vfio_get_iommu_type(); + + if (iommu_type_id < 0) + r->result = SOCKET_ERR; + else { + r->iommu_type_id = iommu_type_id; + r->result = SOCKET_OK; + } + break; + } default: RTE_LOG(ERR, EAL, "vfio received invalid message!\n"); return -1; -- 2.17.1