diff options
author | Vitaly Kuznetsov <vkuznets@redhat.com> | 2018-02-09 14:01:33 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2018-03-16 22:01:29 +0100 |
commit | 0bcc3fb95b97ac2ca223a5a870287b37f56265ac (patch) | |
tree | 3edf2ac70bf99b8d77affeb6464e0f70cfdc756d /arch/x86 | |
parent | c51eb52b8f9835f8f4f51e390885f8ddcfe53871 (diff) | |
download | linux-stable-0bcc3fb95b97ac2ca223a5a870287b37f56265ac.tar.gz linux-stable-0bcc3fb95b97ac2ca223a5a870287b37f56265ac.tar.bz2 linux-stable-0bcc3fb95b97ac2ca223a5a870287b37f56265ac.zip |
KVM: lapic: stop advertising DIRECTED_EOI when in-kernel IOAPIC is in use
Devices which use level-triggered interrupts under Windows 2016 with
Hyper-V role enabled don't work: Windows disables EOI broadcast in SPIV
unconditionally. Our in-kernel IOAPIC implementation emulates an old IOAPIC
version which has no EOI register so EOI never happens.
The issue was discovered and discussed a while ago:
https://www.spinics.net/lists/kvm/msg148098.html
While this is a guest OS bug (it should check that IOAPIC has the required
capabilities before disabling EOI broadcast) we can workaround it in KVM:
advertising DIRECTED_EOI with in-kernel IOAPIC makes little sense anyway.
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kvm/lapic.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 391dda8d43b7..70dcb5548022 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -321,8 +321,16 @@ void kvm_apic_set_version(struct kvm_vcpu *vcpu) if (!lapic_in_kernel(vcpu)) return; + /* + * KVM emulates 82093AA datasheet (with in-kernel IOAPIC implementation) + * which doesn't have EOI register; Some buggy OSes (e.g. Windows with + * Hyper-V role) disable EOI broadcast in lapic not checking for IOAPIC + * version first and level-triggered interrupts never get EOIed in + * IOAPIC. + */ feat = kvm_find_cpuid_entry(apic->vcpu, 0x1, 0); - if (feat && (feat->ecx & (1 << (X86_FEATURE_X2APIC & 31)))) + if (feat && (feat->ecx & (1 << (X86_FEATURE_X2APIC & 31))) && + !ioapic_in_kernel(vcpu->kvm)) v |= APIC_LVR_DIRECTED_EOI; kvm_lapic_set_reg(apic, APIC_LVR, v); } |