KVM: arm64: TLBI fixes for the pgtable code
Will Deacon
maintainerv2 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
--->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
Will Deacon
maintainerPATCH 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.
--- arch/arm64/kvm/hyp/pgtable.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/arm64/kvm/hyp/pgtable.c +3 -1
@@ -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
Will Deacon
maintainerPATCH v2 2/4 KVM: arm64: Don't pass a TLBI level hint when zapping table entries
In reply to Will DeaconThe TLBI level hints are for leaf entries only, so take care not to pass them incorrectly after clearing a table entry.
--- arch/arm64/kvm/hyp/pgtable.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
arch/arm64/kvm/hyp/pgtable.c +7 -5
@@ -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
Will Deacon
maintainerPATCH v2 3/4 KVM: arm64: Use TLBI_TTL_UNKNOWN in __kvm_tlb_flush_vmid_range()
In reply to Will DeaconCommit 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().
--- 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
@@ -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
@@ -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
Will Deacon
maintainerPATCH v2 4/4 KVM: arm64: Ensure target address is granule-aligned for range TLBI
In reply to Will DeaconWhen 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().
--- arch/arm64/kvm/hyp/pgtable.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
arch/arm64/kvm/hyp/pgtable.c +7 -4
@@ -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
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.
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 messagesCheers,
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: UseTLBI_TTL_UNKNOWNin__kvm_tlb_flush_vmid_range()
KVM: arm64: Ensure target address is granule-aligned for range TLBIarch/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
Oliver Upton
AppliedQuoted 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: 4c36a156738887c1edd78589fe192d757989bcdeSignature · 2 lines
Best, Oliver