Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux...
[cascardo/linux.git] / virt / kvm / ioapic.c
index cfb7e4d..ce82b94 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/hrtimer.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/current.h>
@@ -115,6 +116,42 @@ static void update_handled_vectors(struct kvm_ioapic *ioapic)
        smp_wmb();
 }
 
+void kvm_ioapic_calculate_eoi_exitmap(struct kvm_vcpu *vcpu,
+                                       u64 *eoi_exit_bitmap)
+{
+       struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic;
+       union kvm_ioapic_redirect_entry *e;
+       struct kvm_lapic_irq irqe;
+       int index;
+
+       spin_lock(&ioapic->lock);
+       /* traverse ioapic entry to set eoi exit bitmap*/
+       for (index = 0; index < IOAPIC_NUM_PINS; index++) {
+               e = &ioapic->redirtbl[index];
+               if (!e->fields.mask &&
+                       (e->fields.trig_mode == IOAPIC_LEVEL_TRIG ||
+                        kvm_irq_has_notifier(ioapic->kvm, KVM_IRQCHIP_IOAPIC,
+                                index))) {
+                       irqe.dest_id = e->fields.dest_id;
+                       irqe.vector = e->fields.vector;
+                       irqe.dest_mode = e->fields.dest_mode;
+                       irqe.delivery_mode = e->fields.delivery_mode << 8;
+                       kvm_calculate_eoi_exitmap(vcpu, &irqe, eoi_exit_bitmap);
+               }
+       }
+       spin_unlock(&ioapic->lock);
+}
+EXPORT_SYMBOL_GPL(kvm_ioapic_calculate_eoi_exitmap);
+
+void kvm_ioapic_make_eoibitmap_request(struct kvm *kvm)
+{
+       struct kvm_ioapic *ioapic = kvm->arch.vioapic;
+
+       if (!kvm_apic_vid_enabled(kvm) || !ioapic)
+               return;
+       kvm_make_update_eoibitmap_request(kvm);
+}
+
 static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
 {
        unsigned index;
@@ -156,6 +193,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
                if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG
                    && ioapic->irr & (1 << index))
                        ioapic_service(ioapic, index);
+               kvm_ioapic_make_eoibitmap_request(ioapic->kvm);
                break;
        }
 }
@@ -179,15 +217,6 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq)
        irqe.level = 1;
        irqe.shorthand = 0;
 
-#ifdef CONFIG_X86
-       /* Always delivery PIT interrupt to vcpu 0 */
-       if (irq == 0) {
-               irqe.dest_mode = 0; /* Physical mode. */
-               /* need to read apic_id from apic regiest since
-                * it can be rewritten */
-               irqe.dest_id = ioapic->kvm->bsp_vcpu_id;
-       }
-#endif
        return kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe);
 }
 
@@ -464,6 +493,7 @@ int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state)
        spin_lock(&ioapic->lock);
        memcpy(ioapic, state, sizeof(struct kvm_ioapic_state));
        update_handled_vectors(ioapic);
+       kvm_ioapic_make_eoibitmap_request(kvm);
        spin_unlock(&ioapic->lock);
        return 0;
 }