In kvm_tlbidomain_vcpu_load(), the domain map is recomputed on every vCPU load, followed by an expensive kvm_flush_remote_tlbs() and kvm_make_all_cpus_request() to invalidate TLBs and IPI all vCPUs. However, when a vCPU is scheduled back onto the same pCPU or the pDomain assignment does not change, the domain map remains the same and the invalidation + IPI is unnecessary. Record the old domain map value before recomputing, and compare it with the new one. If no vDomain's mapping has changed, skip the TLB flush and vCPU IPI, jumping directly to update the tlbid hardware map register. This avoids redundant cross-CPU IPIs and TLB shootdowns in the common case where a vCPU migrates back to its previous pCPU, significantly reducing the overhead of the vCPU load path. Signed-off-by: Jinqian Yang <yangjinqian1@huawei.com> --- arch/arm64/kvm/arm.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 3979eb9dcae0..fed48b4ce23c 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -957,7 +957,8 @@ static void kvm_tlbidomain_vcpu_load(struct kvm_vcpu *vcpu) int max_vdomains = 1 << vdomain->nvis; DECLARE_BITMAP(clear_bits, max_vdomains); struct vcpu_tlbid_data *current_data, *other_data; - int i; + bool domain_map_changed = false; + int i, old_map; /* * If we support tlbid, but user does not enable it, we can do @@ -1003,6 +1004,8 @@ static void kvm_tlbidomain_vcpu_load(struct kvm_vcpu *vcpu) } if (!vdomain->guest_tlbid_enabled) { + old_map = vdomain->domain_map[0]; + /* * If QEMU is not configured with vdomains, only vDomain0 needs * to be mapped. @@ -1011,6 +1014,8 @@ static void kvm_tlbidomain_vcpu_load(struct kvm_vcpu *vcpu) 0, current_data->last_pcpu, test_bit(0, clear_bits)); + if (vdomain->domain_map[0] == old_map) + goto unlock; } else { /* * If QEMU is configured with vdomains, all vdomains need to be @@ -1021,11 +1026,18 @@ static void kvm_tlbidomain_vcpu_load(struct kvm_vcpu *vcpu) if (!is_vcpu_in_vdomain(current_data->vdomain_bitmap, i)) continue; + old_map = vdomain->domain_map[i]; vdomain->domain_map[i] = update_domain_map(vcpu, i, current_data->last_pcpu, test_bit(i, clear_bits)); + + if (vdomain->domain_map[i] != old_map) + domain_map_changed = true; } + + if (!domain_map_changed) + goto unlock; } kvm_flush_remote_tlbs(kvm); @@ -1038,6 +1050,7 @@ static void kvm_tlbidomain_vcpu_load(struct kvm_vcpu *vcpu) */ kvm_make_all_cpus_request(kvm, KVM_REQ_RELOAD_VTLBID | KVM_REQUEST_WAIT); +unlock: /* update tlbid hardware map register */ kvm_arm_update_tlbid_map(vdomain); -- 2.33.0