dev-arm: Implement Level Sensitive PPIs in GICv2
authorGiacomo Travaglini <giacomo.travaglini@arm.com>
Tue, 7 Jul 2020 11:41:52 +0000 (12:41 +0100)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Sat, 11 Jul 2020 07:50:24 +0000 (07:50 +0000)
JIRA: https://gem5.atlassian.net/browse/GEM5-667

Change-Id: I9ae411110f08f4a1de95469ff5ed6788354abafc
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/31056
Reviewed-by: Hsuan Hsu <kugwa2000@gmail.com>
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_v2.cc
src/dev/arm/gic_v2.hh

index 302da2f26fd85f21dc6496a9635051065d1095c4..1a6954d6eb54d2588aa4d6a0e0796119c848bfed 100644 (file)
@@ -343,7 +343,9 @@ GicV2::readCpu(ContextID ctx, Addr daddr)
                 uint32_t int_num = 1 << (cpuHighestInt[ctx] - SGI_MAX);
                 cpuPpiActive[ctx] |= int_num;
                 updateRunPri();
-                cpuPpiPending[ctx] &= ~int_num;
+                if (!isLevelSensitive(ctx, active_int)) {
+                    cpuPpiPending[ctx] &= ~int_num;
+                }
 
             } else {
                 uint32_t int_num = 1 << intNumToBit(cpuHighestInt[ctx]);
@@ -518,7 +520,10 @@ GicV2::writeDistributor(ContextID ctx, Addr daddr, uint32_t data,
 
     if (GICD_ICFGR.contains(daddr)) {
         uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2;
-        getIntConfig(ctx, ix) = data;
+        // Since the GICD_ICFGR0 is RO (WI), we are discarding the write
+        // if ix = 0
+        if (ix != 0)
+            getIntConfig(ctx, ix) = data;
         if (data & NN_CONFIG_MASK)
             warn("GIC N:N mode selected and not supported at this time\n");
         return;
@@ -897,10 +902,16 @@ GicV2::clearInt(uint32_t num)
 void
 GicV2::clearPPInt(uint32_t num, uint32_t cpu)
 {
-    DPRINTF(Interrupt, "Clearing PPI %d, cpuTarget %#x: \n",
-            num, cpu);
-    cpuPpiPending[cpu] &= ~(1 << (num - SGI_MAX));
-    updateIntState(intNumToWord(num));
+    if (isLevelSensitive(cpu, num)) {
+        DPRINTF(Interrupt, "Clearing PPI %d, cpuTarget %#x: \n",
+                num, cpu);
+        cpuPpiPending[cpu] &= ~(1 << (num - SGI_MAX));
+        updateIntState(intNumToWord(num));
+    } else {
+        /* Nothing to do :
+         * Edge-triggered interrupt remain pending until software
+         * writes GICD_ICPENDR or reads GICC_IAR */
+    }
 }
 
 void
@@ -989,7 +1000,7 @@ GicV2::serialize(CheckpointOut &cp) const
     SERIALIZE_ARRAY(iccrpr, CPU_MAX);
     SERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES);
     SERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES);
-    SERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2);
+    SERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2 - 2);
     SERIALIZE_ARRAY(cpuControl, CPU_MAX);
     SERIALIZE_ARRAY(cpuPriority, CPU_MAX);
     SERIALIZE_ARRAY(cpuBpr, CPU_MAX);
@@ -1016,6 +1027,7 @@ GicV2::BankedRegs::serialize(CheckpointOut &cp) const
     SERIALIZE_SCALAR(pendingInt);
     SERIALIZE_SCALAR(activeInt);
     SERIALIZE_SCALAR(intGroup);
+    SERIALIZE_ARRAY(intConfig, 2);
     SERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX);
 }
 
@@ -1033,7 +1045,7 @@ GicV2::unserialize(CheckpointIn &cp)
     UNSERIALIZE_ARRAY(iccrpr, CPU_MAX);
     UNSERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES);
     UNSERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES);
-    UNSERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2);
+    UNSERIALIZE_ARRAY(intConfig, INT_BITS_MAX * 2 - 2);
     UNSERIALIZE_ARRAY(cpuControl, CPU_MAX);
     UNSERIALIZE_ARRAY(cpuPriority, CPU_MAX);
     UNSERIALIZE_ARRAY(cpuBpr, CPU_MAX);
@@ -1075,6 +1087,7 @@ GicV2::BankedRegs::unserialize(CheckpointIn &cp)
     UNSERIALIZE_SCALAR(pendingInt);
     UNSERIALIZE_SCALAR(activeInt);
     UNSERIALIZE_SCALAR(intGroup);
+    UNSERIALIZE_ARRAY(intConfig, 2);
     UNSERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX);
 }
 
index aefa938cbf7b8e922567930acbe748de6cf73972..54c95f93a1615e39221ce6062f41ee3d0522dab8 100644 (file)
@@ -192,6 +192,10 @@ class GicV2 : public BaseGic, public BaseGicRegisters
          * interrupt group bits for first 32 interrupts, 1b per interrupt */
         uint32_t intGroup;
 
+        /** GICD_ICFGR0, GICD_ICFGR1
+         * interrupt config bits for first 32 interrupts, 2b per interrupt */
+        uint32_t intConfig[2];
+
         /** GICD_IPRIORITYR{0..7}
          * interrupt priority for SGIs and PPIs */
         uint8_t intPriority[SGI_MAX + PPI_MAX];
@@ -201,7 +205,7 @@ class GicV2 : public BaseGic, public BaseGicRegisters
 
         BankedRegs() :
             intEnabled(0), pendingInt(0), activeInt(0),
-            intGroup(0), intPriority {0}
+            intGroup(0), intConfig {0}, intPriority {0}
           {}
     };
     std::vector<BankedRegs*> bankedRegs;
@@ -281,18 +285,26 @@ class GicV2 : public BaseGic, public BaseGicRegisters
         }
     }
 
-    /** 2 bit per interrupt signaling if it's level or edge sensitive
+    /**
+     * GICD_ICFGR{2...63}
+     * 2 bit per interrupt signaling if it's level or edge sensitive
      * and if it is 1:N or N:N */
-    uint32_t intConfig[INT_BITS_MAX*2];
+    uint32_t intConfig[INT_BITS_MAX*2 - 2];
 
-    /** GICD_ICFGRn
+    /**
+     * Reads the GICD_ICFGRn register.
      * @param ctx context id (PE specific)
      * @param ix interrupt word index
      * @returns the interrupt config word
      */
     uint32_t& getIntConfig(ContextID ctx, uint32_t ix) {
         assert(ix < INT_BITS_MAX*2);
-        return intConfig[ix];
+        if (ix < 2) {
+            /** SGIs and PPIs **/
+            return getBankedRegs(ctx).intConfig[ix];
+        } else {
+            return intConfig[ix - 2];
+        }
     }
 
     /** GICD_ITARGETSR{8..255}