hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/10293 ---------------------------------------- With directed TLBI enabled, kvm_arch_flush_remote_tlbs() and its range variant turn the invalidation into KVM_REQ_TLB_FLUSH requests: each vCPU locally invalidates its stage-2 context on guest entry, with running vCPUs kicked out synchronously and sleeping ones left alone. The range variant records the range per vCPU so that the consumer invalidates it precisely. The directed branches arm kvm_arch::tlbi_directed; a full broadcast clears it. Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com> --- arch/arm64/kvm/mmu.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 74b9f2629a2e..eb16b8d04908 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -18,6 +18,7 @@ #include <asm/kvm_ras.h> #include <asm/kvm_asm.h> #include <asm/kvm_emulate.h> +#include <asm/kvm_tlbi.h> #include <asm/virt.h> #ifdef CONFIG_HISI_VIRTCCA_CODA #include <asm/kvm_tmi.h> @@ -170,13 +171,42 @@ static bool memslot_is_logging(struct kvm_memory_slot *memslot) */ int kvm_arch_flush_remote_tlbs(struct kvm *kvm) { +#ifdef CONFIG_KVM_ARM_DIRECT_TLBI + /* + * Let the generic layer turn this into KVM_REQ_TLB_FLUSH + * requests: each vCPU locally invalidates its stage-2 context + * on guest entry. Realm and pKVM VMs keep the broadcast. + */ + if (kvm_tlbi_direct_enabled() && + !is_protected_kvm_enabled() && !_kvm_is_realm(kvm) && + in_task() && !irqs_disabled()) { + /* The generic layer makes the per-vCPU requests below. */ + smp_store_release(&kvm->arch.tlbi_directed, true); + return -ENOTSUPP; + } +#endif kvm_call_hyp(__kvm_tlb_flush_vmid, &kvm->arch.mmu); + /* A full-VMID broadcast leaves no stale entry on any pCPU. */ + smp_store_release(&kvm->arch.tlbi_directed, false); return 0; } int kvm_arch_flush_remote_tlbs_range(struct kvm *kvm, gfn_t gfn, u64 nr_pages) { +#ifdef CONFIG_KVM_ARM_DIRECT_TLBI + /* + * vCPUs invalidate the range locally on guest entry; ranges + * that can't be merged escalate to a whole-VMID flush. + */ + if (kvm_tlbi_direct_enabled() && + !is_protected_kvm_enabled() && !_kvm_is_realm(kvm) && + in_task() && !irqs_disabled()) { + kvm_tlbi_request_flush_range(kvm, gfn << PAGE_SHIFT, + nr_pages << PAGE_SHIFT); + return 0; + } +#endif kvm_tlb_flush_vmid_range(&kvm->arch.mmu, gfn << PAGE_SHIFT, nr_pages << PAGE_SHIFT); return 0; -- 2.33.0