From nobody Tue Apr 30 00:26:40 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1569313732; cv=none; d=zoho.com; s=zohoarc; b=YkJhze9u2ih+5OAmS0vFI1n3MkBqmfuWSYT4wHLD4BtMkyK8u2JcIkmj+xI3fdy9nHp1lS1dRVMfTXhSpCpArV9R5OY6EXup7k2rjMqVtI/NQFtZNd6XqVOWESXsCddKqXFvFVobsyhG1zR5IyuoAEH9PRWVk14shxR5Bj+qt40= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1569313732; h=Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=/XubTthtEZo0SoFtuzWqgidV2bfraC/OzAxdRbp3WC8=; b=Z08z841sWQyc6msefN47h+fedpRspCSetAHBeRkD1lT+agJGbxpN3B8SE85LGFi3zzbHLCuPWktP2IdMKpG5wF2GBDqaf/N8BSpnmqVDyOkua0MQnLn+4FnvP4BsPs1Q+PEufW7AocyI1GwXr0IAS9tk9jtNpDrkk3OrQIUp31w= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1569313732658194.70896955393255; Tue, 24 Sep 2019 01:28:52 -0700 (PDT) Received: from localhost ([::1]:42522 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCgBn-0002eB-Ac for importer@patchew.org; Tue, 24 Sep 2019 04:28:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46883) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCg8i-0000g9-8M for qemu-devel@nongnu.org; Tue, 24 Sep 2019 04:25:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCg8g-0006tA-N8 for qemu-devel@nongnu.org; Tue, 24 Sep 2019 04:25:40 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56858) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCg8a-0006sB-Sc; Tue, 24 Sep 2019 04:25:34 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5DB873082133; Tue, 24 Sep 2019 08:25:31 +0000 (UTC) Received: from laptop.redhat.com (ovpn-116-30.ams2.redhat.com [10.36.116.30]) by smtp.corp.redhat.com (Postfix) with ESMTP id F232460603; Tue, 24 Sep 2019 08:25:28 +0000 (UTC) From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, qemu-devel@nongnu.org, qemu-arm@nongnu.org, peter.maydell@linaro.org, pbonzini@redhat.com, alex.williamson@redhat.com, peterx@redhat.com, aik@ozlabs.ru, david@gibson.dropbear.id.au Subject: [PATCH v4 1/2] vfio: Turn the container error into an Error handle Date: Tue, 24 Sep 2019 10:25:16 +0200 Message-Id: <20190924082517.13724-2-eric.auger@redhat.com> In-Reply-To: <20190924082517.13724-1-eric.auger@redhat.com> References: <20190924082517.13724-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Tue, 24 Sep 2019 08:25:31 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" The container error integer field is currently used to store the first error potentially encountered during any vfio_listener_region_add() call. However this fails to propagate detailed error messages up to the vfio_connect_container caller. Instead of using an integer, let's use an Error handle. Messages are slightly reworded to accomodate the propagation. Signed-off-by: Eric Auger Acked-by: Alex Williamson Acked-by: David Gibson Acked-by: Paolo Bonzini Reviewed-by: David Gibson --- v3 -> v4: - remove ret useless assignments and restore hw_error() - remove mr local variable - trace [start, end] instead of [start, size] and improve the message for overalp with existing DMA host window --- hw/vfio/common.c | 43 +++++++++++++++++++++++------------ hw/vfio/spapr.c | 4 +++- include/hw/vfio/vfio-common.h | 2 +- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 3e03c495d8..cebbb1c28a 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -509,6 +509,7 @@ static void vfio_listener_region_add(MemoryListener *li= stener, int ret; VFIOHostDMAWindow *hostwin; bool hostwin_found; + Error *err =3D NULL; =20 if (vfio_listener_skipped_section(section)) { trace_vfio_listener_region_add_skip( @@ -543,13 +544,20 @@ static void vfio_listener_region_add(MemoryListener *= listener, hostwin->max_iova - hostwin->min_iova + 1, section->offset_within_address_space, int128_get64(section->size))) { - ret =3D -1; + error_setg(&err, + "region [0x%"PRIx64",0x%"PRIx64"] overlaps with existi= ng" + "host DMA window [0x%"PRIx64",0x%"PRIx64"]", + section->offset_within_address_space, + section->offset_within_address_space + + int128_get64(section->size) - 1, + hostwin->min_iova, hostwin->max_iova); goto fail; } } =20 ret =3D vfio_spapr_create_window(container, section, &pgsize); if (ret) { + error_setg_errno(&err, -ret, "Failed to create SPAPR window"); goto fail; } =20 @@ -594,10 +602,8 @@ static void vfio_listener_region_add(MemoryListener *l= istener, } =20 if (!hostwin_found) { - error_report("vfio: IOMMU container %p can't map guest IOVA region" - " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx, - container, iova, end); - ret =3D -EFAULT; + error_setg(&err, "Container %p can't map guest IOVA region" + " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx, container, iova, e= nd); goto fail; } =20 @@ -664,11 +670,12 @@ static void vfio_listener_region_add(MemoryListener *= listener, ret =3D vfio_dma_map(container, iova, int128_get64(llsize), vaddr, section->readonly); if (ret) { - error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", " - "0x%"HWADDR_PRIx", %p) =3D %d (%m)", - container, iova, int128_get64(llsize), vaddr, ret); + error_setg(&err, "vfio_dma_map(%p, 0x%"HWADDR_PRIx", " + "0x%"HWADDR_PRIx", %p) =3D %d (%m)", + container, iova, int128_get64(llsize), vaddr, ret); if (memory_region_is_ram_device(section->mr)) { /* Allow unexpected mappings not to be fatal for RAM devices */ + error_report_err(err); return; } goto fail; @@ -688,9 +695,14 @@ fail: */ if (!container->initialized) { if (!container->error) { - container->error =3D ret; + error_propagate_prepend(&container->error, err, + "Region %s: ", + memory_region_name(section->mr)); + } else { + error_free(err); } } else { + error_report_err(err); hw_error("vfio: DMA mapping failed, unable to continue"); } } @@ -1251,6 +1263,7 @@ static int vfio_connect_container(VFIOGroup *group, A= ddressSpace *as, container =3D g_malloc0(sizeof(*container)); container->space =3D space; container->fd =3D fd; + container->error =3D NULL; QLIST_INIT(&container->giommu_list); QLIST_INIT(&container->hostwin_list); =20 @@ -1308,9 +1321,9 @@ static int vfio_connect_container(VFIOGroup *group, A= ddressSpace *as, &address_space_memory); if (container->error) { memory_listener_unregister(&container->prereg_listener); - ret =3D container->error; - error_setg(errp, - "RAM memory listener initialization failed for contain= er"); + ret =3D -1; + error_propagate_prepend(errp, container->error, + "RAM memory listener initialization failed: "); goto free_container_exit; } } @@ -1365,9 +1378,9 @@ static int vfio_connect_container(VFIOGroup *group, A= ddressSpace *as, memory_listener_register(&container->listener, container->space->as); =20 if (container->error) { - ret =3D container->error; - error_setg_errno(errp, -ret, - "memory listener initialization failed for contai= ner"); + ret =3D -1; + error_propagate_prepend(errp, container->error, + "memory listener initialization failed: "); goto listener_release_exit; } =20 diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c index 96c0ad9d9b..e853eebe11 100644 --- a/hw/vfio/spapr.c +++ b/hw/vfio/spapr.c @@ -17,6 +17,7 @@ #include "hw/hw.h" #include "exec/ram_addr.h" #include "qemu/error-report.h" +#include "qapi/error.h" #include "trace.h" =20 static bool vfio_prereg_listener_skipped_section(MemoryRegionSection *sect= ion) @@ -85,7 +86,8 @@ static void vfio_prereg_listener_region_add(MemoryListene= r *listener, */ if (!container->initialized) { if (!container->error) { - container->error =3D ret; + error_setg_errno(&container->error, -ret, + "Memory registering failed"); } } else { hw_error("vfio: Memory registering failed, unable to continue"= ); diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index 9107bd41c0..fd564209ac 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -71,7 +71,7 @@ typedef struct VFIOContainer { MemoryListener listener; MemoryListener prereg_listener; unsigned iommu_type; - int error; + Error *error; bool initialized; unsigned long pgsizes; QLIST_HEAD(, VFIOGuestIOMMU) giommu_list; --=20 2.20.1 From nobody Tue Apr 30 00:26:40 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1569313729; cv=none; d=zoho.com; s=zohoarc; b=jc49T2D9OZk/uTvTjVH1DKNG4Wzh0TQU1biprqKeEdHxZndvpdMCGNlHiVn24iP1aUsotJTrnJq5ojkoPJv66FT0h+tenvK+zjyLbeyygvvCrKm3U3D1GhBiRYSG9+6674goAcc2gmt/c9T93DnIGrxkE6zCmc69jsUGFSNmdhM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1569313729; h=Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=ERtJfpUcVEZ5qRA0/UhIUP1OgdB26jeuXqDh668dT60=; b=VAlGI+yXYsNHQeuItDxjxJCjR0ARMsm0c1eGC3p/eDV7iJ/Jtx7NDiSJZo9Vdyvh1aJq6cQFu5ZgfkYclsMBpN5U6FMne3cEIZPcAe5wI+UsTjztGL3m+1MB+ejYrC77URpIT+rWry1Bt2Ffs/nZrXgo8UdG5fZHIFqyso75owM= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1569313729401662.6714699668462; Tue, 24 Sep 2019 01:28:49 -0700 (PDT) Received: from localhost ([::1]:42520 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCgBe-0002SE-RL for importer@patchew.org; Tue, 24 Sep 2019 04:28:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46914) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iCg8r-0000jf-1A for qemu-devel@nongnu.org; Tue, 24 Sep 2019 04:25:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iCg8o-0006u6-BX for qemu-devel@nongnu.org; Tue, 24 Sep 2019 04:25:48 -0400 Received: from mx1.redhat.com ([209.132.183.28]:39706) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iCg8d-0006sP-BN; Tue, 24 Sep 2019 04:25:36 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3F52918CB8EC; Tue, 24 Sep 2019 08:25:34 +0000 (UTC) Received: from laptop.redhat.com (ovpn-116-30.ams2.redhat.com [10.36.116.30]) by smtp.corp.redhat.com (Postfix) with ESMTP id B2CCA60852; Tue, 24 Sep 2019 08:25:31 +0000 (UTC) From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, qemu-devel@nongnu.org, qemu-arm@nongnu.org, peter.maydell@linaro.org, pbonzini@redhat.com, alex.williamson@redhat.com, peterx@redhat.com, aik@ozlabs.ru, david@gibson.dropbear.id.au Subject: [PATCH v4 2/2] memory: allow memory_region_register_iommu_notifier() to fail Date: Tue, 24 Sep 2019 10:25:17 +0200 Message-Id: <20190924082517.13724-3-eric.auger@redhat.com> In-Reply-To: <20190924082517.13724-1-eric.auger@redhat.com> References: <20190924082517.13724-1-eric.auger@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 (mx1.redhat.com [10.5.110.63]); Tue, 24 Sep 2019 08:25:34 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Currently, when a notifier is attempted to be registered and its flags are not supported (especially the MAP one) by the IOMMU MR, we generally abruptly exit in the IOMMU code. The failure could be handled more nicely in the caller and especially in the VFIO code. So let's allow memory_region_register_iommu_notifier() to fail as well as notify_flag_changed() callback. All sites implementing the callback are updated. This patch does not yet remove the exit(1) in the amd_iommu code. in SMMUv3 we turn the warning message into an error message saying that the assigned device would not work properly. Signed-off-by: Eric Auger Reviewed-by: Peter Xu Acked-by: Alex Williamson Acked-by: David Gibson Reviewed-by: David Gibson --- v2 -> v3: - turn the warning message into an error message --- exec.c | 10 ++++++++-- hw/arm/smmuv3.c | 18 ++++++++++-------- hw/i386/amd_iommu.c | 17 ++++++++++------- hw/i386/intel_iommu.c | 8 +++++--- hw/ppc/spapr_iommu.c | 8 +++++--- hw/vfio/common.c | 9 +++++++-- hw/virtio/vhost.c | 9 +++++++-- include/exec/memory.h | 21 ++++++++++++++++----- memory.c | 31 ++++++++++++++++++++----------- 9 files changed, 88 insertions(+), 43 deletions(-) diff --git a/exec.c b/exec.c index 8b998974f8..7379330756 100644 --- a/exec.c +++ b/exec.c @@ -663,7 +663,8 @@ static void tcg_register_iommu_notifier(CPUState *cpu, */ MemoryRegion *mr =3D MEMORY_REGION(iommu_mr); TCGIOMMUNotifier *notifier; - int i; + Error *err =3D NULL; + int i, ret; =20 for (i =3D 0; i < cpu->iommu_notifiers->len; i++) { notifier =3D g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier = *, i); @@ -692,7 +693,12 @@ static void tcg_register_iommu_notifier(CPUState *cpu, 0, HWADDR_MAX, iommu_idx); - memory_region_register_iommu_notifier(notifier->mr, ¬ifier->n); + ret =3D memory_region_register_iommu_notifier(notifier->mr, ¬if= ier->n, + &err); + if (ret) { + error_report_err(err); + exit(1); + } } =20 if (!notifier->active) { diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index db051dcac8..e2fbb8357e 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -1469,20 +1469,21 @@ static void smmuv3_class_init(ObjectClass *klass, v= oid *data) dc->realize =3D smmu_realize; } =20 -static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu, - IOMMUNotifierFlag old, - IOMMUNotifierFlag new) +static int smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu, + IOMMUNotifierFlag old, + IOMMUNotifierFlag new, + Error **errp) { SMMUDevice *sdev =3D container_of(iommu, SMMUDevice, iommu); SMMUv3State *s3 =3D sdev->smmu; SMMUState *s =3D &(s3->smmu_state); =20 if (new & IOMMU_NOTIFIER_MAP) { - int bus_num =3D pci_bus_num(sdev->bus); - PCIDevice *pcidev =3D pci_find_device(sdev->bus, bus_num, sdev->de= vfn); - - warn_report("SMMUv3 does not support notification on MAP: " - "device %s will not function properly", pcidev->name); + error_setg(errp, + "device %02x.%02x.%x requires iommu MAP notifier which = is " + "not currently supported", pci_bus_num(sdev->bus), + PCI_SLOT(sdev->devfn), PCI_FUNC(sdev->devfn)); + return -EINVAL; } =20 if (old =3D=3D IOMMU_NOTIFIER_NONE) { @@ -1492,6 +1493,7 @@ static void smmuv3_notify_flag_changed(IOMMUMemoryReg= ion *iommu, trace_smmuv3_notify_flag_del(iommu->parent_obj.name); QLIST_REMOVE(sdev, next); } + return 0; } =20 static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass, diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index 08884523e2..d3726361dd 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -1466,18 +1466,21 @@ static const MemoryRegionOps mmio_mem_ops =3D { } }; =20 -static void amdvi_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu, - IOMMUNotifierFlag old, - IOMMUNotifierFlag new) +static int amdvi_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu, + IOMMUNotifierFlag old, + IOMMUNotifierFlag new, + Error **errp) { AMDVIAddressSpace *as =3D container_of(iommu, AMDVIAddressSpace, iommu= ); =20 if (new & IOMMU_NOTIFIER_MAP) { - error_report("device %02x.%02x.%x requires iommu notifier which is= not " - "currently supported", as->bus_num, PCI_SLOT(as->devf= n), - PCI_FUNC(as->devfn)); - exit(1); + error_setg(errp, + "device %02x.%02x.%x requires iommu notifier which is n= ot " + "currently supported", as->bus_num, PCI_SLOT(as->devfn), + PCI_FUNC(as->devfn)); + return -EINVAL; } + return 0; } =20 static void amdvi_init(AMDVIState *s) diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index f1de8fdb75..771bed25c9 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -2929,9 +2929,10 @@ static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemory= Region *iommu, hwaddr addr, return iotlb; } =20 -static void vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu, - IOMMUNotifierFlag old, - IOMMUNotifierFlag new) +static int vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu, + IOMMUNotifierFlag old, + IOMMUNotifierFlag new, + Error **errp) { VTDAddressSpace *vtd_as =3D container_of(iommu, VTDAddressSpace, iommu= ); IntelIOMMUState *s =3D vtd_as->iommu_state; @@ -2944,6 +2945,7 @@ static void vtd_iommu_notify_flag_changed(IOMMUMemory= Region *iommu, } else if (new =3D=3D IOMMU_NOTIFIER_NONE) { QLIST_REMOVE(vtd_as, next); } + return 0; } =20 static int vtd_post_load(void *opaque, int version_id) diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index e87b3d50f7..3d3bcc8649 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -205,9 +205,10 @@ static int spapr_tce_get_attr(IOMMUMemoryRegion *iommu, return -EINVAL; } =20 -static void spapr_tce_notify_flag_changed(IOMMUMemoryRegion *iommu, - IOMMUNotifierFlag old, - IOMMUNotifierFlag new) +static int spapr_tce_notify_flag_changed(IOMMUMemoryRegion *iommu, + IOMMUNotifierFlag old, + IOMMUNotifierFlag new, + Error **errp) { struct SpaprTceTable *tbl =3D container_of(iommu, SpaprTceTable, iommu= ); =20 @@ -216,6 +217,7 @@ static void spapr_tce_notify_flag_changed(IOMMUMemoryRe= gion *iommu, } else if (old !=3D IOMMU_NOTIFIER_NONE && new =3D=3D IOMMU_NOTIFIER_N= ONE) { spapr_tce_set_need_vfio(tbl, false); } + return 0; } =20 static int spapr_tce_table_post_load(void *opaque, int version_id) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index cebbb1c28a..5ca11488d6 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -636,9 +636,14 @@ static void vfio_listener_region_add(MemoryListener *l= istener, section->offset_within_region, int128_get64(llend), iommu_idx); - QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next); =20 - memory_region_register_iommu_notifier(section->mr, &giommu->n); + ret =3D memory_region_register_iommu_notifier(section->mr, &giommu= ->n, + &err); + if (ret) { + g_free(giommu); + goto fail; + } + QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next); memory_region_iommu_replay(giommu->iommu, &giommu->n); =20 return; diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 34accdf615..9a65f034a5 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -672,8 +672,9 @@ static void vhost_iommu_region_add(MemoryListener *list= ener, iommu_listener); struct vhost_iommu *iommu; Int128 end; - int iommu_idx; + int iommu_idx, ret; IOMMUMemoryRegion *iommu_mr; + Error *err =3D NULL; =20 if (!memory_region_is_iommu(section->mr)) { return; @@ -696,7 +697,11 @@ static void vhost_iommu_region_add(MemoryListener *lis= tener, iommu->iommu_offset =3D section->offset_within_address_space - section->offset_within_region; iommu->hdev =3D dev; - memory_region_register_iommu_notifier(section->mr, &iommu->n); + ret =3D memory_region_register_iommu_notifier(section->mr, &iommu->n, = &err); + if (ret) { + error_report_err(err); + exit(1); + } QLIST_INSERT_HEAD(&dev->iommu_list, iommu, iommu_next); /* TODO: can replay help performance here? */ } diff --git a/include/exec/memory.h b/include/exec/memory.h index a30245c25a..c16430726c 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -288,10 +288,16 @@ typedef struct IOMMUMemoryRegionClass { * @iommu: the IOMMUMemoryRegion * @old_flags: events which previously needed to be notified * @new_flags: events which now need to be notified + * + * Returns 0 on success, or a negative errno; in particular + * returns -EINVAL if the new flag bitmap is not supported by the + * IOMMU memory region. In case of failure, the error object + * must be created */ - void (*notify_flag_changed)(IOMMUMemoryRegion *iommu, - IOMMUNotifierFlag old_flags, - IOMMUNotifierFlag new_flags); + int (*notify_flag_changed)(IOMMUMemoryRegion *iommu, + IOMMUNotifierFlag old_flags, + IOMMUNotifierFlag new_flags, + Error **errp); /* Called to handle memory_region_iommu_replay(). * * The default implementation of memory_region_iommu_replay() is to @@ -1067,13 +1073,18 @@ void memory_region_notify_one(IOMMUNotifier *notifi= er, * memory_region_register_iommu_notifier: register a notifier for changes = to * IOMMU translation entries. * + * Returns 0 on success, or a negative errno otherwise. In particular, + * -EINVAL indicates that at least one of the attributes of the notifier + * is not supported (flag/range) by the IOMMU memory region. In case of er= ror + * the error object must be created. + * * @mr: the memory region to observe * @n: the IOMMUNotifier to be added; the notify callback receives a * pointer to an #IOMMUTLBEntry as the opaque value; the pointer * ceases to be valid on exit from the notifier. */ -void memory_region_register_iommu_notifier(MemoryRegion *mr, - IOMMUNotifier *n); +int memory_region_register_iommu_notifier(MemoryRegion *mr, + IOMMUNotifier *n, Error **errp); =20 /** * memory_region_iommu_replay: replay existing IOMMU translations to diff --git a/memory.c b/memory.c index b9dd6b94ca..6df84a4f9c 100644 --- a/memory.c +++ b/memory.c @@ -1837,33 +1837,38 @@ bool memory_region_is_logging(MemoryRegion *mr, uin= t8_t client) return memory_region_get_dirty_log_mask(mr) & (1 << client); } =20 -static void memory_region_update_iommu_notify_flags(IOMMUMemoryRegion *iom= mu_mr) +static int memory_region_update_iommu_notify_flags(IOMMUMemoryRegion *iomm= u_mr, + Error **errp) { IOMMUNotifierFlag flags =3D IOMMU_NOTIFIER_NONE; IOMMUNotifier *iommu_notifier; IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_GET_CLASS(iommu_m= r); + int ret =3D 0; =20 IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) { flags |=3D iommu_notifier->notifier_flags; } =20 if (flags !=3D iommu_mr->iommu_notify_flags && imrc->notify_flag_chang= ed) { - imrc->notify_flag_changed(iommu_mr, - iommu_mr->iommu_notify_flags, - flags); + ret =3D imrc->notify_flag_changed(iommu_mr, + iommu_mr->iommu_notify_flags, + flags, errp); } =20 - iommu_mr->iommu_notify_flags =3D flags; + if (!ret) { + iommu_mr->iommu_notify_flags =3D flags; + } + return ret; } =20 -void memory_region_register_iommu_notifier(MemoryRegion *mr, - IOMMUNotifier *n) +int memory_region_register_iommu_notifier(MemoryRegion *mr, + IOMMUNotifier *n, Error **errp) { IOMMUMemoryRegion *iommu_mr; + int ret; =20 if (mr->alias) { - memory_region_register_iommu_notifier(mr->alias, n); - return; + return memory_region_register_iommu_notifier(mr->alias, n, errp); } =20 /* We need to register for at least one bitfield */ @@ -1874,7 +1879,11 @@ void memory_region_register_iommu_notifier(MemoryReg= ion *mr, n->iommu_idx < memory_region_iommu_num_indexes(iommu_mr)); =20 QLIST_INSERT_HEAD(&iommu_mr->iommu_notify, n, node); - memory_region_update_iommu_notify_flags(iommu_mr); + ret =3D memory_region_update_iommu_notify_flags(iommu_mr, errp); + if (ret) { + QLIST_REMOVE(n, node); + } + return ret; } =20 uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr) @@ -1927,7 +1936,7 @@ void memory_region_unregister_iommu_notifier(MemoryRe= gion *mr, } QLIST_REMOVE(n, node); iommu_mr =3D IOMMU_MEMORY_REGION(mr); - memory_region_update_iommu_notify_flags(iommu_mr); + memory_region_update_iommu_notify_flags(iommu_mr, NULL); } =20 void memory_region_notify_one(IOMMUNotifier *notifier, --=20 2.20.1