[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 3 of 4] [qemu ppc uic] Remember the state of level-t
From: |
Hollis Blanchard |
Subject: |
[Qemu-devel] [PATCH 3 of 4] [qemu ppc uic] Remember the state of level-triggered interrupts |
Date: |
Wed, 23 Apr 2008 17:23:54 -0500 |
This fixes the following race condition:
1. target handles an interrupt and begins to EOI
2. device raises an interrupt, setting UIC SR
3. target finishes EOI by clearing SR bit
On hardware, a device with a level-triggered interrupt would instantly
re-assert SR after step 3, so we need to do the same.
Signed-off-by: Hollis Blanchard <address@hidden>
diff --git a/qemu/hw/ppc4xx_devs.c b/qemu/hw/ppc4xx_devs.c
--- a/qemu/hw/ppc4xx_devs.c
+++ b/qemu/hw/ppc4xx_devs.c
@@ -278,6 +278,7 @@
struct ppcuic_t {
uint32_t dcr_base;
int use_vectors;
+ uint32_t level; /* Remembers the state of level-triggered interrupts. */
uint32_t uicsr; /* Status register */
uint32_t uicer; /* Enable register */
uint32_t uiccr; /* Critical register */
@@ -385,10 +386,13 @@
uic->uicsr |= mask;
} else {
/* Level sensitive interrupt */
- if (level == 1)
+ if (level == 1) {
uic->uicsr |= mask;
- else
+ uic->level |= mask;
+ } else {
uic->uicsr &= ~mask;
+ uic->level &= ~mask;
+ }
}
#ifdef DEBUG_UIC
if (loglevel & CPU_LOG_INT) {
@@ -460,6 +464,7 @@
switch (dcrn) {
case DCR_UICSR:
uic->uicsr &= ~val;
+ uic->uicsr |= uic->level;
ppcuic_trigger_irq(uic);
break;
case DCR_UICSRS: