From patchwork Wed Apr 24 12:01:21 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Gibson X-Patchwork-Id: 239178 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id ED1A32C007A for ; Wed, 24 Apr 2013 22:13:11 +1000 (EST) Received: from localhost ([::1]:51881 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UUyZS-0006Ew-21 for incoming@patchwork.ozlabs.org; Wed, 24 Apr 2013 08:13:10 -0400 Received: from eggs.gnu.org ([208.118.235.92]:42906) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UUyYv-00065Z-Te for qemu-devel@nongnu.org; Wed, 24 Apr 2013 08:12:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UUyYr-0003pd-Bj for qemu-devel@nongnu.org; Wed, 24 Apr 2013 08:12:37 -0400 Received: from ozlabs.org ([203.10.76.45]:57445) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UUyOR-0008JA-9e for qemu-devel@nongnu.org; Wed, 24 Apr 2013 08:01:47 -0400 Received: by ozlabs.org (Postfix, from userid 1007) id 898D02C011E; Wed, 24 Apr 2013 22:01:38 +1000 (EST) From: David Gibson To: alex.williamson@redhat.com, aik@ozlabs.ru Date: Wed, 24 Apr 2013 22:01:21 +1000 Message-Id: <1366804881-553-6-git-send-email-david@gibson.dropbear.id.au> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1366804881-553-1-git-send-email-david@gibson.dropbear.id.au> References: <1366804881-553-1-git-send-email-david@gibson.dropbear.id.au> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 203.10.76.45 Cc: qemu-devel@nongnu.org, David Gibson Subject: [Qemu-devel] [PATCH 5/5] vfio: Only use memory listeners when appropriate X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Currently, vfio registers a MemoryListener for every vfio container we create, to keep the container's mappings in sync with main system memory. That's only correct though, if the context the container is attached to represents a dma address space which actually matches main system memory - roughly speaking that means that there is no guest side IOMMU above the vfio device in question. This patch corrects the code, by only registering the MemoryListener when the container belongs to a DMAContext which does not include an IOMMU (i.e. which has no ->translate function). In other cases we given an error; that will change when vfio support for guest side IOMMUs is added. In addition, this generalizes the code slightly, by attaching the MemoryListener to the DMAContext's underlying AddressSpace, rather than just assuming that it is main system memory. Signed-off-by: David Gibson --- hw/misc/vfio.c | 79 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index ab870a8..dce6189 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -2616,28 +2616,11 @@ void dma_context_init_vfio(DMAContext *dma) QLIST_INIT(&dma->vfio.containers); } -static int vfio_connect_context(VFIOGroup *group, DMAContext *dma) +static int vfio_connect_container_address_space(VFIOGroup *group, + DMAContext *dma) { VFIOContainer *container; - int ret, fd; - - if (group->container) { - if (group->container->dma == dma) { - return 0; - } else { - error_report("vfio: group %d used in multiple DMA contexts", - group->groupid); - return -EBUSY; - } - } - - QLIST_FOREACH(container, &dma->vfio.containers, next) { - if (!ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &container->fd)) { - group->container = container; - QLIST_INSERT_HEAD(&container->group_list, group, container_next); - return 0; - } - } + int fd, ret; fd = qemu_open("/dev/vfio/vfio", O_RDWR); if (fd < 0) { @@ -2657,15 +2640,15 @@ static int vfio_connect_context(VFIOGroup *group, DMAContext *dma) container->dma = dma; container->fd = fd; - if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU)) { - ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd); - if (ret) { - error_report("vfio: failed to set group container: %m"); - g_free(container); - close(fd); - return -errno; - } + ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd); + if (ret) { + error_report("vfio: failed to set group container: %m"); + g_free(container); + close(fd); + return -errno; + } + if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU)) { ret = ioctl(fd, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU); if (ret) { error_report("vfio: failed to set iommu for container: %m"); @@ -2673,11 +2656,6 @@ static int vfio_connect_context(VFIOGroup *group, DMAContext *dma) close(fd); return -errno; } - - container->iommu_data.listener = vfio_memory_listener; - container->iommu_data.release = vfio_listener_release; - - memory_listener_register(&container->iommu_data.listener, &address_space_memory); } else { error_report("vfio: No available IOMMU models"); g_free(container); @@ -2685,6 +2663,11 @@ static int vfio_connect_context(VFIOGroup *group, DMAContext *dma) return -EINVAL; } + container->iommu_data.listener = vfio_memory_listener; + container->iommu_data.release = vfio_listener_release; + + memory_listener_register(&container->iommu_data.listener, dma->as); + QLIST_INIT(&container->group_list); QLIST_INSERT_HEAD(&dma->vfio.containers, container, next); @@ -2694,6 +2677,36 @@ static int vfio_connect_context(VFIOGroup *group, DMAContext *dma) return 0; } +static int vfio_connect_context(VFIOGroup *group, DMAContext *dma) +{ + VFIOContainer *container; + + if (group->container) { + if (group->container->dma == dma) { + return 0; + } else { + error_report("vfio: group %d used in multiple DMA contexts", + group->groupid); + return -EBUSY; + } + } + + QLIST_FOREACH(container, &dma->vfio.containers, next) { + if (!ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &container->fd)) { + group->container = container; + QLIST_INSERT_HEAD(&container->group_list, group, container_next); + return 0; + } + } + + if (!dma->translate) { + return vfio_connect_container_address_space(group, dma); + } + + error_report("vfio: no support for guest side IOMMU"); + return -ENODEV; +} + static void vfio_disconnect_context(VFIOGroup *group) { VFIOContainer *container = group->container;