public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] avoid redeliver of edge interrupt before next edge
@ 2009-07-05 15:48 Gleb Natapov
  2009-07-05 15:48 ` [PATCH 2/2] Use temporary variable to shorten lines Gleb Natapov
  2009-07-05 15:58 ` [PATCH 1/2] avoid redeliver of edge interrupt before next edge Avi Kivity
  0 siblings, 2 replies; 3+ messages in thread
From: Gleb Natapov @ 2009-07-05 15:48 UTC (permalink / raw)
  To: avi; +Cc: kvm

The check for an edge is broken in current ioapic code. ioapic->irr is
cleared on each edge interrupt by ioapic_service() and this makes
old_irr != ioapic->irr condition in kvm_ioapic_set_irq() to be always
true. The patch fixes the code to properly recognise edge.

Some HW emulation calls set_irq() without level change. If each such
call is propagated to an OS it may confuse a device driver. This is the
case with keyboard device emulation and WindowsXP installer on SMP VM.
Each button stroke produce two interrupts (down/up) one interrupt is
submitted to CPU0 and another to CPU1. This confuses Windows somehow
and it ignores button strokes.

Signed-off-by: Gleb Natapov <gleb@redhat.com>
---

Same patch as before but split in two. First one fixes bug, second
make cosmetic changes.

 virt/kvm/ioapic.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index 124ecf7..8a9c6cc 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -95,8 +95,6 @@ static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx)
 		if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG)
 			pent->fields.remote_irr = 1;
 	}
-	if (!pent->fields.trig_mode)
-		ioapic->irr &= ~(1 << idx);
 
 	return injected;
 }
@@ -136,7 +134,8 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val)
 		mask_after = ioapic->redirtbl[index].fields.mask;
 		if (mask_before != mask_after)
 			kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after);
-		if (ioapic->irr & (1 << index))
+		if (ioapic->redirtbl[index].fields.trig_mode == IOAPIC_LEVEL_TRIG
+		    && ioapic->irr & (1 << index))
 			ioapic_service(ioapic, index);
 		break;
 	}
@@ -186,9 +185,10 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level)
 		if (!level)
 			ioapic->irr &= ~mask;
 		else {
+			int edge = (entry.fields.trig_mode == IOAPIC_EDGE_TRIG);
 			ioapic->irr |= mask;
-			if ((!entry.fields.trig_mode && old_irr != ioapic->irr)
-			    || !entry.fields.remote_irr)
+			if ((edge && old_irr != ioapic->irr) ||
+			    (!edge && !entry.fields.remote_irr))
 				ret = ioapic_service(ioapic, irq);
 		}
 	}
-- 
1.6.2.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-07-05 15:55 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-05 15:48 [PATCH 1/2] avoid redeliver of edge interrupt before next edge Gleb Natapov
2009-07-05 15:48 ` [PATCH 2/2] Use temporary variable to shorten lines Gleb Natapov
2009-07-05 15:58 ` [PATCH 1/2] avoid redeliver of edge interrupt before next edge Avi Kivity

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox