History

svm: Fix AVIC incomplete IPI emulation

In case of incomplete IPI with invalid interrupt type, the current SVM driver does not properly emulate the IPI, and fails to boot FreeBSD guests with multiple vcpus when enabling AVIC. Fix this by update APIC ICR high/low registers, which also emulate sending the IPI.

Suravee Suthikulpanit committed 7 years ago

Commit bb218fb1 parent 37ef0c41 file · +4 −15Browse files

Unified · Split

arch/x86/kvm/svm.c+4−15
@@ -4504,25 +4504,14 @@ static int avic_incomplete_ipi_interception(struct vcpu_svm *svm) · 4503 unmodified lines
45044504 kvm_lapic_reg_write(apic, APIC_ICR, icrl);
45054505 break;
45064506 case AVIC_IPI_FAILURE_TARGET_NOT_RUNNING: {
4507− int i;
4508− struct kvm_vcpu *vcpu;
4509− struct kvm *kvm = svm->vcpu.kvm;
45104507 struct kvm_lapic *apic = svm->vcpu.arch.apic;
45114508
45124509 /*
4513− * At this point, we expect that the AVIC HW has already
4514− * set the appropriate IRR bits on the valid target
4515− * vcpus. So, we just need to kick the appropriate vcpu.
4510+ * Update ICR high and low, then emulate sending IPI,
4511+ * which is handled when writing APIC_ICR.
45164512 */
4517− kvm_for_each_vcpu(i, vcpu, kvm) {
4518− bool m = kvm_apic_match_dest(vcpu, apic,
4519− icrl & KVM_APIC_SHORT_MASK,
4520− GET_APIC_DEST_FIELD(icrh),
4521− icrl & KVM_APIC_DEST_MASK);
4522−
4523− if (m && !avic_vcpu_is_running(vcpu))
4524− kvm_vcpu_wake_up(vcpu);
4525− }
4513+ kvm_lapic_reg_write(apic, APIC_ICR2, icrh);
4514+ kvm_lapic_reg_write(apic, APIC_ICR, icrl);
45264515 break;
45274516 }
45284517 case AVIC_IPI_FAILURE_INVALID_TARGET: