summaryrefslogtreecommitdiff
path: root/arch/x86/kvm/irq.c
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw@amazon.co.uk>2020-12-09 23:08:30 +0300
committerDavid Woodhouse <dwmw@amazon.co.uk>2021-02-04 17:19:39 +0300
commit40da8ccd724f7ca2f08550a46268bc3a91cc8869 (patch)
tree7f9240ecbda4aa6a5b33cd2b75d408aed68df5d9 /arch/x86/kvm/irq.c
parentf2340cd9e41dc463cb1189274f3db560c1dfa1f4 (diff)
downloadlinux-40da8ccd724f7ca2f08550a46268bc3a91cc8869.tar.xz
KVM: x86/xen: Add event channel interrupt vector upcall
It turns out that we can't handle event channels *entirely* in userspace by delivering them as ExtINT, because KVM is a bit picky about when it accepts ExtINT interrupts from a legacy PIC. The in-kernel local APIC has to have LVT0 configured in APIC_MODE_EXTINT and unmasked, which isn't necessarily the case for Xen guests especially on secondary CPUs. To cope with this, add kvm_xen_get_interrupt() which checks the evtchn_pending_upcall field in the Xen vcpu_info, and delivers the Xen upcall vector (configured by KVM_XEN_ATTR_TYPE_UPCALL_VECTOR) if it's set regardless of LAPIC LVT0 configuration. This gives us the minimum support we need for completely userspace-based implementation of event channels. This does mean that vcpu_enter_guest() needs to check for the evtchn_pending_upcall flag being set, because it can't rely on someone having set KVM_REQ_EVENT unless we were to add some way for userspace to do so manually. Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Diffstat (limited to 'arch/x86/kvm/irq.c')
-rw-r--r--arch/x86/kvm/irq.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c
index a035cca82f8f..172b05343cfd 100644
--- a/arch/x86/kvm/irq.c
+++ b/arch/x86/kvm/irq.c
@@ -14,6 +14,7 @@
#include "irq.h"
#include "i8254.h"
#include "x86.h"
+#include "xen.h"
/*
* check if there are pending timer events
@@ -56,6 +57,9 @@ int kvm_cpu_has_extint(struct kvm_vcpu *v)
if (!lapic_in_kernel(v))
return v->arch.interrupt.injected;
+ if (kvm_xen_has_interrupt(v))
+ return 1;
+
if (!kvm_apic_accept_pic_intr(v))
return 0;
@@ -110,6 +114,9 @@ static int kvm_cpu_get_extint(struct kvm_vcpu *v)
if (!lapic_in_kernel(v))
return v->arch.interrupt.nr;
+ if (kvm_xen_has_interrupt(v))
+ return v->kvm->arch.xen.upcall_vector;
+
if (irqchip_split(v->kvm)) {
int vector = v->arch.pending_external_vector;