Merge tag 'upstream-4.12-rc1' of git://git.infradead.org/linux-ubifs
[linux-2.6-block.git] / arch / x86 / kvm / irq_comm.c
index 6c0191615f23a34bae5c0972a20025cf5b695af9..3cc3b2d130a0c277e6b4cb6f59aa2a391d2253f6 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/kvm_host.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/rculist.h>
+
 #include <trace/events/kvm.h>
 
 #include <asm/msidef.h>
@@ -40,16 +42,7 @@ static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
                           struct kvm *kvm, int irq_source_id, int level,
                           bool line_status)
 {
-       struct kvm_pic *pic = pic_irqchip(kvm);
-
-       /*
-        * XXX: rejecting pic routes when pic isn't in use would be better,
-        * but the default routing table is installed while kvm->arch.vpic is
-        * NULL and KVM_CREATE_IRQCHIP can race with KVM_IRQ_LINE.
-        */
-       if (!pic)
-               return -1;
-
+       struct kvm_pic *pic = kvm->arch.vpic;
        return kvm_pic_set_irq(pic, e->irqchip.pin, irq_source_id, level);
 }
 
@@ -58,10 +51,6 @@ static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
                              bool line_status)
 {
        struct kvm_ioapic *ioapic = kvm->arch.vioapic;
-
-       if (!ioapic)
-               return -1;
-
        return kvm_ioapic_set_irq(ioapic, e->irqchip.pin, irq_source_id, level,
                                line_status);
 }
@@ -243,11 +232,11 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id)
                goto unlock;
        }
        clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap);
-       if (!ioapic_in_kernel(kvm))
+       if (!irqchip_kernel(kvm))
                goto unlock;
 
        kvm_ioapic_clear_all(kvm->arch.vioapic, irq_source_id);
-       kvm_pic_clear_all(pic_irqchip(kvm), irq_source_id);
+       kvm_pic_clear_all(kvm->arch.vpic, irq_source_id);
 unlock:
        mutex_unlock(&kvm->irq_lock);
 }
@@ -285,38 +274,42 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
        srcu_read_unlock(&kvm->irq_srcu, idx);
 }
 
+bool kvm_arch_can_set_irq_routing(struct kvm *kvm)
+{
+       return irqchip_in_kernel(kvm);
+}
+
 int kvm_set_routing_entry(struct kvm *kvm,
                          struct kvm_kernel_irq_routing_entry *e,
                          const struct kvm_irq_routing_entry *ue)
 {
-       int r = -EINVAL;
-       int delta;
-       unsigned max_pin;
-
+       /* We can't check irqchip_in_kernel() here as some callers are
+        * currently inititalizing the irqchip. Other callers should therefore
+        * check kvm_arch_can_set_irq_routing() before calling this function.
+        */
        switch (ue->type) {
        case KVM_IRQ_ROUTING_IRQCHIP:
-               delta = 0;
+               if (irqchip_split(kvm))
+                       return -EINVAL;
+               e->irqchip.pin = ue->u.irqchip.pin;
                switch (ue->u.irqchip.irqchip) {
-               case KVM_IRQCHIP_PIC_MASTER:
-                       e->set = kvm_set_pic_irq;
-                       max_pin = PIC_NUM_PINS;
-                       break;
                case KVM_IRQCHIP_PIC_SLAVE:
+                       e->irqchip.pin += PIC_NUM_PINS / 2;
+                       /* fall through */
+               case KVM_IRQCHIP_PIC_MASTER:
+                       if (ue->u.irqchip.pin >= PIC_NUM_PINS / 2)
+                               return -EINVAL;
                        e->set = kvm_set_pic_irq;
-                       max_pin = PIC_NUM_PINS;
-                       delta = 8;
                        break;
                case KVM_IRQCHIP_IOAPIC:
-                       max_pin = KVM_IOAPIC_NUM_PINS;
+                       if (ue->u.irqchip.pin >= KVM_IOAPIC_NUM_PINS)
+                               return -EINVAL;
                        e->set = kvm_set_ioapic_irq;
                        break;
                default:
-                       goto out;
+                       return -EINVAL;
                }
                e->irqchip.irqchip = ue->u.irqchip.irqchip;
-               e->irqchip.pin = ue->u.irqchip.pin + delta;
-               if (e->irqchip.pin >= max_pin)
-                       goto out;
                break;
        case KVM_IRQ_ROUTING_MSI:
                e->set = kvm_set_msi;
@@ -325,7 +318,7 @@ int kvm_set_routing_entry(struct kvm *kvm,
                e->msi.data = ue->u.msi.data;
 
                if (kvm_msi_route_invalid(kvm, e))
-                       goto out;
+                       return -EINVAL;
                break;
        case KVM_IRQ_ROUTING_HV_SINT:
                e->set = kvm_hv_set_sint;
@@ -333,12 +326,10 @@ int kvm_set_routing_entry(struct kvm *kvm,
                e->hv_sint.sint = ue->u.hv_sint.sint;
                break;
        default:
-               goto out;
+               return -EINVAL;
        }
 
-       r = 0;
-out:
-       return r;
+       return 0;
 }
 
 bool kvm_intr_is_single_vcpu(struct kvm *kvm, struct kvm_lapic_irq *irq,
@@ -409,7 +400,7 @@ int kvm_setup_empty_irq_routing(struct kvm *kvm)
 
 void kvm_arch_post_irq_routing_update(struct kvm *kvm)
 {
-       if (ioapic_in_kernel(kvm) || !irqchip_in_kernel(kvm))
+       if (!irqchip_split(kvm))
                return;
        kvm_make_scan_ioapic_request(kvm);
 }