From nobody Mon Feb 9 07:55:29 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.zoho.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 1487364153779200.5332984578822; Fri, 17 Feb 2017 12:42:33 -0800 (PST) Received: from localhost ([::1]:55796 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cepMN-0005hi-B5 for importer@patchew.org; Fri, 17 Feb 2017 15:42:31 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44427) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ceocI-0004Tp-Q4 for qemu-devel@nongnu.org; Fri, 17 Feb 2017 14:54:56 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ceocF-0005rs-5Z for qemu-devel@nongnu.org; Fri, 17 Feb 2017 14:54:54 -0500 Received: from mail.kernel.org ([198.145.29.136]:34578) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ceocE-0005rE-Mu for qemu-devel@nongnu.org; Fri, 17 Feb 2017 14:54:50 -0500 Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9AA4920221; Fri, 17 Feb 2017 19:54:48 +0000 (UTC) Received: from redhat.com (pool-96-237-235-121.bstnma.fios.verizon.net [96.237.235.121]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 22BE120220; Fri, 17 Feb 2017 19:54:47 +0000 (UTC) Date: Fri, 17 Feb 2017 21:54:46 +0200 From: "Michael S. Tsirkin" To: qemu-devel@nongnu.org Message-ID: <1487361200-29966-17-git-send-email-mst@redhat.com> References: <1487361200-29966-1-git-send-email-mst@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <1487361200-29966-1-git-send-email-mst@redhat.com> X-Mailer: git-send-email 2.8.0.287.g0deeb61 X-Mutt-Fcc: =sent X-Virus-Scanned: ClamAV using ClamSMTP X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 198.145.29.136 Subject: [Qemu-devel] [PULL 16/23] vfio: introduce vfio_get_vaddr() 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: Peter Maydell , Alex Williamson , Peter Xu , 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 Content-Type: text/plain; charset="utf-8" From: Peter Xu A cleanup for vfio_iommu_map_notify(). Now we will fetch vaddr even if the operation is unmap, but it won't hurt much. One thing to mention is that we need the RCU read lock to protect the whole translation and map/unmap procedure. Acked-by: Alex Williamson Reviewed-by: David Gibson Signed-off-by: Peter Xu Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/vfio/common.c | 65 +++++++++++++++++++++++++++++++++++++++-------------= ---- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 174f351..42c4790 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -294,54 +294,79 @@ static bool vfio_listener_skipped_section(MemoryRegio= nSection *section) section->offset_within_address_space & (1ULL << 63); } =20 -static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) +/* Called with rcu_read_lock held. */ +static bool vfio_get_vaddr(IOMMUTLBEntry *iotlb, void **vaddr, + bool *read_only) { - VFIOGuestIOMMU *giommu =3D container_of(n, VFIOGuestIOMMU, n); - VFIOContainer *container =3D giommu->container; - hwaddr iova =3D iotlb->iova + giommu->iommu_offset; MemoryRegion *mr; hwaddr xlat; hwaddr len =3D iotlb->addr_mask + 1; - void *vaddr; - int ret; - - trace_vfio_iommu_map_notify(iotlb->perm =3D=3D IOMMU_NONE ? "UNMAP" : = "MAP", - iova, iova + iotlb->addr_mask); - - if (iotlb->target_as !=3D &address_space_memory) { - error_report("Wrong target AS \"%s\", only system memory is allowe= d", - iotlb->target_as->name ? iotlb->target_as->name : "no= ne"); - return; - } + bool writable =3D iotlb->perm & IOMMU_WO; =20 /* * The IOMMU TLB entry we have just covers translation through * this IOMMU to its immediate target. We need to translate * it the rest of the way through to memory. */ - rcu_read_lock(); mr =3D address_space_translate(&address_space_memory, iotlb->translated_addr, - &xlat, &len, iotlb->perm & IOMMU_WO); + &xlat, &len, writable); if (!memory_region_is_ram(mr)) { error_report("iommu map to non memory area %"HWADDR_PRIx"", xlat); - goto out; + return false; } + /* * Translation truncates length to the IOMMU page size, * check that it did not truncate too much. */ if (len & iotlb->addr_mask) { error_report("iommu has granularity incompatible with target AS"); + return false; + } + + *vaddr =3D memory_region_get_ram_ptr(mr) + xlat; + *read_only =3D !writable || mr->readonly; + + return true; +} + +static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) +{ + VFIOGuestIOMMU *giommu =3D container_of(n, VFIOGuestIOMMU, n); + VFIOContainer *container =3D giommu->container; + hwaddr iova =3D iotlb->iova + giommu->iommu_offset; + bool read_only; + void *vaddr; + int ret; + + trace_vfio_iommu_map_notify(iotlb->perm =3D=3D IOMMU_NONE ? "UNMAP" : = "MAP", + iova, iova + iotlb->addr_mask); + + if (iotlb->target_as !=3D &address_space_memory) { + error_report("Wrong target AS \"%s\", only system memory is allowe= d", + iotlb->target_as->name ? iotlb->target_as->name : "no= ne"); + return; + } + + rcu_read_lock(); + + if (!vfio_get_vaddr(iotlb, &vaddr, &read_only)) { goto out; } =20 if ((iotlb->perm & IOMMU_RW) !=3D IOMMU_NONE) { - vaddr =3D memory_region_get_ram_ptr(mr) + xlat; + /* + * vaddr is only valid until rcu_read_unlock(). But after + * vfio_dma_map has set up the mapping the pages will be + * pinned by the kernel. This makes sure that the RAM backend + * of vaddr will always be there, even if the memory object is + * destroyed and its backing memory munmap-ed. + */ ret =3D vfio_dma_map(container, iova, iotlb->addr_mask + 1, vaddr, - !(iotlb->perm & IOMMU_WO) || mr->readonly); + read_only); if (ret) { error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", " "0x%"HWADDR_PRIx", %p) =3D %d (%m)", --=20 MST