|
|
@@ -4496,14 +4496,25 @@ static int avic_incomplete_ipi_interception(struct vcpu_svm *svm)
|
|
|
kvm_lapic_reg_write(apic, APIC_ICR, icrl);
|
|
|
break;
|
|
|
case AVIC_IPI_FAILURE_TARGET_NOT_RUNNING: {
|
|
|
+ int i;
|
|
|
+ struct kvm_vcpu *vcpu;
|
|
|
+ struct kvm *kvm = svm->vcpu.kvm;
|
|
|
struct kvm_lapic *apic = svm->vcpu.arch.apic;
|
|
|
|
|
|
/*
|
|
|
- * Update ICR high and low, then emulate sending IPI,
|
|
|
- * which is handled when writing APIC_ICR.
|
|
|
+ * At this point, we expect that the AVIC HW has already
|
|
|
+ * set the appropriate IRR bits on the valid target
|
|
|
+ * vcpus. So, we just need to kick the appropriate vcpu.
|
|
|
*/
|
|
|
- kvm_lapic_reg_write(apic, APIC_ICR2, icrh);
|
|
|
- kvm_lapic_reg_write(apic, APIC_ICR, icrl);
|
|
|
+ kvm_for_each_vcpu(i, vcpu, kvm) {
|
|
|
+ bool m = kvm_apic_match_dest(vcpu, apic,
|
|
|
+ icrl & KVM_APIC_SHORT_MASK,
|
|
|
+ GET_APIC_DEST_FIELD(icrh),
|
|
|
+ icrl & KVM_APIC_DEST_MASK);
|
|
|
+
|
|
|
+ if (m && !avic_vcpu_is_running(vcpu))
|
|
|
+ kvm_vcpu_wake_up(vcpu);
|
|
|
+ }
|
|
|
break;
|
|
|
}
|
|
|
case AVIC_IPI_FAILURE_INVALID_TARGET:
|