diff options
author | Feng Wu <feng.wu@intel.com> | 2015-09-18 10:29:47 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2015-10-01 09:06:49 -0400 |
commit | 8feb4a04dc756002f78df0026e58118669de4851 (patch) | |
tree | 5805a8d7b71c693d71dacf1d417d1f600732cef9 | |
parent | ebbfc765369690cf8fc512615e6b83ec1702f8ac (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.h | 3 | ||||
-rw-r--r-- | arch/x86/kvm/irq_comm.c | 27 | ||||
-rw-r--r-- | arch/x86/kvm/lapic.c | 59 | ||||
-rw-r--r-- | arch/x86/kvm/lapic.h | 2 |
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, | |||
1241 | bool kvm_vcpu_is_reset_bsp(struct kvm_vcpu *vcpu); | 1241 | bool kvm_vcpu_is_reset_bsp(struct kvm_vcpu *vcpu); |
1242 | bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu); | 1242 | bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu); |
1243 | 1243 | ||
1244 | bool 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 | ||
300 | bool 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 | } | ||
325 | EXPORT_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 | ||
758 | bool 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; | ||
812 | out: | ||
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 | ||
169 | void wait_lapic_expire(struct kvm_vcpu *vcpu); | 169 | void wait_lapic_expire(struct kvm_vcpu *vcpu); |
170 | 170 | ||
171 | bool kvm_intr_is_single_vcpu_fast(struct kvm *kvm, struct kvm_lapic_irq *irq, | ||
172 | struct kvm_vcpu **dest_vcpu); | ||
171 | #endif | 173 | #endif |