Skip to content

Commit 782f645

Browse files
sean-jcbonzini
authored andcommitted
KVM: SVM: Skip AVIC and IRTE updates when loading blocking vCPU
Don't bother updating the Physical APIC table or IRTE when loading a vCPU that is blocking, i.e. won't be marked IsRun{ning}=1, as the pCPU is queried if and only if IsRunning is '1'. If the vCPU was migrated, the new pCPU will be picked up when avic_vcpu_load() is called by svm_vcpu_unblocking(). Signed-off-by: Sean Christopherson <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent af52f5a commit 782f645

File tree

1 file changed

+18
-14
lines changed

1 file changed

+18
-14
lines changed

arch/x86/kvm/svm/avic.c

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,6 @@ void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
975975
{
976976
u64 entry;
977977
/* ID = 0xff (broadcast), ID > 0xff (reserved) */
978-
bool is_blocking = kvm_vcpu_is_blocking(vcpu);
979978
int h_physical_id = kvm_cpu_get_apicid(cpu);
980979
struct vcpu_svm *svm = to_svm(vcpu);
981980

@@ -986,24 +985,25 @@ void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
986985
if (WARN_ON(h_physical_id > AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK))
987986
return;
988987

988+
/*
989+
* No need to update anything if the vCPU is blocking, i.e. if the vCPU
990+
* is being scheduled in after being preempted. The CPU entries in the
991+
* Physical APIC table and IRTE are consumed iff IsRun{ning} is '1'.
992+
* If the vCPU was migrated, its new CPU value will be stuffed when the
993+
* vCPU unblocks.
994+
*/
995+
if (kvm_vcpu_is_blocking(vcpu))
996+
return;
997+
989998
entry = READ_ONCE(*(svm->avic_physical_id_cache));
990999
WARN_ON(entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK);
9911000

9921001
entry &= ~AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK;
9931002
entry |= (h_physical_id & AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK);
994-
995-
entry &= ~AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
996-
997-
/*
998-
* Don't mark the vCPU as running if its blocking, i.e. if the vCPU is
999-
* preempted after svm_vcpu_blocking() but before KVM voluntarily
1000-
* schedules out the vCPU.
1001-
*/
1002-
if (!is_blocking)
1003-
entry |= AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
1003+
entry |= AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
10041004

10051005
WRITE_ONCE(*(svm->avic_physical_id_cache), entry);
1006-
avic_update_iommu_vcpu_affinity(vcpu, h_physical_id, !is_blocking);
1006+
avic_update_iommu_vcpu_affinity(vcpu, h_physical_id, true);
10071007
}
10081008

10091009
void avic_vcpu_put(struct kvm_vcpu *vcpu)
@@ -1012,8 +1012,12 @@ void avic_vcpu_put(struct kvm_vcpu *vcpu)
10121012
struct vcpu_svm *svm = to_svm(vcpu);
10131013

10141014
entry = READ_ONCE(*(svm->avic_physical_id_cache));
1015-
if (entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK)
1016-
avic_update_iommu_vcpu_affinity(vcpu, -1, 0);
1015+
1016+
/* Nothing to do if IsRunning == '0' due to vCPU blocking. */
1017+
if (!(entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK))
1018+
return;
1019+
1020+
avic_update_iommu_vcpu_affinity(vcpu, -1, 0);
10171021

10181022
entry &= ~AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK;
10191023
WRITE_ONCE(*(svm->avic_physical_id_cache), entry);

0 commit comments

Comments
 (0)