From nobody Tue Feb 10 04:53:53 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.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 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518163189270146.67578596214014; Thu, 8 Feb 2018 23:59:49 -0800 (PST) Received: from localhost ([::1]:44693 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ek3b2-0005a4-I7 for importer@patchew.org; Fri, 09 Feb 2018 02:59:48 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47308) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ek3Wg-0002E6-Se for qemu-devel@nongnu.org; Fri, 09 Feb 2018 02:55:20 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ek3Wf-0004q5-NB for qemu-devel@nongnu.org; Fri, 09 Feb 2018 02:55:18 -0500 Received: from ozlabs.ru ([107.173.13.209]:57956) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ek3Wf-0004oz-D6; Fri, 09 Feb 2018 02:55:17 -0500 Received: from vpl1.ozlabs.ibm.com (localhost [IPv6:::1]) by ozlabs.ru (Postfix) with ESMTP id E09DA3A60047; Fri, 9 Feb 2018 02:55:16 -0500 (EST) From: Alexey Kardashevskiy To: qemu-devel@nongnu.org Date: Fri, 9 Feb 2018 18:55:01 +1100 Message-Id: <20180209075503.16996-3-aik@ozlabs.ru> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20180209075503.16996-1-aik@ozlabs.ru> References: <20180209075503.16996-1-aik@ozlabs.ru> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 107.173.13.209 Subject: [Qemu-devel] [PATCH qemu v7 2/4] vfio/pci: Relax DMA map errors for MMIO regions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alexey Kardashevskiy , Alex Williamson , qemu-ppc@nongnu.org, David Gibson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" At the moment if vfio_memory_listener is registered in the system memory address space, it maps/unmaps every RAM memory region for DMA. It expects system page size aligned memory sections so vfio_dma_map would not fail and so far this has been the case. A mapping failure would be fatal. A side effect of such behavior is that some MMIO pages would not be mapped silently. However we are going to change MSIX BAR handling so we will end having non-aligned sections in vfio_memory_listener (more details is in the next patch) and vfio_dma_map will exit QEMU. In order to avoid fatal failures on what previously was not a failure and was just silently ignored, this checks the section alignment to the smallest supported IOMMU page size and prints an error if not aligned; it also prints an error if vfio_dma_map failed despite the page size check. Both errors are not fatal; only MMIO RAM regions are checked (aka "RAM device" regions). If the amount of errors printed is overwhelming, the MSIX relocation could be used to avoid excessive error output. This is unlikely to cause any behavioral change. Signed-off-by: Alexey Kardashevskiy --- hw/vfio/common.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++---= --- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index f895e3c..736f271 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -544,18 +544,40 @@ static void vfio_listener_region_add(MemoryListener *= listener, =20 llsize =3D int128_sub(llend, int128_make64(iova)); =20 + if (memory_region_is_ram_device(section->mr)) { + hwaddr pgmask =3D (1ULL << ctz64(hostwin->iova_pgsizes)) - 1; + + if ((iova & pgmask) || (llsize & pgmask)) { + error_report("Region 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx + " is not aligned to 0x%"HWADDR_PRIx + " and cannot be mapped for DMA", + section->offset_within_region, + int128_getlo(section->size), + pgmask + 1); + return; + } + } + 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); + if (memory_region_is_ram_device(section->mr)) { + /* Allow unexpected mappings not to be fatal for RAM devices */ + return; + } goto fail; } =20 return; =20 fail: + if (memory_region_is_ram_device(section->mr)) { + error_report("failed to vfio_dma_map. pci p2p may not work"); + return; + } /* * On the initfn path, store the first error in the container so we * can gracefully fail. Runtime, there's not much we can do other @@ -577,6 +599,7 @@ static void vfio_listener_region_del(MemoryListener *li= stener, hwaddr iova, end; Int128 llend, llsize; int ret; + bool try_unmap =3D true; =20 if (vfio_listener_skipped_section(section)) { trace_vfio_listener_region_del_skip( @@ -629,13 +652,33 @@ static void vfio_listener_region_del(MemoryListener *= listener, =20 trace_vfio_listener_region_del(iova, end); =20 - ret =3D vfio_dma_unmap(container, iova, int128_get64(llsize)); + if (memory_region_is_ram_device(section->mr)) { + hwaddr pgmask; + VFIOHostDMAWindow *hostwin; + bool hostwin_found =3D false; + + QLIST_FOREACH(hostwin, &container->hostwin_list, hostwin_next) { + if (hostwin->min_iova <=3D iova && end <=3D hostwin->max_iova)= { + hostwin_found =3D true; + break; + } + } + assert(hostwin_found); /* or region_add() would have failed */ + + pgmask =3D (1ULL << ctz64(hostwin->iova_pgsizes)) - 1; + try_unmap =3D !((iova & pgmask) || (llsize & pgmask)); + } + + if (try_unmap) { + ret =3D vfio_dma_unmap(container, iova, int128_get64(llsize)); + if (ret) { + error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", " + "0x%"HWADDR_PRIx") =3D %d (%m)", + container, iova, int128_get64(llsize), ret); + } + } + memory_region_unref(section->mr); - if (ret) { - error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", " - "0x%"HWADDR_PRIx") =3D %d (%m)", - container, iova, int128_get64(llsize), ret); - } =20 if (container->iommu_type =3D=3D VFIO_SPAPR_TCE_v2_IOMMU) { vfio_spapr_remove_window(container, --=20 2.11.0