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.
Showing the changes to include/uapi (1 of 6 files). Show all
Unified · Split
| @@ -1596,6 +1596,7 @@ struct kvm_xen_hvm_attr { · 1595 unmodified lines | |||
| 1596 | __u16 pad[3]; | 1596 | __u16 pad[3]; |
| 1597 | union { | 1597 | union { |
| 1598 | __u8 long_mode; | 1598 | __u8 long_mode; |
| 1599 | __u8 vector; | ||
| 1599 | struct { | 1600 | struct { |
| 1600 | __u64 gfn; | 1601 | __u64 gfn; |
| 1601 | } shared_info; | 1602 | } shared_info; |
| @@ -1605,6 +1606,7 @@ struct kvm_xen_hvm_attr { · 3 unmodified lines | |||
| 1605 | 1606 | ||
| 1606 | #define KVM_XEN_ATTR_TYPE_LONG_MODE 0x0 | 1607 | #define KVM_XEN_ATTR_TYPE_LONG_MODE 0x0 |
| 1607 | #define KVM_XEN_ATTR_TYPE_SHARED_INFO 0x1 | 1608 | #define KVM_XEN_ATTR_TYPE_SHARED_INFO 0x1 |
| 1609 | #define KVM_XEN_ATTR_TYPE_UPCALL_VECTOR 0x2 | ||
| 1608 | 1610 | ||
| 1609 | /* Per-vCPU Xen attributes */ | 1611 | /* Per-vCPU Xen attributes */ |
| 1610 | #define KVM_XEN_VCPU_GET_ATTR _IOWR(KVMIO, 0xca, struct kvm_xen_vcpu_attr) | 1612 | #define KVM_XEN_VCPU_GET_ATTR _IOWR(KVMIO, 0xca, struct kvm_xen_vcpu_attr) |