aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm/irq_comm.c
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2009-08-24 04:54:19 -0400
committerAvi Kivity <avi@redhat.com>2009-12-03 02:32:06 -0500
commit1a6e4a8c276e122dbeb6f9c610f29735e4236bfd (patch)
treea954fc1865f41cd79e5336c59904de1213e141d5 /virt/kvm/irq_comm.c
parent79c727d4371aa9af47b0cdbcad53742b5a7919ea (diff)
KVM: Move irq sharing information to irqchip level
This removes assumptions that max GSIs is smaller than number of pins. Sharing is tracked on pin level not GSI level. [avi: no PIC on ia64] Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'virt/kvm/irq_comm.c')
-rw-r--r--virt/kvm/irq_comm.c59
1 files changed, 36 insertions, 23 deletions
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index 001663ff401a..9783f5c43dae 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -31,20 +31,39 @@
31 31
32#include "ioapic.h" 32#include "ioapic.h"
33 33
34static inline int kvm_irq_line_state(unsigned long *irq_state,
35 int irq_source_id, int level)
36{
37 /* Logical OR for level trig interrupt */
38 if (level)
39 set_bit(irq_source_id, irq_state);
40 else
41 clear_bit(irq_source_id, irq_state);
42
43 return !!(*irq_state);
44}
45
34static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e, 46static int kvm_set_pic_irq(struct kvm_kernel_irq_routing_entry *e,
35 struct kvm *kvm, int level) 47 struct kvm *kvm, int irq_source_id, int level)
36{ 48{
37#ifdef CONFIG_X86 49#ifdef CONFIG_X86
38 return kvm_pic_set_irq(pic_irqchip(kvm), e->irqchip.pin, level); 50 struct kvm_pic *pic = pic_irqchip(kvm);
51 level = kvm_irq_line_state(&pic->irq_states[e->irqchip.pin],
52 irq_source_id, level);
53 return kvm_pic_set_irq(pic, e->irqchip.pin, level);
39#else 54#else
40 return -1; 55 return -1;
41#endif 56#endif
42} 57}
43 58
44static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e, 59static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
45 struct kvm *kvm, int level) 60 struct kvm *kvm, int irq_source_id, int level)
46{ 61{
47 return kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level); 62 struct kvm_ioapic *ioapic = kvm->arch.vioapic;
63 level = kvm_irq_line_state(&ioapic->irq_states[e->irqchip.pin],
64 irq_source_id, level);
65
66 return kvm_ioapic_set_irq(ioapic, e->irqchip.pin, level);
48} 67}
49 68
50inline static bool kvm_is_dm_lowest_prio(struct kvm_lapic_irq *irq) 69inline static bool kvm_is_dm_lowest_prio(struct kvm_lapic_irq *irq)
@@ -96,10 +115,13 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src,
96} 115}
97 116
98static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, 117static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
99 struct kvm *kvm, int level) 118 struct kvm *kvm, int irq_source_id, int level)
100{ 119{
101 struct kvm_lapic_irq irq; 120 struct kvm_lapic_irq irq;
102 121
122 if (!level)
123 return -1;
124
103 trace_kvm_msi_set_irq(e->msi.address_lo, e->msi.data); 125 trace_kvm_msi_set_irq(e->msi.address_lo, e->msi.data);
104 126
105 irq.dest_id = (e->msi.address_lo & 127 irq.dest_id = (e->msi.address_lo &
@@ -125,34 +147,19 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
125int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) 147int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level)
126{ 148{
127 struct kvm_kernel_irq_routing_entry *e; 149 struct kvm_kernel_irq_routing_entry *e;
128 unsigned long *irq_state, sig_level;
129 int ret = -1; 150 int ret = -1;
130 151
131 trace_kvm_set_irq(irq, level, irq_source_id); 152 trace_kvm_set_irq(irq, level, irq_source_id);
132 153
133 WARN_ON(!mutex_is_locked(&kvm->irq_lock)); 154 WARN_ON(!mutex_is_locked(&kvm->irq_lock));
134 155
135 if (irq < KVM_IOAPIC_NUM_PINS) {
136 irq_state = (unsigned long *)&kvm->arch.irq_states[irq];
137
138 /* Logical OR for level trig interrupt */
139 if (level)
140 set_bit(irq_source_id, irq_state);
141 else
142 clear_bit(irq_source_id, irq_state);
143 sig_level = !!(*irq_state);
144 } else if (!level)
145 return ret;
146 else /* Deal with MSI/MSI-X */
147 sig_level = 1;
148
149 /* Not possible to detect if the guest uses the PIC or the 156 /* Not possible to detect if the guest uses the PIC or the
150 * IOAPIC. So set the bit in both. The guest will ignore 157 * IOAPIC. So set the bit in both. The guest will ignore
151 * writes to the unused one. 158 * writes to the unused one.
152 */ 159 */
153 list_for_each_entry(e, &kvm->irq_routing, link) 160 list_for_each_entry(e, &kvm->irq_routing, link)
154 if (e->gsi == irq) { 161 if (e->gsi == irq) {
155 int r = e->set(e, kvm, sig_level); 162 int r = e->set(e, kvm, irq_source_id, level);
156 if (r < 0) 163 if (r < 0)
157 continue; 164 continue;
158 165
@@ -232,8 +239,14 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id)
232 printk(KERN_ERR "kvm: IRQ source ID out of range!\n"); 239 printk(KERN_ERR "kvm: IRQ source ID out of range!\n");
233 return; 240 return;
234 } 241 }
235 for (i = 0; i < KVM_IOAPIC_NUM_PINS; i++) 242 for (i = 0; i < KVM_IOAPIC_NUM_PINS; i++) {
236 clear_bit(irq_source_id, &kvm->arch.irq_states[i]); 243 clear_bit(irq_source_id, &kvm->arch.vioapic->irq_states[i]);
244 if (i >= 16)
245 continue;
246#ifdef CONFIG_X86
247 clear_bit(irq_source_id, &pic_irqchip(kvm)->irq_states[i]);
248#endif
249 }
237 clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap); 250 clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap);
238 mutex_unlock(&kvm->irq_lock); 251 mutex_unlock(&kvm->irq_lock);
239} 252}