From nobody Mon Feb 9 22:20:05 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1768297223; cv=none; d=zohomail.com; s=zohoarc; b=DSL054wmppeB81woWpKxMs0Gg3t6c2EPnxY2bHZzk/v7y8BZNaJwrCIk8nRt0RujnTcMt+Ekz0pl9sJZKh0cwV/UBqnLfvq6rcP2XKio4ArIvRlGxgSPCesNR9uYkCUmKNWtpT2Y70iHCitBHtPHjv60tSv5hxA1/aRJz5wTsDc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1768297223; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=3vjfMWroBwbRuDbaxuV3pc5DM8ekaFeG0lGHDNirnPw=; b=Ls/AZAaGqfXhlvm4Wv7MEknJZA0qJHZ5hu880qRz2Da/U8kmYNvA9tSkAWtFXiQUChLcP2owCkuCHHSCFQaxrTYmQwGPUHbU9Cee0exf0yBX85EWmPifPITq/8nMuyyXAg+t3wThUmktODmAv0UiDaEFaFFIOQw4X9Wyi59XF9Q= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1768297223281163.8011972661492; Tue, 13 Jan 2026 01:40:23 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vfarI-0003pG-Mm; Tue, 13 Jan 2026 04:38:43 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vfar0-0003Cm-Qh for qemu-devel@nongnu.org; Tue, 13 Jan 2026 04:38:25 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vfaqz-0003UA-0M for qemu-devel@nongnu.org; Tue, 13 Jan 2026 04:38:22 -0500 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-336-MDk5YS8sMFiC-QDE-tk12Q-1; Tue, 13 Jan 2026 04:38:18 -0500 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5AE1C19560B2; Tue, 13 Jan 2026 09:38:17 +0000 (UTC) Received: from corto.redhat.com (unknown [10.44.32.79]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id BA14230001A8; Tue, 13 Jan 2026 09:38:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768297099; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3vjfMWroBwbRuDbaxuV3pc5DM8ekaFeG0lGHDNirnPw=; b=Aqg7snEIJnnhhdeXODRYUfJILmnFV9pXT7owtkU71g52E0pgbsturTz3da/aTjQkLccYWO uvwKs7nLVObNt4erljRJ85J/hkwUdbzw6MqyULeveWoX/dhj9p077x0x0zBbXIKlPl+tCj 9FVQ29li9j9r3c5DIxT4rbeDs9hSQXQ= X-MC-Unique: MDk5YS8sMFiC-QDE-tk12Q-1 X-Mimecast-MFC-AGG-ID: MDk5YS8sMFiC-QDE-tk12Q_1768297097 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= To: qemu-devel@nongnu.org Cc: Alex Williamson , Zhenzhong Duan , =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Subject: [PULL 33/41] vfio/listener: Bypass readonly region for dirty tracking Date: Tue, 13 Jan 2026 10:36:29 +0100 Message-ID: <20260113093637.1549214-34-clg@redhat.com> In-Reply-To: <20260113093637.1549214-1-clg@redhat.com> References: <20260113093637.1549214-1-clg@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Received-SPF: pass (zohomail.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; Received-SPF: pass (zohomail.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; Received-SPF: pass client-ip=170.10.133.124; envelope-from=clg@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1768297239227158500 From: Zhenzhong Duan When doing dirty tracking or calculating dirty tracking range, readonly regions can be bypassed, because corresponding DMA mappings are readonly and never become dirty. This can optimize dirty tracking a bit for passthrough device. Signed-off-by: Zhenzhong Duan Link: https://lore.kernel.org/qemu-devel/20260106062808.316574-4-zhenzhong.= duan@intel.com Signed-off-by: C=C3=A9dric Le Goater --- hw/vfio/listener.c | 48 ++++++++++++++++++++++++++++++++++---------- hw/vfio/trace-events | 1 + 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/hw/vfio/listener.c b/hw/vfio/listener.c index 813621f22f8b5ec284388f9c5f719525ec5f282c..f193468dee30354ea8c07e9bf2d= 89b4da42ab78a 100644 --- a/hw/vfio/listener.c +++ b/hw/vfio/listener.c @@ -76,8 +76,13 @@ static bool vfio_log_sync_needed(const VFIOContainer *bc= ontainer) return true; } =20 -static bool vfio_listener_skipped_section(MemoryRegionSection *section) +static bool vfio_listener_skipped_section(MemoryRegionSection *section, + bool bypass_ro) { + if (bypass_ro && section->readonly) { + return true; + } + return (!memory_region_is_ram(section->mr) && !memory_region_is_iommu(section->mr)) || memory_region_is_protected(section->mr) || @@ -368,9 +373,9 @@ static bool vfio_known_safe_misalignment(MemoryRegionSe= ction *section) } =20 static bool vfio_listener_valid_section(MemoryRegionSection *section, - const char *name) + bool bypass_ro, const char *name) { - if (vfio_listener_skipped_section(section)) { + if (vfio_listener_skipped_section(section, bypass_ro)) { trace_vfio_listener_region_skip(name, section->offset_within_address_space, section->offset_within_address_space + @@ -497,7 +502,7 @@ void vfio_container_region_add(VFIOContainer *bcontaine= r, int ret; Error *err =3D NULL; =20 - if (!vfio_listener_valid_section(section, "region_add")) { + if (!vfio_listener_valid_section(section, false, "region_add")) { return; } =20 @@ -663,7 +668,7 @@ static void vfio_listener_region_del(MemoryListener *li= stener, int ret; bool try_unmap =3D true; =20 - if (!vfio_listener_valid_section(section, "region_del")) { + if (!vfio_listener_valid_section(section, false, "region_del")) { return; } =20 @@ -722,9 +727,10 @@ static void vfio_listener_region_del(MemoryListener *l= istener, } =20 /* - * Fake an IOTLB entry for identity mapping which is needed by dir= ty - * tracking when switch out of PT domain. In fact, in unmap_bitmap, - * only translated_addr field is used to set dirty bitmap. + * Fake an IOTLB entry for writable identity mapping which is need= ed + * by dirty tracking when switch out of PT domain. In fact, in + * unmap_bitmap, only translated_addr field is used to set dirty + * bitmap. * * Note: When switch into PT domain from DMA domain, the whole IOM= MU * MR is deleted without iotlb, before that happen, we depend on @@ -733,7 +739,8 @@ static void vfio_listener_region_del(MemoryListener *li= stener, * it is triggered during switching to block domain because vtd do= es * not support direct switching from DMA to PT domain. */ - if (global_dirty_tracking && memory_region_is_ram(section->mr)) { + if (global_dirty_tracking && memory_region_is_ram(section->mr) && + !section->readonly) { entry.iova =3D iova; entry.translated_addr =3D iova; iotlb =3D &entry; @@ -841,7 +848,8 @@ static void vfio_dirty_tracking_update(MemoryListener *= listener, container_of(listener, VFIODirtyRangesListener, listener); hwaddr iova, end; =20 - if (!vfio_listener_valid_section(section, "tracking_update") || + /* Bypass readonly section as it never becomes dirty */ + if (!vfio_listener_valid_section(section, true, "tracking_update") || !vfio_get_section_iova_range(dirty->bcontainer, section, &iova, &end, NULL)) { return; @@ -1100,6 +1108,19 @@ static void vfio_iommu_map_dirty_notify(IOMMUNotifie= r *n, IOMMUTLBEntry *iotlb) if (!mr) { goto out_unlock; } + + /* + * The mapping is readonly when either it's a readonly mapping in guest + * or mapped target is readonly, bypass it for dirty tracking as it + * never becomes dirty. + */ + if (!(iotlb->perm & IOMMU_WO) || mr->readonly) { + trace_vfio_iommu_map_dirty_notify_skip_ro(iova, + iova + iotlb->addr_mask); + rcu_read_unlock(); + return; + } + translated_addr =3D memory_region_get_ram_addr(mr) + xlat; =20 ret =3D vfio_container_query_dirty_bitmap(bcontainer, iova, iotlb->add= r_mask + 1, @@ -1235,7 +1256,12 @@ static void vfio_listener_log_sync(MemoryListener *l= istener, int ret; Error *local_err =3D NULL; =20 - if (vfio_listener_skipped_section(section)) { + /* + * Bypass readonly section as it never becomes dirty, iommu memory sec= tion + * is RW and never bypassed. The readonly mappings in iommu MR are byp= assed + * in vfio_iommu_map_dirty_notify(). + */ + if (vfio_listener_skipped_section(section, true)) { return; } =20 diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events index 3c62bab7647a7d027038444fa4b164182d3feb2b..180e3d526b80bd43d18bbfb9332= 833df4fbeb720 100644 --- a/hw/vfio/trace-events +++ b/hw/vfio/trace-events @@ -103,6 +103,7 @@ vfio_listener_region_del(uint64_t start, uint64_t end) = "region_del 0x%"PRIx64" - vfio_device_dirty_tracking_update(uint64_t start, uint64_t end, uint64_t m= in, uint64_t max) "section 0x%"PRIx64" - 0x%"PRIx64" -> update [0x%"PRIx64"= - 0x%"PRIx64"]" vfio_device_dirty_tracking_start(int nr_ranges, uint64_t min32, uint64_t m= ax32, uint64_t min64, uint64_t max64, uint64_t minpci, uint64_t maxpci) "nr= _ranges %d 32:[0x%"PRIx64" - 0x%"PRIx64"], 64:[0x%"PRIx64" - 0x%"PRIx64"], = pci64:[0x%"PRIx64" - 0x%"PRIx64"]" vfio_iommu_map_dirty_notify(uint64_t iova_start, uint64_t iova_end) "iommu= dirty @ 0x%"PRIx64" - 0x%"PRIx64 +vfio_iommu_map_dirty_notify_skip_ro(uint64_t iova_start, uint64_t iova_end= ) "iommu dirty @ 0x%"PRIx64" - 0x%"PRIx64 =20 # container.c vfio_container_query_dirty_bitmap(uint64_t iova, uint64_t size, uint64_t b= ackend_flag, uint64_t bitmap_size, uint64_t translated_addr, uint64_t dirty= _pages) "iova=3D0x%"PRIx64" size=3D0x%"PRIx64" backend_flag=3D0x%"PRIx64" b= itmap_size=3D0x%"PRIx64" gpa=3D0x%"PRIx64" dirty_pages=3D%"PRIu64 --=20 2.52.0