diff options
author | Gleb Natapov <gleb@redhat.com> | 2009-03-05 09:35:04 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-06-10 04:48:27 -0400 |
commit | 58c2dde17d6eb6c8c0566e52d184aa16755d890f (patch) | |
tree | a968731cbce73932decd63e00be313cebfd2f57f /virt/kvm/irq_comm.c | |
parent | e1035715ef8d3171e29f9c6aee6f40d57b3fead5 (diff) |
KVM: APIC: get rid of deliver_bitmask
Deliver interrupt during destination matching loop.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Acked-by: Xiantao Zhang <xiantao.zhang@intel.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'virt/kvm/irq_comm.c')
-rw-r--r-- | virt/kvm/irq_comm.c | 71 |
1 files changed, 42 insertions, 29 deletions
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index f5e059b67cd4..4fa1f604b425 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c | |||
@@ -22,6 +22,9 @@ | |||
22 | #include <linux/kvm_host.h> | 22 | #include <linux/kvm_host.h> |
23 | 23 | ||
24 | #include <asm/msidef.h> | 24 | #include <asm/msidef.h> |
25 | #ifdef CONFIG_IA64 | ||
26 | #include <asm/iosapic.h> | ||
27 | #endif | ||
25 | 28 | ||
26 | #include "irq.h" | 29 | #include "irq.h" |
27 | 30 | ||
@@ -43,61 +46,71 @@ static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e, | |||
43 | return kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level); | 46 | return kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level); |
44 | } | 47 | } |
45 | 48 | ||
46 | void kvm_get_intr_delivery_bitmask(struct kvm *kvm, struct kvm_lapic *src, | 49 | inline static bool kvm_is_dm_lowest_prio(struct kvm_lapic_irq *irq) |
47 | int dest_id, int dest_mode, bool low_prio, int short_hand, | ||
48 | unsigned long *deliver_bitmask) | ||
49 | { | 50 | { |
50 | int i, lowest = -1; | 51 | #ifdef CONFIG_IA64 |
51 | struct kvm_vcpu *vcpu; | 52 | return irq->delivery_mode == |
53 | (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT); | ||
54 | #else | ||
55 | return irq->delivery_mode == APIC_DM_LOWEST; | ||
56 | #endif | ||
57 | } | ||
52 | 58 | ||
53 | if (dest_mode == 0 && dest_id == 0xff && low_prio) | 59 | int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src, |
60 | struct kvm_lapic_irq *irq) | ||
61 | { | ||
62 | int i, r = -1; | ||
63 | struct kvm_vcpu *vcpu, *lowest = NULL; | ||
64 | |||
65 | if (irq->dest_mode == 0 && irq->dest_id == 0xff && | ||
66 | kvm_is_dm_lowest_prio(irq)) | ||
54 | printk(KERN_INFO "kvm: apic: phys broadcast and lowest prio\n"); | 67 | printk(KERN_INFO "kvm: apic: phys broadcast and lowest prio\n"); |
55 | 68 | ||
56 | bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS); | ||
57 | for (i = 0; i < KVM_MAX_VCPUS; i++) { | 69 | for (i = 0; i < KVM_MAX_VCPUS; i++) { |
58 | vcpu = kvm->vcpus[i]; | 70 | vcpu = kvm->vcpus[i]; |
59 | 71 | ||
60 | if (!vcpu || !kvm_apic_present(vcpu)) | 72 | if (!vcpu || !kvm_apic_present(vcpu)) |
61 | continue; | 73 | continue; |
62 | 74 | ||
63 | if (!kvm_apic_match_dest(vcpu, src, short_hand, dest_id, | 75 | if (!kvm_apic_match_dest(vcpu, src, irq->shorthand, |
64 | dest_mode)) | 76 | irq->dest_id, irq->dest_mode)) |
65 | continue; | 77 | continue; |
66 | 78 | ||
67 | if (!low_prio) { | 79 | if (!kvm_is_dm_lowest_prio(irq)) { |
68 | __set_bit(i, deliver_bitmask); | 80 | if (r < 0) |
81 | r = 0; | ||
82 | r += kvm_apic_set_irq(vcpu, irq); | ||
69 | } else { | 83 | } else { |
70 | if (lowest < 0) | 84 | if (!lowest) |
71 | lowest = i; | 85 | lowest = vcpu; |
72 | if (kvm_apic_compare_prio(vcpu, kvm->vcpus[lowest]) < 0) | 86 | else if (kvm_apic_compare_prio(vcpu, lowest) < 0) |
73 | lowest = i; | 87 | lowest = vcpu; |
74 | } | 88 | } |
75 | } | 89 | } |
76 | 90 | ||
77 | if (lowest != -1) | 91 | if (lowest) |
78 | __set_bit(lowest, deliver_bitmask); | 92 | r = kvm_apic_set_irq(lowest, irq); |
93 | |||
94 | return r; | ||
79 | } | 95 | } |
80 | 96 | ||
81 | static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, | 97 | static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, |
82 | struct kvm *kvm, int level) | 98 | struct kvm *kvm, int level) |
83 | { | 99 | { |
84 | union kvm_ioapic_redirect_entry entry; | 100 | struct kvm_lapic_irq irq; |
85 | 101 | ||
86 | entry.bits = 0; | 102 | irq.dest_id = (e->msi.address_lo & |
87 | entry.fields.dest_id = (e->msi.address_lo & | ||
88 | MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT; | 103 | MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT; |
89 | entry.fields.vector = (e->msi.data & | 104 | irq.vector = (e->msi.data & |
90 | MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT; | 105 | MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT; |
91 | entry.fields.dest_mode = test_bit(MSI_ADDR_DEST_MODE_SHIFT, | 106 | irq.dest_mode = (1 << MSI_ADDR_DEST_MODE_SHIFT) & e->msi.address_lo; |
92 | (unsigned long *)&e->msi.address_lo); | 107 | irq.trig_mode = (1 << MSI_DATA_TRIGGER_SHIFT) & e->msi.data; |
93 | entry.fields.trig_mode = test_bit(MSI_DATA_TRIGGER_SHIFT, | 108 | irq.delivery_mode = e->msi.data & 0x700; |
94 | (unsigned long *)&e->msi.data); | 109 | irq.level = 1; |
95 | entry.fields.delivery_mode = test_bit( | 110 | irq.shorthand = 0; |
96 | MSI_DATA_DELIVERY_MODE_SHIFT, | ||
97 | (unsigned long *)&e->msi.data); | ||
98 | 111 | ||
99 | /* TODO Deal with RH bit of MSI message address */ | 112 | /* TODO Deal with RH bit of MSI message address */ |
100 | return ioapic_deliver_entry(kvm, &entry); | 113 | return kvm_irq_delivery_to_apic(kvm, NULL, &irq); |
101 | } | 114 | } |
102 | 115 | ||
103 | /* This should be called with the kvm->lock mutex held | 116 | /* This should be called with the kvm->lock mutex held |