From nobody Tue Sep 29 07:39:38 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D37193A5435 for ; Mon, 10 Aug 2026 20:51:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786395114; cv=none; b=KEw6dX04Roc1k3DNzaFLzbe0JKoQZjsZB5CtI2MqSid+uFuXVz3t/R5TOrS14dt7clrpG5w0rardPA0XE0+83UCxJpq7gM0X6XIVhorDycXjoBHouO48vFdPxXNrmdzSPsni6LBY8llvQ2iw57VdzmcFp1QO4q/5ZKT/3b4+u+g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786395114; c=relaxed/simple; bh=C0zHuUit0QjMQm3WjT5g8a9NFp/o3ACfm47H8bW7/Mc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=j12GoA2k5IZW5eWKeHNLZrhwgAK4HtqFpf3paEAvogUwihnCrz4ThuNMosrNGvydeIYdwbPnmDsmWsr5tIVEzJ07LcVmjCrmvhjJGlJqZO0YiCaVdCPDvekHrpz6xCnE7k/LLKE+yf+WiKxJixhudFY4XSYUGGbKfK9K7AWMjww= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=QD2mj78W; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="QD2mj78W" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 655151516; Mon, 10 Aug 2026 13:51:47 -0700 (PDT) Received: from workstation-e142269.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 71D013F673; Mon, 10 Aug 2026 13:51:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1786395111; bh=C0zHuUit0QjMQm3WjT5g8a9NFp/o3ACfm47H8bW7/Mc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QD2mj78WiGj/48zY4GzWuaWWCWaV92sp0DCEPhZF28BxAEJYhCyQ+KSpfbpQ10Irg JLINt+a/QbOQwSqL06eh8CEK8rwBOj+b/bypHuQTKzdCvhT3NL7qJ5BLi0Mojh4NCp qYxeYcYlg8wFekgRHjG/bXNaU8Co4CmAQGlP546I= From: Wei-Lin Chang To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org Cc: Marc Zyngier , Oliver Upton , Fuad Tabba , Joey Gouly , Steffen Eiden , Suzuki K Poulose , Zenghui Yu , Catalin Marinas , Will Deacon , Lorenzo Stoakes , Itaru Kitayama , Wei-Lin Chang Subject: [PATCH v5 1/6] KVM: arm64: Use a variable for the canonical IPA in kvm_s2_fault_map() Date: Mon, 10 Aug 2026 21:50:33 +0100 Message-ID: <20260810205038.118843-2-weilin.chang@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260810205038.118843-1-weilin.chang@arm.com> References: <20260810205038.118843-1-weilin.chang@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Create a variable to store the canonical IPA, instead of calculating it when needed. This will be useful when we need to use the canonical IPA for guest stage-2 tracking later. Signed-off-by: Wei-Lin Chang Tested-by: Itaru Kitayama Tested-by: Wang Han --- arch/arm64/kvm/mmu.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 6c941aaa10c6..336dd8f7e8ab 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -2021,6 +2021,7 @@ static int kvm_s2_fault_map(const struct kvm_s2_fault= _desc *s2fd, enum kvm_pgtable_walk_flags flags =3D KVM_PGTABLE_WALK_SHARED; bool writable =3D prot & KVM_PGTABLE_PROT_W; struct kvm *kvm =3D s2fd->vcpu->kvm; + phys_addr_t canonical_ipa; struct kvm_pgtable *pgt; long perm_fault_granule; long mapping_size; @@ -2039,6 +2040,7 @@ static int kvm_s2_fault_map(const struct kvm_s2_fault= _desc *s2fd, mapping_size =3D s2vi->vma_pagesize; pfn =3D s2vi->pfn; gfn =3D s2vi->gfn; + canonical_ipa =3D gfn_to_gpa(get_canonical_gfn(s2fd, s2vi)); =20 /* * If we are not forced to use page mapping, check if we are @@ -2057,6 +2059,7 @@ static int kvm_s2_fault_map(const struct kvm_s2_fault= _desc *s2fd, goto out_unlock; } } + canonical_ipa =3D ALIGN_DOWN(canonical_ipa, mapping_size); } =20 if (!perm_fault_granule && !s2vi->map_non_cacheable && kvm_has_mte(kvm)) @@ -2090,11 +2093,9 @@ static int kvm_s2_fault_map(const struct kvm_s2_faul= t_desc *s2fd, * making sure we adjust the canonical IPA if the mapping size has * been updated (via a THP upgrade, for example). */ - if (writable && !ret) { - phys_addr_t ipa =3D gfn_to_gpa(get_canonical_gfn(s2fd, s2vi)); - ipa &=3D ~(mapping_size - 1); - mark_page_dirty_in_slot(kvm, s2fd->memslot, gpa_to_gfn(ipa)); - } + if (writable && !ret) + mark_page_dirty_in_slot(kvm, s2fd->memslot, + gpa_to_gfn(canonical_ipa)); =20 if (ret !=3D -EAGAIN) return ret; --=20 2.43.0 From nobody Tue Sep 29 07:39:38 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id EB3B8440A26 for ; Mon, 10 Aug 2026 20:51:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786395116; cv=none; b=oCJn9CE5XerIykw7QDayFDrxcbpg752Kv8Wmp3Eee2tg2ef/3sgsk/6B8qocHvwLeLgGlQRUbFOOxZAQrhjc+9ptzNF/9aLkcfaTAsMVLm0n8CC9+71MGB/oHO3p0fsNlwqJQdTu4KMWLJuClauVIOJHs2PTdpLDuKF3wqIcQUE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786395116; c=relaxed/simple; bh=+00wwLx2iD8NqUqVubsawzy5FD696qdsjH5gps6fsU8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pqIjEPPlyk8omMqw5jdKlN8uvucPx+Lgf5i6Lc0ANMmtsqOVJQgqNXWgXVi8ik2i7OKaDShQ7Tde7F4uYOtSjeTZXjFPfwRmLjk8YjiFDTO66PioiQvNHyiqlMbwhF0N1PUw2Eus9bkHD8OYxQWFMIZaNB6EUqCVWO+iSChkLXM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=g34esSVb; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="g34esSVb" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 929A61655; Mon, 10 Aug 2026 13:51:49 -0700 (PDT) Received: from workstation-e142269.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id A27EA3F673; Mon, 10 Aug 2026 13:51:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1786395113; bh=+00wwLx2iD8NqUqVubsawzy5FD696qdsjH5gps6fsU8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=g34esSVbwgvbpFnxNBpR1Me1bmsksw0WYXt0Sq2xiR4AT3vfjPITtqT56LaFKP/RB QKtAiNOmsH1OF4L1utKZU8Q+ej6AIMcG9Exk7XpM2YkOUJmO9IpGxXYpfNcCzf3Mc6 sajgsFgdsiv8DS4sLiamM19Dv6DOy1LCb2CK+QL4= From: Wei-Lin Chang To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org Cc: Marc Zyngier , Oliver Upton , Fuad Tabba , Joey Gouly , Steffen Eiden , Suzuki K Poulose , Zenghui Yu , Catalin Marinas , Will Deacon , Lorenzo Stoakes , Itaru Kitayama , Wei-Lin Chang Subject: [PATCH v5 2/6] KVM: arm64: nv: Introduce guest stage-2 tracking structures Date: Mon, 10 Aug 2026 21:50:34 +0100 Message-ID: <20260810205038.118843-3-weilin.chang@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260810205038.118843-1-weilin.chang@arm.com> References: <20260810205038.118843-1-weilin.chang@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In order to avoid unmapping all shadow stage-2 mappings when KVM receives a MMU notifier unmap call, we have to keep track of the canonical IPA -> nested IPA relationship of the shadow mappings created. This essentially means tracking the guest's stage-2. To do this, represent each mapping by struct kvm_guest_s2_mapping. It stores the mapping's canonical IPA range and the nested IPA range using two interval tree nodes. Both nodes will be inserted into their respective interval trees called guest_s2_mappings. The canonical IPA ranges will be stored in the tree within the canonical MMU, and the nested IPA ranges will be stored in the corresponding nested MMU's tree. For example: struct kvm_guest_s2_mapping mapping1, mapping2; ---------------------> mapping2.canonical | mapping1.canonical | ^ (both stored in canonical mmu's tree) | | --*****-----------------------*****----------- CIPA \\\\\ ||||| mapping1.nested_mmu \\\\\ \\\\\ | \\\\\ \\\\\ v Tested-by: Itaru Kitayama Tested-by: Wang Han ------\\\\\---------------------*****--------- NIPA #1 (nested mmu #1) \\\\\ | \\\\\ -> mapping1.nested \\\\\ (stored in nested mmu #1's tree) \\\\\ -----------*****------------------------------ NIPA #2 (nested mmu #2) | ^ -> mapping2.nested | (stored in nested mmu #2's tree) mapping2.nested_mmu Using the trees we can look up nodes in either of the IPA spaces, and for each node, find the corresponding range in the other IPA space from the other node in the enclosing kvm_guest_s2_mapping. Define kvm_guest_s2_mapping and the interval tree here. Guest stage-2 mapping tracking will come in subsequent patches. Signed-off-by: Wei-Lin Chang --- arch/arm64/include/asm/kvm_host.h | 17 +++++++++++++++++ arch/arm64/kvm/mmu.c | 30 ++++++++++++++++++++++++++++++ arch/arm64/kvm/nested.c | 1 + 3 files changed, 48 insertions(+) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index bae2c4f92ef5..0695c4ef93f1 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -150,6 +151,16 @@ struct kvm_vmid { atomic64_t id; }; =20 +/* + * Record of a guest stage-2 mapping, storing canonical and nested IPA + * ranges. Both ranges have the same size. + */ +struct kvm_guest_s2_mapping { + struct interval_tree_node canonical; + struct interval_tree_node nested; + struct kvm_s2_mmu *nested_mmu; +}; + struct kvm_s2_mmu { struct kvm_vmid vmid; =20 @@ -227,6 +238,9 @@ struct kvm_s2_mmu { */ bool pending_unmap; =20 + /* Guest s2 mapping records indexed in this MMU's IPA space. */ + struct rb_root_cached guest_s2_mappings; + /* * 0: Nobody is currently using this, check vttbr for validity * >0: Somebody is actively using this. @@ -326,6 +340,9 @@ struct kvm_arch { size_t nested_mmus_size; int nested_mmus_next; =20 + /* Guest s2 tracking trees access serialization. */ + spinlock_t guest_s2_tracking_lock; + /* Interrupt controller */ struct vgic_dist vgic; =20 diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 336dd8f7e8ab..59b4f583240e 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -1033,6 +1034,8 @@ int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s= 2_mmu *mmu, unsigned long t =20 mmu->pgd_phys =3D __pa(pgt->pgd); =20 + mmu->guest_s2_mappings =3D RB_ROOT_CACHED; + if (kvm_is_nested_s2_mmu(kvm, mmu)) kvm_init_nested_s2_mmu(mmu); =20 @@ -1122,10 +1125,32 @@ void stage2_unmap_vm(struct kvm *kvm) srcu_read_unlock(&kvm->srcu, idx); } =20 +static void guest_s2_tracking_destroy(struct kvm_s2_mmu *mmu, + struct rb_root_cached *tree) +{ + struct kvm *kvm =3D kvm_s2_mmu_to_kvm(mmu); + struct kvm_guest_s2_mapping *mapping; + struct interval_tree_node *node; + + while ((node =3D interval_tree_iter_first(tree, 0, ULONG_MAX))) { + interval_tree_remove(node, tree); + + if (!kvm_is_nested_s2_mmu(kvm, mmu)) { + mapping =3D container_of(node, struct kvm_guest_s2_mapping, + canonical); + /* The canonical MMU is destroyed after the nested MMUs. */ + kfree(mapping); + } + + cond_resched(); + } +} + void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu) { struct kvm *kvm =3D kvm_s2_mmu_to_kvm(mmu); struct kvm_pgtable *pgt =3D NULL; + struct rb_root_cached mappings_tree; =20 write_lock(&kvm->mmu_lock); pgt =3D mmu->pgt; @@ -1138,12 +1163,17 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu) if (kvm_is_nested_s2_mmu(kvm, mmu)) kvm_init_nested_s2_mmu(mmu); =20 + mappings_tree =3D mmu->guest_s2_mappings; + mmu->guest_s2_mappings =3D RB_ROOT_CACHED; + write_unlock(&kvm->mmu_lock); =20 if (pgt) { kvm_stage2_destroy(pgt); kfree(pgt); } + + guest_s2_tracking_destroy(mmu, &mappings_tree); } =20 static void hyp_mc_free_fn(void *addr, void *mc) diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c index dfb96edbdc43..744aacba61ae 100644 --- a/arch/arm64/kvm/nested.c +++ b/arch/arm64/kvm/nested.c @@ -49,6 +49,7 @@ void kvm_init_nested(struct kvm *kvm) kvm->arch.nested_mmus =3D NULL; kvm->arch.nested_mmus_size =3D 0; atomic_set(&kvm->arch.vncr_map_count, 0); + spin_lock_init(&kvm->arch.guest_s2_tracking_lock); } =20 static int init_nested_s2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu) --=20 2.43.0 From nobody Tue Sep 29 07:39:38 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 28CB7443AA5 for ; Mon, 10 Aug 2026 20:51:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786395118; cv=none; b=FGD21danXB3g9pC+iBwLKL5LQIcK78+QLU9HZ1oQpzvFcMmwX2Wa914j83A4xgfTFelnoArsgHbdw2tySrbGHgUNjLJXo5xB6vZjSSzMGoxLdh+Knu7USAieoxivQRKEQsxQ1Ut5BKgIvLjWf2k83dokHklWAoIxz44hLSsoXNw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786395118; c=relaxed/simple; bh=hN26P/A7fPLce60cNx8etfOGz+xdHCZDDJNeNaHZn5U=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=onbn4dW+m0jHX0Da7dDJyuvSMWl6S3oK8ZXjMtcbrI1ioDgBQ2qoL3PCP93TwLyrtyFZVFOv+3+BnVt8dpgubXzwqTgxM1Y//z9gqFrcgDJVZFutU3cI+C6ZGzB1Wp4B3mm++axKTWNVplCSYlw0brYbg5V9peFJYlML0bBOdYk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=KbEWoXia; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="KbEWoXia" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C44791516; Mon, 10 Aug 2026 13:51:51 -0700 (PDT) Received: from workstation-e142269.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D2BB83F673; Mon, 10 Aug 2026 13:51:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1786395115; bh=hN26P/A7fPLce60cNx8etfOGz+xdHCZDDJNeNaHZn5U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KbEWoXiadmbBfT9ixd2GAFqz9FXrmRXiuqzsMnN8bAxCWDoVW6zt/ngneh3o/bRl/ iiU2+MKQwB7mp2sWun5HX2a8rX4ayUV2qiXc5tjRvFsyMsbsHBT6KPnWdl17LJPWKx 5ZcQ0YdIG1LXmBJVJS1W66ODjqJ+8QjTwdqrxUVs= From: Wei-Lin Chang To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org Cc: Marc Zyngier , Oliver Upton , Fuad Tabba , Joey Gouly , Steffen Eiden , Suzuki K Poulose , Zenghui Yu , Catalin Marinas , Will Deacon , Lorenzo Stoakes , Itaru Kitayama , Wei-Lin Chang Subject: [PATCH v5 3/6] KVM: arm64: nv: Track guest stage-2 mapping creation Date: Mon, 10 Aug 2026 21:50:35 +0100 Message-ID: <20260810205038.118843-4-weilin.chang@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260810205038.118843-1-weilin.chang@arm.com> References: <20260810205038.118843-1-weilin.chang@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" During shadow stage-2 faults, in addition to creating mappings in the shadow page tables, also allocate kvm_guest_s2_mapping objects, record the mapping ranges, and insert them into the canonical and nested mmu's guest_s2_mappings tree. Note that because we allow parallel faulting, the interval trees could store mappings that are not live in the shadow page tables. Storing a superset of the live mappings is fine because we will only over-unmap when we use this information later to do the targeted MMU notifier unmap. Signed-off-by: Wei-Lin Chang Tested-by: Itaru Kitayama Tested-by: Wang Han --- arch/arm64/include/asm/kvm_nested.h | 3 +++ arch/arm64/kvm/mmu.c | 29 +++++++++++++++++++++++++++++ arch/arm64/kvm/nested.c | 25 +++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/arch/arm64/include/asm/kvm_nested.h b/arch/arm64/include/asm/k= vm_nested.h index 012d711034d1..560b78b3f5ff 100644 --- a/arch/arm64/include/asm/kvm_nested.h +++ b/arch/arm64/include/asm/kvm_nested.h @@ -77,6 +77,9 @@ extern void kvm_s2_mmu_iterate_by_vmid(struct kvm *kvm, u= 16 vmid, const union tlbi_info *info, void (*)(struct kvm_s2_mmu *, const union tlbi_info *)); +extern void kvm_record_guest_s2_mapping(struct kvm_s2_mmu *mmu, gpa_t cano= nical_ipa, + gpa_t nested_ipa, size_t map_size, + struct kvm_guest_s2_mapping *mapping); extern void kvm_vcpu_load_hw_mmu(struct kvm_vcpu *vcpu); extern void kvm_vcpu_put_hw_mmu(struct kvm_vcpu *vcpu); =20 diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 59b4f583240e..cea968921041 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -1642,6 +1642,7 @@ static int gmem_abort(const struct kvm_s2_fault_desc = *s2fd) enum kvm_pgtable_walk_flags flags =3D KVM_PGTABLE_WALK_SHARED; enum kvm_pgtable_prot prot =3D KVM_PGTABLE_PROT_R; struct kvm_pgtable *pgt =3D s2fd->vcpu->arch.hw_mmu->pgt; + struct kvm_guest_s2_mapping *mapping =3D NULL; unsigned long mmu_seq; struct page *page; struct kvm *kvm =3D s2fd->vcpu->kvm; @@ -1655,6 +1656,11 @@ static int gmem_abort(const struct kvm_s2_fault_desc= *s2fd) ret =3D topup_mmu_memcache(s2fd->vcpu, memcache); if (ret) return ret; + if (kvm_is_nested_s2_mmu(kvm, pgt->mmu)) { + mapping =3D kmalloc_obj(struct kvm_guest_s2_mapping, GFP_KERNEL_ACCOUNT= ); + if (!mapping) + return -ENOMEM; + } } =20 if (s2fd->nested) @@ -1675,6 +1681,7 @@ static int gmem_abort(const struct kvm_s2_fault_desc = *s2fd) if (ret) { kvm_prepare_memory_fault_exit(s2fd->vcpu, s2fd->fault_ipa, PAGE_SIZE, write_fault, exec_fault, false); + kfree(mapping); return ret; } =20 @@ -1708,11 +1715,17 @@ static int gmem_abort(const struct kvm_s2_fault_des= c *s2fd) ret =3D KVM_PGT_FN(kvm_pgtable_stage2_map)(pgt, s2fd->fault_ipa, PAGE_SI= ZE, __pfn_to_phys(pfn), prot, memcache, flags); + if (!ret && kvm_is_nested_s2_mmu(kvm, pgt->mmu)) { + kvm_record_guest_s2_mapping(pgt->mmu, gfn << PAGE_SHIFT, + s2fd->fault_ipa, PAGE_SIZE, mapping); + mapping =3D NULL; + } } =20 out_unlock: kvm_release_faultin_page(kvm, page, !!ret, prot & KVM_PGTABLE_PROT_W); kvm_fault_unlock(kvm); + kfree(mapping); =20 if ((prot & KVM_PGTABLE_PROT_W) && !ret) mark_page_dirty_in_slot(kvm, s2fd->memslot, gfn); @@ -2049,6 +2062,7 @@ static int kvm_s2_fault_map(const struct kvm_s2_fault= _desc *s2fd, void *memcache) { enum kvm_pgtable_walk_flags flags =3D KVM_PGTABLE_WALK_SHARED; + struct kvm_guest_s2_mapping *mapping =3D NULL; bool writable =3D prot & KVM_PGTABLE_PROT_W; struct kvm *kvm =3D s2fd->vcpu->kvm; phys_addr_t canonical_ipa; @@ -2059,6 +2073,15 @@ static int kvm_s2_fault_map(const struct kvm_s2_faul= t_desc *s2fd, gfn_t gfn; int ret; =20 + if (kvm_is_nested_s2_mmu(kvm, s2fd->vcpu->arch.hw_mmu)) { + mapping =3D kmalloc_obj(struct kvm_guest_s2_mapping, + GFP_KERNEL_ACCOUNT); + if (!mapping) { + kvm_release_page_unused(s2vi->page); + return -ENOMEM; + } + } + kvm_fault_lock(kvm); pgt =3D s2fd->vcpu->arch.hw_mmu->pgt; ret =3D -EAGAIN; @@ -2112,11 +2135,17 @@ static int kvm_s2_fault_map(const struct kvm_s2_fau= lt_desc *s2fd, ret =3D KVM_PGT_FN(kvm_pgtable_stage2_map)(pgt, gfn_to_gpa(gfn), mapping= _size, __pfn_to_phys(pfn), prot, memcache, flags); + if (!ret && kvm_is_nested_s2_mmu(kvm, pgt->mmu)) { + kvm_record_guest_s2_mapping(pgt->mmu, canonical_ipa, + gfn_to_gpa(gfn), mapping_size, mapping); + mapping =3D NULL; + } } =20 out_unlock: kvm_release_faultin_page(kvm, s2vi->page, !!ret, writable); kvm_fault_unlock(kvm); + kfree(mapping); =20 /* * Mark the page dirty only if the fault is handled successfully, diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c index 744aacba61ae..646b628bba17 100644 --- a/arch/arm64/kvm/nested.c +++ b/arch/arm64/kvm/nested.c @@ -5,6 +5,7 @@ */ =20 #include +#include #include #include =20 @@ -852,6 +853,30 @@ static struct kvm_s2_mmu *get_s2_mmu_nested(struct kvm= _vcpu *vcpu) return s2_mmu; } =20 +void kvm_record_guest_s2_mapping(struct kvm_s2_mmu *mmu, gpa_t canonical_i= pa, + gpa_t nested_ipa, size_t map_size, + struct kvm_guest_s2_mapping *mapping) +{ + struct kvm *kvm =3D kvm_s2_mmu_to_kvm(mmu); + + lockdep_assert_held_read(&kvm->mmu_lock); + + if (WARN_ON(!IS_ALIGNED(canonical_ipa, map_size))) + canonical_ipa =3D ALIGN_DOWN(canonical_ipa, map_size); + + mapping->canonical.start =3D canonical_ipa; + mapping->canonical.last =3D canonical_ipa + map_size - 1; + + mapping->nested.start =3D nested_ipa; + mapping->nested.last =3D nested_ipa + map_size - 1; + + mapping->nested_mmu =3D mmu; + + guard(spinlock)(&kvm->arch.guest_s2_tracking_lock); + interval_tree_insert(&mapping->nested, &mmu->guest_s2_mappings); + interval_tree_insert(&mapping->canonical, &kvm->arch.mmu.guest_s2_mapping= s); +} + void kvm_init_nested_s2_mmu(struct kvm_s2_mmu *mmu) { /* CnP being set denotes an invalid entry */ --=20 2.43.0 From nobody Tue Sep 29 07:39:38 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9E1DA443E4A for ; Mon, 10 Aug 2026 20:51:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786395120; cv=none; b=eg096BxREvhg4EkspjLYD7CI5zG9F+gBnxNYEMd4en1/g63mJO5uHLVPRiQ1CX8jAPq/Sv/hk0vq+6UowRlI4lHkU4cVmg809J3FSv/1deyusidbyY9qQMVyaMc2Y4JgCkGZ0AktPaefO9kiMfcqfHDcc27utitnq+ypvEs+XSA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786395120; c=relaxed/simple; bh=ulWcug5FR5A8S6ih5KiWhVhUwpQ0/EYi/o4gse2V6ZQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aWH7BZvhjnpw8+54S3nP+LM23jGk7C7Hsk8+gyyIZJhcA2iNytCk6DuWHB/WCjWf4mL95yxwMEmgGFf875YHegcG//btG+Vsp2SYwAnLMu8vBa+H7BxABIT1TfTG28BvZYWptJ6SP8XUfiVuDwPFfQRSt0K2gL5Aw3m6Xlsqmd0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=fmLOTLUM; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="fmLOTLUM" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 009C614BF; Mon, 10 Aug 2026 13:51:54 -0700 (PDT) Received: from workstation-e142269.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 0F67A3F673; Mon, 10 Aug 2026 13:51:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1786395117; bh=ulWcug5FR5A8S6ih5KiWhVhUwpQ0/EYi/o4gse2V6ZQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fmLOTLUMUkm3jSxi2mHi2jLK4kmZz/fqGjfpyPxxPxrV32tOxQw/DQG+rv/AcEeC8 Dot5WoK+xd1g4XH/I+DZdnpVis5gDquwMUsYcN7VcqI6QAWK3CdQPL2MqtHXcCm95c jMZ2ax7HFA71xBLCC75+zluGUYsYdOH5NI2tGPuc= From: Wei-Lin Chang To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org Cc: Marc Zyngier , Oliver Upton , Fuad Tabba , Joey Gouly , Steffen Eiden , Suzuki K Poulose , Zenghui Yu , Catalin Marinas , Will Deacon , Lorenzo Stoakes , Itaru Kitayama , Wei-Lin Chang Subject: [PATCH v5 4/6] KVM: arm64: nv: Track guest stage-2 mapping removal Date: Mon, 10 Aug 2026 21:50:36 +0100 Message-ID: <20260810205038.118843-5-weilin.chang@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260810205038.118843-1-weilin.chang@arm.com> References: <20260810205038.118843-1-weilin.chang@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" kvm_stage2_unmap_range() is the helper to remove mappings from the stage-2 page tables. It is called during guest TLBI handling, memslot removal, nested mmu reuse, etc. Teach it about the guest stage-2 tracking trees and remove mappings from there when shadow mappings are removed. This keeps the tracking trees from having stale mappings pile up. Signed-off-by: Wei-Lin Chang Tested-by: Itaru Kitayama Tested-by: Wang Han --- arch/arm64/include/asm/kvm_host.h | 5 ++++- arch/arm64/include/asm/kvm_nested.h | 2 ++ arch/arm64/kvm/mmu.c | 23 +++++++++++++++++++++-- arch/arm64/kvm/nested.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index 0695c4ef93f1..0bb83be1dd4f 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -340,7 +340,10 @@ struct kvm_arch { size_t nested_mmus_size; int nested_mmus_next; =20 - /* Guest s2 tracking trees access serialization. */ + /* + * Serializes guest s2 tracking trees access when the mmu_lock + * is only held for read. + */ spinlock_t guest_s2_tracking_lock; =20 /* Interrupt controller */ diff --git a/arch/arm64/include/asm/kvm_nested.h b/arch/arm64/include/asm/k= vm_nested.h index 560b78b3f5ff..ffa3fa01f3cd 100644 --- a/arch/arm64/include/asm/kvm_nested.h +++ b/arch/arm64/include/asm/kvm_nested.h @@ -80,6 +80,8 @@ extern void kvm_s2_mmu_iterate_by_vmid(struct kvm *kvm, u= 16 vmid, extern void kvm_record_guest_s2_mapping(struct kvm_s2_mmu *mmu, gpa_t cano= nical_ipa, gpa_t nested_ipa, size_t map_size, struct kvm_guest_s2_mapping *mapping); +extern void kvm_remove_guest_s2_mappings(struct kvm_s2_mmu *mmu, + gpa_t nipa, size_t size); extern void kvm_vcpu_load_hw_mmu(struct kvm_vcpu *vcpu); extern void kvm_vcpu_put_hw_mmu(struct kvm_vcpu *vcpu); =20 diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index cea968921041..ddd1bbede227 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -314,6 +314,19 @@ static void invalidate_icache_guest_page(void *va, siz= e_t size) * we then fully enforce cacheability of RAM, no matter what the guest * does. */ + +static int kvm_pgtable_stage2_unmap_tracked(struct kvm_pgtable *pgt, u64 a= ddr, u64 size) +{ + int ret; + + ret =3D kvm_pgtable_stage2_unmap(pgt, addr, size); + if (ret) + return ret; + + kvm_remove_guest_s2_mappings(pgt->mmu, addr, size); + return 0; +} + /** * __unmap_stage2_range -- Clear stage2 page table entries to unmap a range * @mmu: The KVM stage-2 MMU pointer @@ -331,11 +344,17 @@ static void __unmap_stage2_range(struct kvm_s2_mmu *m= mu, phys_addr_t start, u64 { struct kvm *kvm =3D kvm_s2_mmu_to_kvm(mmu); phys_addr_t end =3D start + size; + int (*fn)(struct kvm_pgtable *, u64, u64); =20 lockdep_assert_held_write(&kvm->mmu_lock); WARN_ON(size & ~PAGE_MASK); - WARN_ON(stage2_apply_range(mmu, start, end, KVM_PGT_FN(kvm_pgtable_stage2= _unmap), - may_block)); + + if (kvm_is_nested_s2_mmu(kvm, mmu)) + fn =3D kvm_pgtable_stage2_unmap_tracked; + else + fn =3D KVM_PGT_FN(kvm_pgtable_stage2_unmap); + + WARN_ON(stage2_apply_range(mmu, start, end, fn, may_block)); } =20 void kvm_stage2_unmap_range(struct kvm_s2_mmu *mmu, phys_addr_t start, diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c index 646b628bba17..2a4c86df404c 100644 --- a/arch/arm64/kvm/nested.c +++ b/arch/arm64/kvm/nested.c @@ -877,6 +877,34 @@ void kvm_record_guest_s2_mapping(struct kvm_s2_mmu *mm= u, gpa_t canonical_ipa, interval_tree_insert(&mapping->canonical, &kvm->arch.mmu.guest_s2_mapping= s); } =20 +void kvm_remove_guest_s2_mappings(struct kvm_s2_mmu *mmu, gpa_t nipa, + size_t size) +{ + struct kvm *kvm =3D kvm_s2_mmu_to_kvm(mmu); + struct interval_tree_node *node, *next; + struct kvm_guest_s2_mapping *mapping; + gpa_t nipa_end =3D nipa + size - 1; + + /* + * Guest s2 tracking interval trees are only accessed while holding the + * mmu_lock, hence we don't have to take guest_s2_tracking_lock if the + * mmu_lock is held for write. + */ + lockdep_assert_held_write(&kvm_s2_mmu_to_kvm(mmu)->mmu_lock); + + node =3D interval_tree_iter_first(&mmu->guest_s2_mappings, nipa, nipa_end= ); + while (node) { + next =3D interval_tree_iter_next(node, nipa, nipa_end); + mapping =3D container_of(node, struct kvm_guest_s2_mapping, + nested); + interval_tree_remove(&mapping->nested, &mmu->guest_s2_mappings); + interval_tree_remove(&mapping->canonical, + &kvm->arch.mmu.guest_s2_mappings); + kfree(mapping); + node =3D next; + } +} + void kvm_init_nested_s2_mmu(struct kvm_s2_mmu *mmu) { /* CnP being set denotes an invalid entry */ --=20 2.43.0 From nobody Tue Sep 29 07:39:38 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D3C564446F4 for ; Mon, 10 Aug 2026 20:52:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786395122; cv=none; b=QRFVdN52WuQauouybatpKlvpngp8XNobuL40XbF/07GHwHmsARI8EEka9883bM7hvRIHVsazxD4PGHOOPWKEgrxQtnHrEaC/ihvn95nAzqKLUlzslPnabXT07+6hYRftVyzP37sOnbFcmMgj5g4J8NHI7UFjZPOCXSHaYGO/0Ow= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786395122; c=relaxed/simple; bh=iEsxLdgXbUKc751dxgYuroZ4a7e4sbdIu33U4XqBSbg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LrjJkkhQEsjfHH5lWkNEcdMABWszS2jhr5Ok7qOHscbFrumQGwqZV53LCr+o0eW8kaCw4OK9l7SNpX0OPUtvCUMbxtHVqdw18wD13is9CNqcQe+YKU3MXSH6/69Yh9EveFMNcsAwN3B54xrJkx5C+UtFk9XAY7jMxGunE23uyKY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=HD/R2hl2; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="HD/R2hl2" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 307D51655; Mon, 10 Aug 2026 13:51:56 -0700 (PDT) Received: from workstation-e142269.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3ED843F673; Mon, 10 Aug 2026 13:51:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1786395120; bh=iEsxLdgXbUKc751dxgYuroZ4a7e4sbdIu33U4XqBSbg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=HD/R2hl2cWK/QwxjdLZu/A1ylJ48Ljs6g/FsWr91HaSL4aCeR4a8f6XgEx2zoaJeX 3GWqcYS9tMFtjRqctOtG1hIyHwnfWNJQR5jWWtL3V/dWqF1qqxmKmD3bpa8XEoItnx 63Vl1tpUEZbEX5aWpVxzHl0Cm6oSZU2CzsTE7CtU= From: Wei-Lin Chang To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org Cc: Marc Zyngier , Oliver Upton , Fuad Tabba , Joey Gouly , Steffen Eiden , Suzuki K Poulose , Zenghui Yu , Catalin Marinas , Will Deacon , Lorenzo Stoakes , Itaru Kitayama , Wei-Lin Chang Subject: [PATCH v5 5/6] KVM: arm64: nv: Avoid full shadow stage-2 unmap Date: Mon, 10 Aug 2026 21:50:37 +0100 Message-ID: <20260810205038.118843-6-weilin.chang@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260810205038.118843-1-weilin.chang@arm.com> References: <20260810205038.118843-1-weilin.chang@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" With guest stage-2 tracking in place, we can improve MMU notifier unmaps from unmapping all existing shadow stage-2 mappings to only unmapping the ones affected by the given canonical IPA range. Signed-off-by: Wei-Lin Chang Tested-by: Itaru Kitayama Tested-by: Wang Han --- arch/arm64/include/asm/kvm_nested.h | 2 ++ arch/arm64/kvm/mmu.c | 7 +++-- arch/arm64/kvm/nested.c | 47 +++++++++++++++++++++++++++-- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/arch/arm64/include/asm/kvm_nested.h b/arch/arm64/include/asm/k= vm_nested.h index ffa3fa01f3cd..4e7d89b6824b 100644 --- a/arch/arm64/include/asm/kvm_nested.h +++ b/arch/arm64/include/asm/kvm_nested.h @@ -170,6 +170,8 @@ extern int kvm_s2_handle_perm_fault(struct kvm_vcpu *vc= pu, struct kvm_s2_trans *trans); extern int kvm_inject_s2_fault(struct kvm_vcpu *vcpu, u64 esr_el2); extern void kvm_nested_s2_wp(struct kvm *kvm); +extern void kvm_nested_unmap_cipa_range(struct kvm *kvm, gpa_t cipa, + size_t unmap_size, bool may_block); extern void kvm_nested_s2_unmap(struct kvm *kvm, bool may_block); extern void kvm_nested_s2_flush(struct kvm *kvm); =20 diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index ddd1bbede227..241f020910d8 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -2518,8 +2518,9 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_= gfn_range *range) __unmap_stage2_range(&kvm->arch.mmu, range->start << PAGE_SHIFT, (range->end - range->start) << PAGE_SHIFT, range->may_block); - - kvm_nested_s2_unmap(kvm, range->may_block); + kvm_nested_unmap_cipa_range(kvm, range->start << PAGE_SHIFT, + (range->end - range->start) << PAGE_SHIFT, + range->may_block); return false; } =20 @@ -2797,7 +2798,7 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm, =20 write_lock(&kvm->mmu_lock); kvm_stage2_unmap_range(&kvm->arch.mmu, gpa, size, true); - kvm_nested_s2_unmap(kvm, true); + kvm_nested_unmap_cipa_range(kvm, gpa, size, true); write_unlock(&kvm->mmu_lock); } =20 diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c index 2a4c86df404c..0dc5824c8237 100644 --- a/arch/arm64/kvm/nested.c +++ b/arch/arm64/kvm/nested.c @@ -886,9 +886,8 @@ void kvm_remove_guest_s2_mappings(struct kvm_s2_mmu *mm= u, gpa_t nipa, gpa_t nipa_end =3D nipa + size - 1; =20 /* - * Guest s2 tracking interval trees are only accessed while holding the - * mmu_lock, hence we don't have to take guest_s2_tracking_lock if the - * mmu_lock is held for write. + * See kvm_nested_unmap_cipa_range() for why guest_s2_tracking_lock + * isn't taken here. */ lockdep_assert_held_write(&kvm_s2_mmu_to_kvm(mmu)->mmu_lock); =20 @@ -1286,6 +1285,48 @@ void kvm_nested_s2_wp(struct kvm *kvm) kvm_invalidate_vncr_ipa(kvm, 0, BIT(kvm->arch.mmu.pgt->ia_bits)); } =20 +void kvm_nested_unmap_cipa_range(struct kvm *kvm, gpa_t cipa, size_t unmap= _size, + bool may_block) +{ + gpa_t cipa_end =3D cipa + unmap_size - 1; + struct kvm_guest_s2_mapping *mapping; + struct interval_tree_node *node; + size_t mapping_size; + + /* + * Guest s2 tracking interval trees are only accessed while holding the + * mmu_lock, hence we don't have to take guest_s2_tracking_lock if the + * mmu_lock is held for write. This saves us from having to manually + * lock/unlock guest_s2_tracking_lock below around + * cond_resched_rwlock_write(). + */ + lockdep_assert_held_write(&kvm->mmu_lock); + + if (!kvm->arch.nested_mmus_size) + return; + + while ((node =3D interval_tree_iter_first(&kvm->arch.mmu.guest_s2_mapping= s, + cipa, cipa_end))) { + mapping =3D container_of(node, struct kvm_guest_s2_mapping, + canonical); + mapping_size =3D mapping->nested.last - mapping->nested.start + 1; + + if (WARN_ON_ONCE(kvm_pgtable_stage2_unmap(mapping->nested_mmu->pgt, + mapping->nested.start, + mapping_size))) + return; + + interval_tree_remove(node, &kvm->arch.mmu.guest_s2_mappings); + interval_tree_remove(&mapping->nested, &mapping->nested_mmu->guest_s2_ma= ppings); + kfree(mapping); + + if (may_block) + cond_resched_rwlock_write(&kvm->mmu_lock); + } + + kvm_invalidate_vncr_ipa(kvm, cipa, cipa + unmap_size); +} + void kvm_nested_s2_unmap(struct kvm *kvm, bool may_block) { int i; --=20 2.43.0 From nobody Tue Sep 29 07:39:38 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B9A084457A2 for ; Mon, 10 Aug 2026 20:52:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786395124; cv=none; b=ud66bREoE7EXkoOVYuszAWwQ7TXHy2FKyV3UwU5GMcC8bfFaeGQreK0hXqiZ9fk7wl720tROi8MyS8LPn7Ik5w/dwmyR/3+S8CxKf198P5wJ2q9EXEbIMTIQnyPP3pwMhWk4Br3C+K4r5h44ycra63F0O1LlCQr1V12c+nudU+w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786395124; c=relaxed/simple; bh=WaxPznMv/qn072xMj4ZtLqSYLS1ETbEkJqwZWvJUvvk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UROFlR3Tv9f83Xf8apIX5eG4QzA/O+S4rIioHFOWejGd9AJTgjPebD5KQ8a/KSb6QMmNrrqvJ2zNs8hIpNzWDJ2LCJLZ4m2KRB8d3VxQ0symIsHt6NHUMSsp5rFazV7lTv3wpzE8oewXsfBss5iffEms0mbyMqLDu1EF7u5GM+4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=azDkaTuC; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="azDkaTuC" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 62B3114BF; Mon, 10 Aug 2026 13:51:58 -0700 (PDT) Received: from workstation-e142269.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 6F2FF3F673; Mon, 10 Aug 2026 13:52:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1786395122; bh=WaxPznMv/qn072xMj4ZtLqSYLS1ETbEkJqwZWvJUvvk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=azDkaTuCtoM0963uMoAgwfn60Y35yixNRfx7qxD7cyA0McQWE0HKFpDhq5aSxTaHD l9/lSrVuzw3tpVCsv/w+HCi25HRvRIBZ5yvLtzOrTNXMGy4W59Y943W8ifm6PR3OGh XcZzcq9Upt5b43oIlLOhxprb1TGx1KsPmEiKcPXw= From: Wei-Lin Chang To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, linux-kernel@vger.kernel.org Cc: Marc Zyngier , Oliver Upton , Fuad Tabba , Joey Gouly , Steffen Eiden , Suzuki K Poulose , Zenghui Yu , Catalin Marinas , Will Deacon , Lorenzo Stoakes , Itaru Kitayama , Wei-Lin Chang Subject: [PATCH v5 6/6] KVM: arm64: Refactor kvm_unmap_gfn_range() with common variables Date: Mon, 10 Aug 2026 21:50:38 +0100 Message-ID: <20260810205038.118843-7-weilin.chang@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260810205038.118843-1-weilin.chang@arm.com> References: <20260810205038.118843-1-weilin.chang@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" __unmap_stage2_range() and kvm_nested_unmap_cipa_range() are using the same arguments. Clean this up by using local variables. Signed-off-by: Wei-Lin Chang Tested-by: Itaru Kitayama Tested-by: Wang Han --- arch/arm64/kvm/mmu.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 241f020910d8..9d3ea44a894b 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -2512,15 +2512,16 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu) =20 bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) { + gpa_t gpa =3D range->start << PAGE_SHIFT; + size_t size =3D (range->end - range->start) << PAGE_SHIFT; + bool may_block =3D range->may_block; + if (!kvm->arch.mmu.pgt || kvm_vm_is_protected(kvm)) return false; =20 - __unmap_stage2_range(&kvm->arch.mmu, range->start << PAGE_SHIFT, - (range->end - range->start) << PAGE_SHIFT, - range->may_block); - kvm_nested_unmap_cipa_range(kvm, range->start << PAGE_SHIFT, - (range->end - range->start) << PAGE_SHIFT, - range->may_block); + __unmap_stage2_range(&kvm->arch.mmu, gpa, size, may_block); + kvm_nested_unmap_cipa_range(kvm, gpa, size, may_block); + return false; } =20 --=20 2.43.0