{"id":2229559,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2229559/?format=json","web_url":"http://patchwork.ozlabs.org/project/kvm-riscv/patch/20260428131359.34872-9-fangyu.yu@linux.alibaba.com/","project":{"id":70,"url":"http://patchwork.ozlabs.org/api/1.1/projects/70/?format=json","name":"Linux KVM RISC-V","link_name":"kvm-riscv","list_id":"kvm-riscv.lists.infradead.org","list_email":"kvm-riscv@lists.infradead.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20260428131359.34872-9-fangyu.yu@linux.alibaba.com>","date":"2026-04-28T13:13:56","name":"[RFC,08/11] iommu/riscv: Add dirty tracking support for second-stage domains","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"5d91f7de53f9a6d600ead9b9a308167db16ea2e5","submitter":{"id":91416,"url":"http://patchwork.ozlabs.org/api/1.1/people/91416/?format=json","name":null,"email":"fangyu.yu@linux.alibaba.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/kvm-riscv/patch/20260428131359.34872-9-fangyu.yu@linux.alibaba.com/mbox/","series":[{"id":501850,"url":"http://patchwork.ozlabs.org/api/1.1/series/501850/?format=json","web_url":"http://patchwork.ozlabs.org/project/kvm-riscv/list/?series=501850","date":"2026-04-28T13:13:48","name":"iommu/riscv: Add hardware dirty tracking for second-stage domains","version":1,"mbox":"http://patchwork.ozlabs.org/series/501850/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2229559/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2229559/checks/","tags":{},"headers":{"Return-Path":"\n <kvm-riscv-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n secure) header.d=lists.infradead.org header.i=@lists.infradead.org\n header.a=rsa-sha256 header.s=bombadil.20210309 header.b=XG+Qz0Qr;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=linux.alibaba.com header.i=@linux.alibaba.com\n header.a=rsa-sha256 header.s=default header.b=WZA/DBBi;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=none (no SPF record) smtp.mailfrom=lists.infradead.org\n (client-ip=2607:7c80:54:3::133; helo=bombadil.infradead.org;\n envelope-from=kvm-riscv-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from bombadil.infradead.org (bombadil.infradead.org\n [IPv6:2607:7c80:54:3::133])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g4grd2Jjnz1xrS\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 28 Apr 2026 23:14:41 +1000 (AEST)","from localhost ([::1] helo=bombadil.infradead.org)\n\tby bombadil.infradead.org with esmtp (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1wHiGt-00000001VAW-1mGs;\n\tTue, 28 Apr 2026 13:14:39 +0000","from out30-111.freemail.mail.aliyun.com ([115.124.30.111])\n\tby bombadil.infradead.org with esmtps (Exim 4.98.2 #2 (Red Hat Linux))\n\tid 1wHiGo-00000001V3A-2QuB;\n\tTue, 28 Apr 2026 13:14:36 +0000","from localhost.localdomain(mailfrom:fangyu.yu@linux.alibaba.com\n fp:SMTPD_---0X1ubIGy_1777382066 cluster:ay36)\n          by smtp.aliyun-inc.com;\n          Tue, 28 Apr 2026 21:14:27 +0800"],"DKIM-Signature":["v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;\n\td=lists.infradead.org; s=bombadil.20210309; h=Sender:\n\tContent-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post:\n\tList-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:\n\tMessage-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:\n\tResent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:\n\tList-Owner; bh=txeYxQPZHPvX+nSzFdRIU6eolWGf8A8JjAszKx22ze8=; b=XG+Qz0QrvR4moF\n\tdZ08Vq6aXpZWVUDnhvO0cyNm1tWgqEEzc4tr9uxt1YxX2uuziM/DGUU0ZVPAkGVatkRlGnGhqis1F\n\tuA9320eqxCgKB1LcKdaxZnjupHFI8DKmhq3KVCwhhmHoWoZS1XgoMN/Q7iO7Cy3rHC7tmZZq1/L5l\n\tvIWWivjDEkkqXfABaZvrjqk2ytUOFnsreWc9umG5O9x2MIlZWVOt4KhSskQOjLKt5bV1HJxUh5BI4\n\tpspWbZP+hBX6Ca3sYG/1C3mzFEOk/h99UlRggiuuKsn2ZwUhxRwdNgaO5ZVkCtrkzeqRf1YMGb7EQ\n\tTayC5b22n1QY4YJfko6Q==;","v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=linux.alibaba.com; s=default;\n\tt=1777382072; h=From:To:Subject:Date:Message-Id:MIME-Version;\n\tbh=wDviUyznucLdHZjKk0KKSvorH0J1X46CC4BtnY6yTUA=;\n\tb=WZA/DBBixqgFm2LEsELE+O04ozNxRXmWrrra05ecv84KtS+ggUBzHH2oS4hW5zyvIP2Wr2M3/SwKGeOqsmm7+vXrdIRe9L5FEp7V2BHezyWJWvDLtR4M0X7ewVYL8/WbJ+XwZYRjQd5fdzaous+7z2On/TwIoFvDXdAj3gtPX84="],"X-Alimail-AntiSpam":"\n AC=PASS;BC=-1|-1;BR=01201311R121e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=maildocker-contentspam033045098064;MF=fangyu.yu@linux.alibaba.com;NM=1;PH=DS;RN=23;SR=0;TI=SMTPD_---0X1ubIGy_1777382066;","From":"fangyu.yu@linux.alibaba.com","To":"joro@8bytes.org,\n\twill@kernel.org,\n\trobin.murphy@arm.com,\n\tpjw@kernel.org,\n\tpalmer@dabbelt.com,\n\taou@eecs.berkeley.edu,\n\talex@ghiti.fr,\n\ttjeznach@rivosinc.com,\n\tjgg@ziepe.ca,\n\tkevin.tian@intel.com,\n\tbaolu.lu@linux.intel.com,\n\tvasant.hegde@amd.com,\n\tanup@brainfault.org,\n\tatish.patra@linux.dev,\n\tskhawaja@google.com,\n\tjgg@nvidia.com","Cc":"guoren@kernel.org,\n\tkvm@vger.kernel.org,\n\tiommu@lists.linux.dev,\n\tkvm-riscv@lists.infradead.org,\n\tlinux-riscv@lists.infradead.org,\n\tlinux-kernel@vger.kernel.org,\n\tFangyu Yu <fangyu.yu@linux.alibaba.com>","Subject":"[RFC PATCH 08/11] iommu/riscv: Add dirty tracking support for\n second-stage domains","Date":"Tue, 28 Apr 2026 21:13:56 +0800","Message-Id":"<20260428131359.34872-9-fangyu.yu@linux.alibaba.com>","X-Mailer":"git-send-email 2.39.3 (Apple Git-146)","In-Reply-To":"<20260428131359.34872-1-fangyu.yu@linux.alibaba.com>","References":"<20260428131359.34872-1-fangyu.yu@linux.alibaba.com>","MIME-Version":"1.0","X-CRM114-Version":"20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 ","X-CRM114-CacheID":"sfid-20260428_061434_968039_7795DEE5 ","X-CRM114-Status":"GOOD (  15.14  )","X-Spam-Score":"-17.6 (-----------------)","X-Spam-Report":"Spam detection software,\n running on the system \"bombadil.infradead.org\",\n has NOT identified this incoming email as spam.  The original\n message has been attached to this so you can view it or label\n similar future email.  If you have any questions, see\n the administrator of that system for details.\n Content preview:  From: Fangyu Yu <fangyu.yu@linux.alibaba.com> Add hardware\n    dirty tracking support for second-stage (iohgatp) domains used in KVM VFIO\n    device pass-through. The RISC-V IOMMU can automatically set the dirty bit\n    in PTEs on write access when DC.tc.GADE is set and the hardware has\n AMO_HWAD\n    capability. Wire this up to the iommufd dirty tracking interface:\n Content analysis details:   (-17.6 points, 5.0 required)\n  pts rule name              description\n ---- ----------------------\n --------------------------------------------------\n -0.0 RCVD_IN_DNSWL_NONE     RBL: Sender listed at https://www.dnswl.org/, no\n                             trust\n                             [115.124.30.111 listed in list.dnswl.org]\n -7.5 USER_IN_DEF_SPF_WL     From: address is in the default SPF welcome-list\n  0.0 SPF_HELO_NONE          SPF: HELO does not publish an SPF Record\n -0.0 SPF_PASS               SPF: sender matches SPF record\n -7.5 USER_IN_DEF_DKIM_WL    From: address is in the default DKIM welcome-list\n -0.1 DKIM_VALID_EF          Message has a valid DKIM or DK signature from\n                             envelope-from domain\n  0.1 DKIM_SIGNED            Message has a DKIM or DK signature,\n not necessarily valid\n -0.1 DKIM_VALID             Message has at least one valid DKIM or DK\n signature\n -0.1 DKIM_VALID_AU          Message has a valid DKIM or DK signature from\n author's\n                             domain\n -1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%\n                             [score: 0.0000]\n  0.0 UNPARSEABLE_RELAY      Informational: message has unparseable relay\n lines\n -0.5 ENV_AND_HDR_SPF_MATCH  Env and Hdr From used in default SPF WL Match","X-BeenThere":"kvm-riscv@lists.infradead.org","X-Mailman-Version":"2.1.34","Precedence":"list","List-Id":"<kvm-riscv.lists.infradead.org>","List-Unsubscribe":"<http://lists.infradead.org/mailman/options/kvm-riscv>,\n <mailto:kvm-riscv-request@lists.infradead.org?subject=unsubscribe>","List-Archive":"<http://lists.infradead.org/pipermail/kvm-riscv/>","List-Post":"<mailto:kvm-riscv@lists.infradead.org>","List-Help":"<mailto:kvm-riscv-request@lists.infradead.org?subject=help>","List-Subscribe":"<http://lists.infradead.org/mailman/listinfo/kvm-riscv>,\n <mailto:kvm-riscv-request@lists.infradead.org?subject=subscribe>","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Sender":"\"kvm-riscv\" <kvm-riscv-bounces@lists.infradead.org>","Errors-To":"kvm-riscv-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org"},"content":"From: Fangyu Yu <fangyu.yu@linux.alibaba.com>\n\nAdd hardware dirty tracking support for second-stage (iohgatp) domains\nused in KVM VFIO device pass-through.\n\nThe RISC-V IOMMU can automatically set the dirty bit in PTEs on write\naccess when DC.tc.GADE is set and the hardware has AMO_HWAD capability.\nWire this up to the iommufd dirty tracking interface:\n\n  - riscv_iommu_set_dirty_tracking(): Walks all bonds of the domain and\n    sets or clears DC.tc.GADE in each device context entry.\n\n  - riscv_iommu_dirty_ops: Exposes set_dirty_tracking and the generic\n    page-table read_and_clear_dirty via IOMMU_PT_DIRTY_OPS(riscv_64).\n\n  - domain_alloc_paging_flags: Assigns dirty_ops to second-stage domains\n    when AMO_HWAD is advertised in hardware capabilities.\n\n  - riscv_iommu_capable: Reports IOMMU_CAP_DIRTY_TRACKING when\n    AMO_HWAD is present.\n\nSigned-off-by: Fangyu Yu <fangyu.yu@linux.alibaba.com>\n---\n drivers/iommu/riscv/iommu.c | 84 +++++++++++++++++++++++++++++++++++++\n 1 file changed, 84 insertions(+)","diff":"diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c\nindex 0c13430ecc7f..1f7967074492 100644\n--- a/drivers/iommu/riscv/iommu.c\n+++ b/drivers/iommu/riscv/iommu.c\n@@ -1247,6 +1247,84 @@ static int riscv_iommu_attach_paging_domain(struct iommu_domain *iommu_domain,\n \treturn 0;\n }\n \n+/*\n+ * Enable or disable hardware A/D bit updates (GADE) in the device context for\n+ * all devices attached to a second-stage domain. When dirty tracking is\n+ * enabled the IOMMU hardware will set the dirty bit in PTEs on write access,\n+ * making them visible to read_and_clear_dirty().\n+ */\n+static int riscv_iommu_set_dirty_tracking(struct iommu_domain *iommu_domain,\n+\t\t\t\t\t  bool enable)\n+{\n+\tstruct riscv_iommu_domain *domain = iommu_domain_to_riscv(iommu_domain);\n+\tstruct riscv_iommu_bond *bond;\n+\tstruct riscv_iommu_device *iommu, *prev;\n+\tstruct riscv_iommu_dc *dc;\n+\tstruct iommu_fwspec *fwspec;\n+\tstruct riscv_iommu_command cmd;\n+\tu64 tc;\n+\tint i;\n+\n+\trcu_read_lock();\n+\n+\tlist_for_each_entry_rcu(bond, &domain->bonds, list) {\n+\t\tiommu = dev_to_iommu(bond->dev);\n+\t\tfwspec = dev_iommu_fwspec_get(bond->dev);\n+\n+\t\tfor (i = 0; i < fwspec->num_ids; i++) {\n+\t\t\tdc = riscv_iommu_get_dc(iommu, fwspec->ids[i]);\n+\t\t\ttc = READ_ONCE(dc->tc);\n+\t\t\tif (!(tc & RISCV_IOMMU_DC_TC_V))\n+\t\t\t\tcontinue;\n+\n+\t\t\tif (enable)\n+\t\t\t\ttc |= RISCV_IOMMU_DC_TC_GADE;\n+\t\t\telse\n+\t\t\t\ttc &= ~RISCV_IOMMU_DC_TC_GADE;\n+\t\t\tWRITE_ONCE(dc->tc, tc);\n+\n+\t\t\t/* Invalidate cached device context entry */\n+\t\t\triscv_iommu_cmd_iodir_inval_ddt(&cmd);\n+\t\t\triscv_iommu_cmd_iodir_set_did(&cmd, fwspec->ids[i]);\n+\t\t\triscv_iommu_cmd_send(iommu, &cmd);\n+\t\t\triscv_iommu_iodir_iotinval(iommu, false, dc->iohgatp, dc, NULL);\n+\t\t}\n+\t}\n+\n+\tprev = NULL;\n+\tlist_for_each_entry_rcu(bond, &domain->bonds, list) {\n+\t\tiommu = dev_to_iommu(bond->dev);\n+\t\tif (iommu == prev)\n+\t\t\tcontinue;\n+\n+\t\triscv_iommu_cmd_sync(iommu, RISCV_IOMMU_IOTINVAL_TIMEOUT);\n+\t\tprev = iommu;\n+\t}\n+\n+\trcu_read_unlock();\n+\n+\t/*\n+\t * Reflect the active dirty-tracking state in the page table feature\n+\t * flags.  When active, riscvpt_iommu_set_prot() will leave D=0 in\n+\t * new mappings so that the hardware can set it on the first write,\n+\t * providing accurate per-page dirty information.  When inactive,\n+\t * new mappings get D=1 to avoid write faults on a D=0 PTE.\n+\t */\n+\tif (enable)\n+\t\tdomain->riscvpt.riscv_64pt.common.features |=\n+\t\t\tBIT(PT_FEAT_RISCV_DIRTY_TRACKING_ACTIVE);\n+\telse\n+\t\tdomain->riscvpt.riscv_64pt.common.features &=\n+\t\t\t~BIT(PT_FEAT_RISCV_DIRTY_TRACKING_ACTIVE);\n+\n+\treturn 0;\n+}\n+\n+static const struct iommu_dirty_ops riscv_iommu_dirty_ops = {\n+\tIOMMU_PT_DIRTY_OPS(riscv_64),\n+\t.set_dirty_tracking = riscv_iommu_set_dirty_tracking,\n+};\n+\n static const struct iommu_domain_ops riscv_iommu_paging_domain_ops = {\n \tIOMMU_PT_DOMAIN_OPS(riscv_64),\n \t.attach_dev = riscv_iommu_attach_paging_domain,\n@@ -1325,6 +1403,8 @@ static struct iommu_domain *riscv_iommu_domain_alloc_paging_flags(\n \t\t\triscv_iommu_free_paging_domain(&domain->domain);\n \t\t\treturn ERR_PTR(-ENOMEM);\n \t\t}\n+\t\tif (iommu->caps & RISCV_IOMMU_CAPABILITIES_AMO_HWAD)\n+\t\t\tdomain->domain.dirty_ops = &riscv_iommu_dirty_ops;\n \t} else {\n \t\tdomain->pscid = ida_alloc_range(&riscv_iommu_pscids, 1,\n \t\t\t\t\t\tRISCV_IOMMU_MAX_PSCID, GFP_KERNEL);\n@@ -1401,10 +1481,14 @@ static struct iommu_group *riscv_iommu_device_group(struct device *dev)\n \n static bool riscv_iommu_capable(struct device *dev, enum iommu_cap cap)\n {\n+\tstruct riscv_iommu_device *iommu = dev_to_iommu(dev);\n+\n \tswitch (cap) {\n \tcase IOMMU_CAP_CACHE_COHERENCY:\n \tcase IOMMU_CAP_DEFERRED_FLUSH:\n \t\treturn true;\n+\tcase IOMMU_CAP_DIRTY_TRACKING:\n+\t\treturn !!(iommu->caps & RISCV_IOMMU_CAPABILITIES_AMO_HWAD);\n \tdefault:\n \t\treturn false;\n \t}\n","prefixes":["RFC","08/11"]}