x86, apicv: add virtual interrupt delivery support
[deliverable/linux.git] / arch / x86 / kvm / irq.c
index b111aee815f811b60806c8e4849ece5daae04fdb..484bc874688b4ba2bfb8199702671779ffd69d2f 100644 (file)
@@ -37,6 +37,38 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL(kvm_cpu_has_pending_timer);
 
+/*
+ * check if there is pending interrupt from
+ * non-APIC source without intack.
+ */
+static int kvm_cpu_has_extint(struct kvm_vcpu *v)
+{
+       if (kvm_apic_accept_pic_intr(v))
+               return pic_irqchip(v->kvm)->output;     /* PIC */
+       else
+               return 0;
+}
+
+/*
+ * check if there is injectable interrupt:
+ * when virtual interrupt delivery enabled,
+ * interrupt from apic will handled by hardware,
+ * we don't need to check it here.
+ */
+int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v)
+{
+       if (!irqchip_in_kernel(v->kvm))
+               return v->arch.interrupt.pending;
+
+       if (kvm_cpu_has_extint(v))
+               return 1;
+
+       if (kvm_apic_vid_enabled(v->kvm))
+               return 0;
+
+       return kvm_apic_has_interrupt(v) != -1; /* LAPIC */
+}
+
 /*
  * check if there is pending interrupt without
  * intack.
@@ -46,27 +78,41 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
        if (!irqchip_in_kernel(v->kvm))
                return v->arch.interrupt.pending;
 
-       if (kvm_apic_accept_pic_intr(v) && pic_irqchip(v->kvm)->output)
-               return pic_irqchip(v->kvm)->output;     /* PIC */
+       if (kvm_cpu_has_extint(v))
+               return 1;
 
        return kvm_apic_has_interrupt(v) != -1; /* LAPIC */
 }
 EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt);
 
+/*
+ * Read pending interrupt(from non-APIC source)
+ * vector and intack.
+ */
+static int kvm_cpu_get_extint(struct kvm_vcpu *v)
+{
+       if (kvm_cpu_has_extint(v))
+               return kvm_pic_read_irq(v->kvm); /* PIC */
+       return -1;
+}
+
 /*
  * Read pending interrupt vector and intack.
  */
 int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
 {
+       int vector;
+
        if (!irqchip_in_kernel(v->kvm))
                return v->arch.interrupt.nr;
 
-       if (kvm_apic_accept_pic_intr(v) && pic_irqchip(v->kvm)->output)
-               return kvm_pic_read_irq(v->kvm);        /* PIC */
+       vector = kvm_cpu_get_extint(v);
+
+       if (kvm_apic_vid_enabled(v->kvm) || vector != -1)
+               return vector;                  /* PIC */
 
        return kvm_get_apic_interrupt(v);       /* APIC */
 }
-EXPORT_SYMBOL_GPL(kvm_cpu_get_interrupt);
 
 void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu)
 {
This page took 0.027676 seconds and 5 git commands to generate.