aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm/ioapic.c
diff options
context:
space:
mode:
authorYang Zhang <yang.z.zhang@Intel.com>2013-04-11 07:21:41 -0400
committerMarcelo Tosatti <mtosatti@redhat.com>2013-04-15 22:20:35 -0400
commit2c2bf01136971c33e3b3fabce23925f372c1017e (patch)
tree74a9cf21e9b520eb48fa0dab95d46c253a435818 /virt/kvm/ioapic.c
parentaa2fbe6d44892070d78995f0df875ce930904e29 (diff)
KVM: Use eoi to track RTC interrupt delivery status
Current interrupt coalescing logci which only used by RTC has conflict with Posted Interrupt. This patch introduces a new mechinism to use eoi to track interrupt: When delivering an interrupt to vcpu, the pending_eoi set to number of vcpu that received the interrupt. And decrease it when each vcpu writing eoi. No subsequent RTC interrupt can deliver to vcpu until all vcpus write eoi. Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com> Reviewed-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'virt/kvm/ioapic.c')
-rw-r--r--virt/kvm/ioapic.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index a49fcd55b378..97c67a50f904 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -147,6 +147,22 @@ static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic)
147 __rtc_irq_eoi_tracking_restore_one(vcpu); 147 __rtc_irq_eoi_tracking_restore_one(vcpu);
148} 148}
149 149
150static void rtc_irq_eoi(struct kvm_ioapic *ioapic, struct kvm_vcpu *vcpu)
151{
152 if (test_and_clear_bit(vcpu->vcpu_id, ioapic->rtc_status.dest_map))
153 --ioapic->rtc_status.pending_eoi;
154
155 WARN_ON(ioapic->rtc_status.pending_eoi < 0);
156}
157
158static bool rtc_irq_check_coalesced(struct kvm_ioapic *ioapic)
159{
160 if (ioapic->rtc_status.pending_eoi > 0)
161 return true; /* coalesced */
162
163 return false;
164}
165
150static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx, 166static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx,
151 bool line_status) 167 bool line_status)
152{ 168{
@@ -260,6 +276,7 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq, bool line_status)
260{ 276{
261 union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq]; 277 union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq];
262 struct kvm_lapic_irq irqe; 278 struct kvm_lapic_irq irqe;
279 int ret;
263 280
264 ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x " 281 ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x "
265 "vector=%x trig_mode=%x\n", 282 "vector=%x trig_mode=%x\n",
@@ -275,7 +292,15 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq, bool line_status)
275 irqe.level = 1; 292 irqe.level = 1;
276 irqe.shorthand = 0; 293 irqe.shorthand = 0;
277 294
278 return kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe, NULL); 295 if (irq == RTC_GSI && line_status) {
296 BUG_ON(ioapic->rtc_status.pending_eoi != 0);
297 ret = kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe,
298 ioapic->rtc_status.dest_map);
299 ioapic->rtc_status.pending_eoi = ret;
300 } else
301 ret = kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe, NULL);
302
303 return ret;
279} 304}
280 305
281int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int irq_source_id, 306int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int irq_source_id,
@@ -299,6 +324,12 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int irq_source_id,
299 ret = 1; 324 ret = 1;
300 } else { 325 } else {
301 int edge = (entry.fields.trig_mode == IOAPIC_EDGE_TRIG); 326 int edge = (entry.fields.trig_mode == IOAPIC_EDGE_TRIG);
327
328 if (irq == RTC_GSI && line_status &&
329 rtc_irq_check_coalesced(ioapic)) {
330 ret = 0; /* coalesced */
331 goto out;
332 }
302 ioapic->irr |= mask; 333 ioapic->irr |= mask;
303 if ((edge && old_irr != ioapic->irr) || 334 if ((edge && old_irr != ioapic->irr) ||
304 (!edge && !entry.fields.remote_irr)) 335 (!edge && !entry.fields.remote_irr))
@@ -306,6 +337,7 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int irq_source_id,
306 else 337 else
307 ret = 0; /* report coalesced interrupt */ 338 ret = 0; /* report coalesced interrupt */
308 } 339 }
340out:
309 trace_kvm_ioapic_set_irq(entry.bits, irq, ret == 0); 341 trace_kvm_ioapic_set_irq(entry.bits, irq, ret == 0);
310 spin_unlock(&ioapic->lock); 342 spin_unlock(&ioapic->lock);
311 343
@@ -333,6 +365,8 @@ static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu,
333 if (ent->fields.vector != vector) 365 if (ent->fields.vector != vector)
334 continue; 366 continue;
335 367
368 if (i == RTC_GSI)
369 rtc_irq_eoi(ioapic, vcpu);
336 /* 370 /*
337 * We are dropping lock while calling ack notifiers because ack 371 * We are dropping lock while calling ack notifiers because ack
338 * notifier callbacks for assigned devices call into IOAPIC 372 * notifier callbacks for assigned devices call into IOAPIC