All of lore.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.