aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFeng Wu <feng.wu@intel.com>2015-09-18 10:29:47 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2015-10-01 09:06:49 -0400
commit8feb4a04dc756002f78df0026e58118669de4851 (patch)
tree5805a8d7b71c693d71dacf1d417d1f600732cef9
parentebbfc765369690cf8fc512615e6b83ec1702f8ac (diff)
KVM: Define a new interface kvm_intr_is_single_vcpu()
This patch defines a new interface kvm_intr_is_single_vcpu(), which can returns whether the interrupt is for single-CPU or not. It is used by VT-d PI, since now we only support single-CPU interrupts, For lowest-priority interrupts, if user configures it via /proc/irq or uses irqbalance to make it single-CPU, we can use PI to deliver the interrupts to it. Full functionality of lowest-priority support will be added later. Signed-off-by: Feng Wu <feng.wu@intel.com> Reviewed-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/include/asm/kvm_host.h3
-rw-r--r--arch/x86/kvm/irq_comm.c27
-rw-r--r--arch/x86/kvm/lapic.c59
-rw-r--r--arch/x86/kvm/lapic.h2
4 files changed, 91 insertions, 0 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index d064cb2e19e8..ba4e5673e604 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1241,4 +1241,7 @@ int x86_set_memory_region(struct kvm *kvm,
1241bool kvm_vcpu_is_reset_bsp(struct kvm_vcpu *vcpu); 1241bool kvm_vcpu_is_reset_bsp(struct kvm_vcpu *vcpu);
1242bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu); 1242bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu);
1243 1243
1244bool kvm_intr_is_single_vcpu(struct kvm *kvm, struct kvm_lapic_irq *irq,
1245 struct kvm_vcpu **dest_vcpu);
1246
1244#endif /* _ASM_X86_KVM_HOST_H */ 1247#endif /* _ASM_X86_KVM_HOST_H */
diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c
index 177460998bb0..39f833f8132e 100644
--- a/arch/x86/kvm/irq_comm.c
+++ b/arch/x86/kvm/irq_comm.c
@@ -297,6 +297,33 @@ out:
297 return r; 297 return r;
298} 298}
299 299
300bool kvm_intr_is_single_vcpu(struct kvm *kvm, struct kvm_lapic_irq *irq,
301 struct kvm_vcpu **dest_vcpu)
302{
303 int i, r = 0;
304 struct kvm_vcpu *vcpu;
305
306 if (kvm_intr_is_single_vcpu_fast(kvm, irq, dest_vcpu))
307 return true;
308
309 kvm_for_each_vcpu(i, vcpu, kvm) {
310 if (!kvm_apic_present(vcpu))
311 continue;
312
313 if (!kvm_apic_match_dest(vcpu, NULL, irq->shorthand,
314 irq->dest_id, irq->dest_mode))
315 continue;
316
317 if (++r == 2)
318 return false;
319
320 *dest_vcpu = vcpu;
321 }
322
323 return r == 1;
324}
325EXPORT_SYMBOL_GPL(kvm_intr_is_single_vcpu);
326
300#define IOAPIC_ROUTING_ENTRY(irq) \ 327#define IOAPIC_ROUTING_ENTRY(irq) \
301 { .gsi = irq, .type = KVM_IRQ_ROUTING_IRQCHIP, \ 328 { .gsi = irq, .type = KVM_IRQ_ROUTING_IRQCHIP, \
302 .u.irqchip = { .irqchip = KVM_IRQCHIP_IOAPIC, .pin = (irq) } } 329 .u.irqchip = { .irqchip = KVM_IRQCHIP_IOAPIC, .pin = (irq) } }
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 2f4c0d0cbe0a..944b38a56929 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -755,6 +755,65 @@ out:
755 return ret; 755 return ret;
756} 756}
757 757
758bool kvm_intr_is_single_vcpu_fast(struct kvm *kvm, struct kvm_lapic_irq *irq,
759 struct kvm_vcpu **dest_vcpu)
760{
761 struct kvm_apic_map *map;
762 bool ret = false;
763 struct kvm_lapic *dst = NULL;
764
765 if (irq->shorthand)
766 return false;
767
768 rcu_read_lock();
769 map = rcu_dereference(kvm->arch.apic_map);
770
771 if (!map)
772 goto out;
773
774 if (irq->dest_mode == APIC_DEST_PHYSICAL) {
775 if (irq->dest_id == 0xFF)
776 goto out;
777
778 if (irq->dest_id >= ARRAY_SIZE(map->phys_map))
779 goto out;
780
781 dst = map->phys_map[irq->dest_id];
782 if (dst && kvm_apic_present(dst->vcpu))
783 *dest_vcpu = dst->vcpu;
784 else
785 goto out;
786 } else {
787 u16 cid;
788 unsigned long bitmap = 1;
789 int i, r = 0;
790
791 if (!kvm_apic_logical_map_valid(map))
792 goto out;
793
794 apic_logical_id(map, irq->dest_id, &cid, (u16 *)&bitmap);
795
796 if (cid >= ARRAY_SIZE(map->logical_map))
797 goto out;
798
799 for_each_set_bit(i, &bitmap, 16) {
800 dst = map->logical_map[cid][i];
801 if (++r == 2)
802 goto out;
803 }
804
805 if (dst && kvm_apic_present(dst->vcpu))
806 *dest_vcpu = dst->vcpu;
807 else
808 goto out;
809 }
810
811 ret = true;
812out:
813 rcu_read_unlock();
814 return ret;
815}
816
758/* 817/*
759 * Add a pending IRQ into lapic. 818 * Add a pending IRQ into lapic.
760 * Return 1 if successfully added and 0 if discarded. 819 * Return 1 if successfully added and 0 if discarded.
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 7259d272416f..fde8e35d5850 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -168,4 +168,6 @@ bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector);
168 168
169void wait_lapic_expire(struct kvm_vcpu *vcpu); 169void wait_lapic_expire(struct kvm_vcpu *vcpu);
170 170
171bool kvm_intr_is_single_vcpu_fast(struct kvm *kvm, struct kvm_lapic_irq *irq,
172 struct kvm_vcpu **dest_vcpu);
171#endif 173#endif