dev-arm: Gicv3 maintenance interrupt never cleared
authorGiacomo Travaglini <giacomo.travaglini@arm.com>
Mon, 20 Jul 2020 09:39:44 +0000 (10:39 +0100)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Thu, 23 Jul 2020 16:51:03 +0000 (16:51 +0000)
The maintenance interrupt is a level sensitive interrupt though it has
been treated as edge triggered so far.

In order to be level sensitive, it needs to be cleared once the condition
which led to its generation are not valid anymore.

Change-Id: I9af9f4bf27622a7961393b00a145d6c9835d738b
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/31614
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/dev/arm/gic_v3_cpu_interface.cc

index 5e1f8719e0d744116005bc51deadf9d361ad9daa..5499e386d00d0be47f74f84d99c2b6404ebfcba1 100644 (file)
@@ -79,6 +79,8 @@ void
 Gicv3CPUInterface::setThreadContext(ThreadContext *tc)
 {
     maintenanceInterrupt = gic->params()->maint_int->get(tc);
+    fatal_if(maintenanceInterrupt->num() >= redistributor->irqPending.size(),
+        "Invalid maintenance interrupt number\n");
 }
 
 bool
@@ -2078,10 +2080,13 @@ Gicv3CPUInterface::virtualUpdate()
 
     ICH_HCR_EL2 ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
 
-    if (ich_hcr_el2.En) {
-        if (maintenanceInterruptStatus()) {
-            maintenanceInterrupt->raise();
-        }
+    const bool maint_pending = redistributor->irqPending[
+        maintenanceInterrupt->num()];
+
+    if (ich_hcr_el2.En && !maint_pending && maintenanceInterruptStatus()) {
+        maintenanceInterrupt->raise();
+    } else if (maint_pending) {
+        maintenanceInterrupt->clear();
     }
 
     if (signal_IRQ) {