Skip to contentSkip to conversation

KVM: arm64: TLBI fixes for the pgtable code

PATCH Applied Will Deacon 4 participants 8 messages Mar 27, 2024 – Apr 1, 2024

Subsystems (2)
lore
Share & tools
lore

Will Deacon

author maintainer
#0 lore raw

v2 cover KVM: arm64: TLBI fixes for the pgtable code

Hi again,

This is version two of the series I previously posted on Monday:

https://lore.kernel.org/r/[email protected]

We've got a long weekend coming up in the UK, so I wanted to get this out before I chuck the laptop in the river.

Changes since v1 include:

* Add Ryan's Reviewed-by on the third patch
* Add an extra patch to ensure correct alignment of range TLBI address argument
* Tweak commit messages

Cheers,

Will

Cc Catalin Marinas <[email protected]>
Cc Gavin Shan <[email protected]>
Cc Marc Zyngier <[email protected]>
Cc Mostafa Saleh <[email protected]>
Cc Oliver Upton <[email protected]>
Cc Quentin Perret <[email protected]>
Cc Raghavendra Rao Ananta <[email protected]>
Cc Ryan Roberts <[email protected]>
Cc Shaoqin Huang <[email protected]>

--->8

Will Deacon (4):
KVM: arm64: Don't defer TLB invalidation when zapping table entries
KVM: arm64: Don't pass a TLBI level hint when zapping table entries
KVM: arm64: Use TLBI_TTL_UNKNOWN in __kvm_tlb_flush_vmid_range()
KVM: arm64: Ensure target address is granule-aligned for range TLBI

 arch/arm64/kvm/hyp/nvhe/tlb.c |  3 ++-
 arch/arm64/kvm/hyp/pgtable.c  | 23 +++++++++++++++--------
 arch/arm64/kvm/hyp/vhe/tlb.c  |  3 ++-
 3 files changed, 19 insertions(+), 10 deletions(-)
Signature · 1 line
2.44.0.396.g6e790dbe36-goog
author maintainer
#1 lore raw

PATCH v2 1/4 KVM: arm64: Don't defer TLB invalidation when zapping table entries

Commit 7657ea920c54 ("KVM: arm64: Use TLBI range-based instructions for unmap") introduced deferred TLB invalidation for the stage-2 page-table so that range-based invalidation can be used for the accumulated addresses. This works fine if the structure of the page-tables remains unchanged, but if entire tables are zapped and subsequently freed then we transiently leave the hardware page-table walker with a reference to freed memory thanks to the translation walk caches. For example, stage2_unmap_walker() will free page-table pages:

	if (childp)
		mm_ops->put_page(childp);

and issue the TLB invalidation later in kvm_pgtable_stage2_unmap():

	if (stage2_unmap_defer_tlb_flush(pgt))
		/* Perform the deferred TLB invalidations */
		kvm_tlb_flush_vmid_range(pgt->mmu, addr, size);

For now, take the conservative approach and invalidate the TLB eagerly when we clear a table entry. Note, however, that the existing level hint passed to __kvm_tlb_flush_vmid_ipa() is incorrect and will be fixed in a subsequent patch.

Cc Raghavendra Rao Ananta <[email protected]>
Cc Shaoqin Huang <[email protected]>
Cc Marc Zyngier <[email protected]>
Cc Oliver Upton <[email protected]>
---
 arch/arm64/kvm/hyp/pgtable.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
arch/arm64/kvm/hyp/pgtable.c +3 -1
index 3fae5830f8d2..de0b667ba296 100644
@@ -896,9 +896,11 @@ static void stage2_unmap_put_pte(const struct kvm_pgtable_visit_ctx *ctx,
 	if (kvm_pte_valid(ctx->old)) {
 		kvm_clear_pte(ctx->ptep);
 
-		if (!stage2_unmap_defer_tlb_flush(pgt))
+		if (!stage2_unmap_defer_tlb_flush(pgt) ||
+		    kvm_pte_table(ctx->old, ctx->level)) {
 			kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu,
 					ctx->addr, ctx->level);
+		}
 	}
 
 	mm_ops->put_page(ctx->ptep);
Signature · 1 line
2.44.0.396.g6e790dbe36-goog
author maintainer
#2 lore raw

PATCH v2 2/4 KVM: arm64: Don't pass a TLBI level hint when zapping table entries

In reply to Will Deacon

The TLBI level hints are for leaf entries only, so take care not to pass them incorrectly after clearing a table entry.

Cc Gavin Shan <[email protected]>
Cc Marc Zyngier <[email protected]>
Cc Quentin Perret <[email protected]>
Fixes 82bb02445de5 ("KVM: arm64: Implement kvm_pgtable_hyp_unmap() at EL2")
Fixes 6d9d2115c480 ("KVM: arm64: Add support for stage-2 map()/unmap() in generic page-table")
---
 arch/arm64/kvm/hyp/pgtable.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)
arch/arm64/kvm/hyp/pgtable.c +7 -5
index de0b667ba296..a40dafc43bb6 100644
@@ -528,7 +528,7 @@ static int hyp_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx,
 
 		kvm_clear_pte(ctx->ptep);
 		dsb(ishst);
-		__tlbi_level(vae2is, __TLBI_VADDR(ctx->addr, 0), ctx->level);
+		__tlbi_level(vae2is, __TLBI_VADDR(ctx->addr, 0), TLBI_TTL_UNKNOWN);
 	} else {
 		if (ctx->end - ctx->addr < granule)
 			return -EINVAL;
@@ -896,10 +896,12 @@ static void stage2_unmap_put_pte(const struct kvm_pgtable_visit_ctx *ctx,
 	if (kvm_pte_valid(ctx->old)) {
 		kvm_clear_pte(ctx->ptep);
 
-		if (!stage2_unmap_defer_tlb_flush(pgt) ||
-		    kvm_pte_table(ctx->old, ctx->level)) {
-			kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu,
-					ctx->addr, ctx->level);
+		if (kvm_pte_table(ctx->old, ctx->level)) {
+			kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, ctx->addr,
+				     TLBI_TTL_UNKNOWN);
+		} else if (!stage2_unmap_defer_tlb_flush(pgt)) {
+			kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, ctx->addr,
+				     ctx->level);
 		}
 	}
 
Signature · 1 line
2.44.0.396.g6e790dbe36-goog
author maintainer
#3 lore raw

PATCH v2 3/4 KVM: arm64: Use TLBI_TTL_UNKNOWN in __kvm_tlb_flush_vmid_range()

In reply to Will Deacon

Commit c910f2b65518 ("arm64/mm: Update tlb invalidation routines for FEAT_LPA2") updated the __tlbi_level() macro to take the target level as an argument, with TLBI_TTL_UNKNOWN (rather than 0) indicating that the caller cannot provide level information. Unfortunately, the two implementations of __kvm_tlb_flush_vmid_range() were not updated and so now ask for an level 0 invalidation if FEAT_LPA2 is implemented.

Fix the problem by passing TLBI_TTL_UNKNOWN instead of 0 as the level argument to __flush_s2_tlb_range_op() in __kvm_tlb_flush_vmid_range().

Cc Catalin Marinas <[email protected]>
Cc Oliver Upton <[email protected]>
Cc Marc Zyngier <[email protected]>
Fixes c910f2b65518 ("arm64/mm: Update tlb invalidation routines for FEAT_LPA2")
---
 arch/arm64/kvm/hyp/nvhe/tlb.c | 3 ++-
 arch/arm64/kvm/hyp/vhe/tlb.c  | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)
arch/arm64/kvm/hyp/nvhe/tlb.c +2 -1
index a60fb13e2192..2fc68da4036d 100644
@@ -154,7 +154,8 @@ void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
 	/* Switch to requested VMID */
 	__tlb_switch_to_guest(mmu, &cxt, false);
 
-	__flush_s2_tlb_range_op(ipas2e1is, start, pages, stride, 0);
+	__flush_s2_tlb_range_op(ipas2e1is, start, pages, stride,
+				TLBI_TTL_UNKNOWN);
 
 	dsb(ish);
 	__tlbi(vmalle1is);
arch/arm64/kvm/hyp/vhe/tlb.c +2 -1
index b32e2940df7d..1a60b95381e8 100644
@@ -171,7 +171,8 @@ void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
 	/* Switch to requested VMID */
 	__tlb_switch_to_guest(mmu, &cxt);
 
-	__flush_s2_tlb_range_op(ipas2e1is, start, pages, stride, 0);
+	__flush_s2_tlb_range_op(ipas2e1is, start, pages, stride,
+				TLBI_TTL_UNKNOWN);
 
 	dsb(ish);
 	__tlbi(vmalle1is);
Signature · 1 line
2.44.0.396.g6e790dbe36-goog
author maintainer
#4 lore raw

PATCH v2 4/4 KVM: arm64: Ensure target address is granule-aligned for range TLBI

In reply to Will Deacon

When zapping a table entry in stage2_try_break_pte(), we issue range TLB invalidation for the region that was mapped by the table. However, we neglect to align the base address down to the granule size and so if we ended up reaching the table entry via a misaligned address then we will accidentally skip invalidation for some prefix of the affected address range.

Align 'ctx->addr' down to the granule size when performing TLB invalidation for an unmapped table in stage2_try_break_pte().

Cc Raghavendra Rao Ananta <[email protected]>
Cc Gavin Shan <[email protected]>
Cc Shaoqin Huang <[email protected]>
Cc Quentin Perret <[email protected]>
Fixes defc8cc7abf0 ("KVM: arm64: Invalidate the table entries upon a range")
---
 arch/arm64/kvm/hyp/pgtable.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
arch/arm64/kvm/hyp/pgtable.c +7 -4
index a40dafc43bb6..5a59ef88b646 100644
@@ -843,12 +843,15 @@ static bool stage2_try_break_pte(const struct kvm_pgtable_visit_ctx *ctx,
 		 * Perform the appropriate TLB invalidation based on the
 		 * evicted pte value (if any).
 		 */
-		if (kvm_pte_table(ctx->old, ctx->level))
-			kvm_tlb_flush_vmid_range(mmu, ctx->addr,
-						kvm_granule_size(ctx->level));
-		else if (kvm_pte_valid(ctx->old))
+		if (kvm_pte_table(ctx->old, ctx->level)) {
+			u64 size = kvm_granule_size(ctx->level);
+			u64 addr = ALIGN_DOWN(ctx->addr, size);
+
+			kvm_tlb_flush_vmid_range(mmu, addr, size);
+		} else if (kvm_pte_valid(ctx->old)) {
 			kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu,
 				     ctx->addr, ctx->level);
+		}
 	}
 
 	if (stage2_pte_is_counted(ctx->old))
Signature · 1 line
2.44.0.396.g6e790dbe36-goog
maintainer Reviewed-by on the v2 series
#5 lore raw
In reply to Will Deacon
Quoted 10 lines · Will Deacon

Hi again,

This is version two of the series I previously posted on Monday:

https://lore.kernel.org/r/[email protected]

We've got a long weekend coming up in the UK, so I wanted to get this out before I chuck the laptop in the river.

Quoted 6 lines

Changes since v1 include:

* Add Ryan's Reviewed-by on the third patch
* Add an extra patch to ensure correct alignment of range TLBI address argument
* Tweak commit messages

For the series,

	M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
Reviewed-by on the v2 series
#6 lore raw
In reply to Will Deacon
Quoted 11 lines · Will Deacon

Hi again,

This is version two of the series I previously posted on Monday:

   https://lore.kernel.org/r/[email protected]

We've got a long weekend coming up in the UK, so I wanted to get this out before I chuck the laptop in the river.

Changes since v1 include:

Quoted 8 lines

* Add Ryan's Reviewed-by on the third patch
* Add an extra patch to ensure correct alignment of range TLBI address argument
* Tweak commit messages

Cheers,

Will

Quoted 24 lines
Cc Catalin Marinas <[email protected]>
Cc Gavin Shan <[email protected]>
Cc Marc Zyngier <[email protected]>
Cc Mostafa Saleh <[email protected]>
Cc Oliver Upton <[email protected]>
Cc Quentin Perret <[email protected]>
Cc Raghavendra Rao Ananta <[email protected]>
Cc Ryan Roberts <[email protected]>
Cc Shaoqin Huang <[email protected]>

--->8

Will Deacon (4):
KVM: arm64: Don't defer TLB invalidation when zapping table entries
KVM: arm64: Don't pass a TLBI level hint when zapping table entries
KVM: arm64: Use TLBI_TTL_UNKNOWN in __kvm_tlb_flush_vmid_range()
KVM: arm64: Ensure target address is granule-aligned for range TLBI

  arch/arm64/kvm/hyp/nvhe/tlb.c |  3 ++-
  arch/arm64/kvm/hyp/pgtable.c  | 23 +++++++++++++++--------
  arch/arm64/kvm/hyp/vhe/tlb.c  |  3 ++-
  3 files changed, 19 insertions(+), 10 deletions(-)
Signature · 1 line
Shaoqin
Applied
#7 lore raw
In reply to Will Deacon
Quoted 8 lines · Will Deacon

This is version two of the series I previously posted on Monday:

https://lore.kernel.org/r/[email protected]

We've got a long weekend coming up in the UK, so I wanted to get this out before I chuck the laptop in the river.

[...]

Applied to kvmarm/fixes, thanks!

[1/4] KVM: arm64: Don't defer TLB invalidation when zapping table entries

      commit: f62d4c3eb687d87b616b4279acec7862553bda77
[2/4] KVM: arm64: Don't pass a TLBI level hint when zapping table entries
      commit: 36e008323926036650299cfbb2dca704c7aba849
[3/4] KVM: arm64: Use TLBI_TTL_UNKNOWN in __kvm_tlb_flush_vmid_range()
      commit: 0f0ff097bf77663b8d2692e33d56119947611bb0
[4/4] KVM: arm64: Ensure target address is granule-aligned for range TLBI
      commit: 4c36a156738887c1edd78589fe192d757989bcde
Signature · 2 lines
Best,
Oliver