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
4504 kvm_lapic_reg_write(apic, APIC_ICR, icrl);4504 kvm_lapic_reg_write(apic, APIC_ICR, icrl);
4505 break;4505 break;
4506 case AVIC_IPI_FAILURE_TARGET_NOT_RUNNING: {4506 case AVIC_IPI_FAILURE_TARGET_NOT_RUNNING: {
4507 int i;
4508 struct kvm_vcpu *vcpu;
4509 struct kvm *kvm = svm->vcpu.kvm;
4510 struct kvm_lapic *apic = svm->vcpu.arch.apic;4507 struct kvm_lapic *apic = svm->vcpu.arch.apic;
4511 4508
4512 /*4509 /*
4513 * At this point, we expect that the AVIC HW has already4510 * Update ICR high and low, then emulate sending IPI,
4514 * set the appropriate IRR bits on the valid target4511 * which is handled when writing APIC_ICR.
4515 * vcpus. So, we just need to kick the appropriate vcpu.
4516 */4512 */
4517 kvm_for_each_vcpu(i, vcpu, kvm) {4513 kvm_lapic_reg_write(apic, APIC_ICR2, icrh);
4518 bool m = kvm_apic_match_dest(vcpu, apic,4514 kvm_lapic_reg_write(apic, APIC_ICR, icrl);
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 }
4526 break;4515 break;
4527 }4516 }
4528 case AVIC_IPI_FAILURE_INVALID_TARGET:4517 case AVIC_IPI_FAILURE_INVALID_TARGET: