7.5 KVM_CAP_SPLIT_IRQCHIP
 
 Architectures: x86
-Parameters: None
+Parameters: args[0] - number of routes reserved for userspace IOAPICs
 Returns: 0 on success, -1 on error
 
 Create a local apic for each processor in the kernel. This can be used
 IOAPIC and PIC (and also the PIT, even though this has to be enabled
 separately).
 
-This supersedes KVM_CREATE_IRQCHIP, creating only local APICs, but no in kernel
-IOAPIC or PIC. This also enables in kernel routing of interrupt requests.
+This capability also enables in kernel routing of interrupt requests;
+when KVM_CAP_SPLIT_IRQCHIP only routes of KVM_IRQ_ROUTING_MSI type are
+used in the IRQ routing table.  The first args[0] MSI routes are reserved
+for the IOAPIC pins.  Whenever the LAPIC receives an EOI for these routes,
+a KVM_EXIT_IOAPIC_EOI vmexit will be reported to userspace.
 
 Fails if VCPU has already been created, or if the irqchip is already in the
 kernel (i.e. KVM_CREATE_IRQCHIP has already been called).
 
        u64 disabled_quirks;
 
        bool irqchip_split;
+       u8 nr_reserved_ioapic_pins;
 };
 
 struct kvm_vm_stat {
 
 struct kvm_vcpu;
 
 #define IOAPIC_NUM_PINS  KVM_IOAPIC_NUM_PINS
+#define MAX_NR_RESERVED_IOAPIC_PINS KVM_MAX_IRQ_ROUTES
 #define IOAPIC_VERSION_ID 0x11 /* IOAPIC version */
 #define IOAPIC_EDGE_TRIG  0
 #define IOAPIC_LEVEL_TRIG 1
 int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state);
 int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state);
 void kvm_ioapic_scan_entry(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
+void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
 
 #endif
 
 {
        return kvm_set_irq_routing(kvm, empty_routing, 0, 0);
 }
+
+void kvm_arch_irq_routing_update(struct kvm *kvm)
+{
+       if (ioapic_in_kernel(kvm) || !irqchip_in_kernel(kvm))
+               return;
+       kvm_make_scan_ioapic_request(kvm);
+}
+
+void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
+{
+       struct kvm *kvm = vcpu->kvm;
+       struct kvm_kernel_irq_routing_entry *entry;
+       struct kvm_irq_routing_table *table;
+       u32 i, nr_ioapic_pins;
+       int idx;
+
+       /* kvm->irq_routing must be read after clearing
+        * KVM_SCAN_IOAPIC. */
+       smp_mb();
+       idx = srcu_read_lock(&kvm->irq_srcu);
+       table = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
+       nr_ioapic_pins = min_t(u32, table->nr_rt_entries,
+                              kvm->arch.nr_reserved_ioapic_pins);
+       for (i = 0; i < nr_ioapic_pins; ++i) {
+               hlist_for_each_entry(entry, &table->map[i], link) {
+                       u32 dest_id, dest_mode;
+
+                       if (entry->type != KVM_IRQ_ROUTING_MSI)
+                               continue;
+                       dest_id = (entry->msi.address_lo >> 12) & 0xff;
+                       dest_mode = (entry->msi.address_lo >> 2) & 0x1;
+                       if (kvm_apic_match_dest(vcpu, NULL, 0, dest_id,
+                                               dest_mode)) {
+                               u32 vector = entry->msi.data & 0xff;
+
+                               __set_bit(vector,
+                                         (unsigned long *) eoi_exit_bitmap);
+                       }
+               }
+       }
+       srcu_read_unlock(&kvm->irq_srcu, idx);
+}
 
        if (old)
                kfree_rcu(old, rcu);
 
-       if (ioapic_in_kernel(kvm))
-               kvm_vcpu_request_scan_ioapic(kvm);
+       kvm_make_scan_ioapic_request(kvm);
 }
 
 static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val)
 
                break;
        case KVM_CAP_SPLIT_IRQCHIP: {
                mutex_lock(&kvm->lock);
+               r = -EINVAL;
+               if (cap->args[0] > MAX_NR_RESERVED_IOAPIC_PINS)
+                       goto split_irqchip_unlock;
                r = -EEXIST;
                if (irqchip_in_kernel(kvm))
                        goto split_irqchip_unlock;
                /* Pairs with irqchip_in_kernel. */
                smp_wmb();
                kvm->arch.irqchip_split = true;
+               kvm->arch.nr_reserved_ioapic_pins = cap->args[0];
                r = 0;
 split_irqchip_unlock:
                mutex_unlock(&kvm->lock);
 
        memset(vcpu->arch.eoi_exit_bitmap, 0, 256 / 8);
 
-       kvm_ioapic_scan_entry(vcpu, vcpu->arch.eoi_exit_bitmap);
+       if (irqchip_split(vcpu->kvm))
+               kvm_scan_ioapic_routes(vcpu, vcpu->arch.eoi_exit_bitmap);
+       else
+               kvm_ioapic_scan_entry(vcpu, vcpu->arch.eoi_exit_bitmap);
        kvm_x86_ops->load_eoi_exitmap(vcpu);
 }
 
 
        struct hlist_node link;
 };
 
+#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
+struct kvm_irq_routing_table {
+       int chip[KVM_NR_IRQCHIPS][KVM_IRQCHIP_NUM_PINS];
+       u32 nr_rt_entries;
+       /*
+        * Array indexed by gsi. Each entry contains list of irq chips
+        * the gsi is connected to.
+        */
+       struct hlist_head map[0];
+};
+#endif
+
 #ifndef KVM_PRIVATE_MEM_SLOTS
 #define KVM_PRIVATE_MEM_SLOTS 0
 #endif
 
 #ifdef __KVM_HAVE_IOAPIC
 void kvm_vcpu_request_scan_ioapic(struct kvm *kvm);
+void kvm_arch_irq_routing_update(struct kvm *kvm);
 #else
 static inline void kvm_vcpu_request_scan_ioapic(struct kvm *kvm)
 {
 }
+static inline void kvm_arch_irq_routing_update(struct kvm *kvm)
+{
+}
 #endif
 
 #ifdef CONFIG_HAVE_KVM_IRQFD
 
 #include <trace/events/kvm.h>
 #include "irq.h"
 
-struct kvm_irq_routing_table {
-       int chip[KVM_NR_IRQCHIPS][KVM_IRQCHIP_NUM_PINS];
-       u32 nr_rt_entries;
-       /*
-        * Array indexed by gsi. Each entry contains list of irq chips
-        * the gsi is connected to.
-        */
-       struct hlist_head map[0];
-};
-
 int kvm_irq_map_gsi(struct kvm *kvm,
                    struct kvm_kernel_irq_routing_entry *entries, int gsi)
 {
        kvm_irq_routing_update(kvm);
        mutex_unlock(&kvm->irq_lock);
 
+       kvm_arch_irq_routing_update(kvm);
+
        synchronize_srcu_expedited(&kvm->irq_srcu);
 
        new = old;