arm: refactor packet processing in Pl390 GIC
authorCurtis Dunham <Curtis.Dunham@arm.com>
Fri, 27 Jan 2017 20:16:23 +0000 (20:16 +0000)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Mon, 3 Apr 2017 16:51:46 +0000 (16:51 +0000)
Change-Id: I696703418506522ba90df5c2c4ca45c95a6efbea
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2441
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Weiping Liao <weipingliao@google.com>
src/dev/arm/gic_pl390.cc
src/dev/arm/gic_pl390.hh

index 22788b3758e68d5053d0d4d03e3ee1def1c62c63..b65014d232c4b4113122c073a4b38a2914560f35 100644 (file)
@@ -129,46 +129,64 @@ Pl390::readDistributor(PacketPtr pkt)
 
     DPRINTF(GIC, "gic distributor read register %#x\n", daddr);
 
+    const uint32_t resp = readDistributor(ctx, daddr, pkt->getSize());
+
+    switch (pkt->getSize()) {
+      case 1:
+        pkt->set<uint8_t>(resp);
+        break;
+      case 2:
+        pkt->set<uint16_t>(resp);
+        break;
+      case 4:
+        pkt->set<uint32_t>(resp);
+        break;
+      default:
+        panic("Invalid size while reading Distributor regs in GIC: %d\n",
+               pkt->getSize());
+    }
+
+    pkt->makeAtomicResponse();
+    return distPioDelay;
+}
+
+uint32_t
+Pl390::readDistributor(ContextID ctx, Addr daddr, size_t resp_sz)
+{
     if (GICD_ISENABLER.contains(daddr)) {
         uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
         assert(ix < 32);
-        pkt->set<uint32_t>(getIntEnabled(ctx, ix));
-        goto done;
+        return getIntEnabled(ctx, ix);
     }
 
     if (GICD_ICENABLER.contains(daddr)) {
         uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
         assert(ix < 32);
-        pkt->set<uint32_t>(getIntEnabled(ctx, ix));
-        goto done;
+        return getIntEnabled(ctx, ix);
     }
 
     if (GICD_ISPENDR.contains(daddr)) {
         uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
         assert(ix < 32);
-        pkt->set<uint32_t>(getPendingInt(ctx, ix));
-        goto done;
+        return getPendingInt(ctx, ix);
     }
 
     if (GICD_ICPENDR.contains(daddr)) {
         uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
         assert(ix < 32);
-        pkt->set<uint32_t>(getPendingInt(ctx, ix));
-        goto done;
+        return getPendingInt(ctx, ix);
     }
 
     if (GICD_ISACTIVER.contains(daddr)) {
         uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
         assert(ix < 32);
-        pkt->set<uint32_t>(getActiveInt(ctx, ix));
-        goto done;
+        return getActiveInt(ctx, ix);
     }
 
     if (GICD_ICACTIVER.contains(daddr)) {
         uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
         assert(ix < 32);
-        pkt->set<uint32_t>(getActiveInt(ctx, ix));
-        goto done;
+        return getActiveInt(ctx, ix);
     }
 
     if (GICD_IPRIORITYR.contains(daddr)) {
@@ -176,27 +194,21 @@ Pl390::readDistributor(PacketPtr pkt)
         assert(int_num < INT_LINES_MAX);
         DPRINTF(Interrupt, "Reading interrupt priority at int# %#x \n",int_num);
 
-        switch (pkt->getSize()) {
+        switch (resp_sz) {
+          default: // will panic() after return to caller anyway
           case 1:
-            pkt->set<uint8_t>(getIntPriority(ctx, int_num));
-            break;
+            return getIntPriority(ctx, int_num);
           case 2:
             assert((int_num + 1) < INT_LINES_MAX);
-            pkt->set<uint16_t>(getIntPriority(ctx, int_num) |
-                               getIntPriority(ctx, int_num+1) << 8);
-            break;
+            return (getIntPriority(ctx, int_num) |
+                    getIntPriority(ctx, int_num+1) << 8);
           case 4:
             assert((int_num + 3) < INT_LINES_MAX);
-            pkt->set<uint32_t>(getIntPriority(ctx, int_num) |
-                               getIntPriority(ctx, int_num+1) << 8 |
-                               getIntPriority(ctx, int_num+2) << 16 |
-                               getIntPriority(ctx, int_num+3) << 24);
-            break;
-          default:
-            panic("Invalid size while reading priority regs in GIC: %d\n",
-                   pkt->getSize());
+            return (getIntPriority(ctx, int_num) |
+                    getIntPriority(ctx, int_num+1) << 8 |
+                    getIntPriority(ctx, int_num+2) << 16 |
+                    getIntPriority(ctx, int_num+3) << 24);
         }
-        goto done;
     }
 
     if (GICD_ITARGETSR.contains(daddr)) {
@@ -207,15 +219,15 @@ Pl390::readDistributor(PacketPtr pkt)
 
         // First 31 interrupts only target single processor (SGI)
         if (int_num > 31) {
-            if (pkt->getSize() == 1) {
-                pkt->set<uint8_t>(cpuTarget[int_num]);
+            if (resp_sz == 1) {
+                return cpuTarget[int_num];
             } else {
-                assert(pkt->getSize() == 4);
+                assert(resp_sz == 4);
                 int_num = mbits(int_num, 31, 2);
-                pkt->set<uint32_t>(cpuTarget[int_num] |
-                                   cpuTarget[int_num+1] << 8 |
-                                   cpuTarget[int_num+2] << 16 |
-                                   cpuTarget[int_num+3] << 24) ;
+                return (cpuTarget[int_num] |
+                        cpuTarget[int_num+1] << 8 |
+                        cpuTarget[int_num+2] << 16 |
+                        cpuTarget[int_num+3] << 24) ;
             }
         } else {
             assert(ctx < sys->numRunningContexts());
@@ -229,9 +241,8 @@ Pl390::readDistributor(PacketPtr pkt)
             // replicate the 8-bit mask 4 times in a 32-bit word
             ctx_mask |= ctx_mask << 8;
             ctx_mask |= ctx_mask << 16;
-            pkt->set<uint32_t>(ctx_mask);
+            return ctx_mask;
         }
-        goto done;
     }
 
     if (GICD_ICFGR.contains(daddr)) {
@@ -239,30 +250,23 @@ Pl390::readDistributor(PacketPtr pkt)
         assert(ix < 64);
         /** @todo software generated interrupts and PPIs
          * can't be configured in some ways */
-        pkt->set<uint32_t>(intConfig[ix]);
-        goto done;
+        return intConfig[ix];
     }
 
     switch(daddr) {
       case GICD_CTLR:
-        pkt->set<uint32_t>(enabled);
-        break;
-      case GICD_TYPER: {
+        return enabled;
+      case GICD_TYPER:
         /* The 0x100 is a made-up flag to show that gem5 extensions
          * are available,
          * write 0x200 to this register to enable it.  */
-        uint32_t tmp = ((sys->numRunningContexts() - 1) << 5) |
-            (itLines/INT_BITS_MAX -1) |
-            (haveGem5Extensions ? 0x100 : 0x0);
-        pkt->set<uint32_t>(tmp);
-      } break;
+        return (((sys->numRunningContexts() - 1) << 5) |
+                (itLines/INT_BITS_MAX -1) |
+                (haveGem5Extensions ? 0x100 : 0x0));
       default:
         panic("Tried to read Gic distributor at offset %#x\n", daddr);
         break;
     }
-done:
-    pkt->makeAtomicResponse();
-    return distPioDelay;
 }
 
 Tick
@@ -277,19 +281,24 @@ Pl390::readCpu(PacketPtr pkt)
     DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr,
             ctx);
 
+    pkt->set<uint32_t>(readCpu(ctx, daddr));
+
+    pkt->makeAtomicResponse();
+    return cpuPioDelay;
+}
+
+uint32_t
+Pl390::readCpu(ContextID ctx, Addr daddr)
+{
     switch(daddr) {
       case GICC_IIDR:
-        pkt->set<uint32_t>(0);
-        break;
+        return 0;
       case GICC_CTLR:
-        pkt->set<uint32_t>(cpuEnabled[ctx]);
-        break;
+        return cpuEnabled[ctx];
       case GICC_PMR:
-        pkt->set<uint32_t>(cpuPriority[ctx]);
-        break;
+        return cpuPriority[ctx];
       case GICC_BPR:
-        pkt->set<uint32_t>(cpuBpr[ctx]);
-        break;
+        return cpuBpr[ctx];
       case GICC_IAR:
         if (enabled && cpuEnabled[ctx]) {
             int active_int = cpuHighestInt[ctx];
@@ -337,26 +346,22 @@ Pl390::readCpu(PacketPtr pkt)
                     ctx, iar.ack_id, iar.cpu_id, iar);
             cpuHighestInt[ctx] = SPURIOUS_INT;
             updateIntState(-1);
-            pkt->set<uint32_t>(iar);
             platform->intrctrl->clear(ctx, ArmISA::INT_IRQ, 0);
+            return iar;
         } else {
-             pkt->set<uint32_t>(SPURIOUS_INT);
+             return SPURIOUS_INT;
         }
 
         break;
       case GICC_RPR:
-        pkt->set<uint32_t>(iccrpr[0]);
-        break;
+        return iccrpr[0];
       case GICC_HPPIR:
-        pkt->set<uint32_t>(0);
         panic("Need to implement HPIR");
         break;
       default:
         panic("Tried to read Gic cpu at offset %#x\n", daddr);
         break;
     }
-    pkt->makeAtomicResponse();
-    return cpuPioDelay;
 }
 
 Tick
@@ -366,9 +371,10 @@ Pl390::writeDistributor(PacketPtr pkt)
 
     assert(pkt->req->hasContextId());
     const ContextID ctx = pkt->req->contextId();
+    const size_t data_sz = pkt->getSize();
 
     uint32_t pkt_data M5_VAR_USED;
-    switch (pkt->getSize())
+    switch (data_sz)
     {
       case 1:
         pkt_data = pkt->get<uint8_t>();
@@ -381,97 +387,104 @@ Pl390::writeDistributor(PacketPtr pkt)
         break;
       default:
         panic("Invalid size when writing to priority regs in Gic: %d\n",
-              pkt->getSize());
+              data_sz);
     }
 
     DPRINTF(GIC, "gic distributor write register %#x size %#x value %#x \n",
-            daddr, pkt->getSize(), pkt_data);
+            daddr, data_sz, pkt_data);
+
+    writeDistributor(ctx, daddr, pkt_data, data_sz);
 
+    pkt->makeAtomicResponse();
+    return distPioDelay;
+}
+
+void
+Pl390::writeDistributor(ContextID ctx, Addr daddr, uint32_t data,
+                        size_t data_sz)
+{
     if (GICD_ISENABLER.contains(daddr)) {
         uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
         assert(ix < 32);
-        getIntEnabled(ctx, ix) |= pkt->get<uint32_t>();
-        goto done;
+        getIntEnabled(ctx, ix) |= data;
+        return;
     }
 
     if (GICD_ICENABLER.contains(daddr)) {
         uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
         assert(ix < 32);
-        getIntEnabled(ctx, ix) &= ~pkt->get<uint32_t>();
-        goto done;
+        getIntEnabled(ctx, ix) &= ~data;
+        return;
     }
 
     if (GICD_ISPENDR.contains(daddr)) {
         uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
-        auto mask = pkt->get<uint32_t>();
+        auto mask = data;
         if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
         getPendingInt(ctx, ix) |= mask;
         updateIntState(ix);
-        goto done;
+        return;
     }
 
     if (GICD_ICPENDR.contains(daddr)) {
         uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
-        auto mask = pkt->get<uint32_t>();
+        auto mask = data;
         if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
         getPendingInt(ctx, ix) &= ~mask;
         updateIntState(ix);
-        goto done;
+        return;
     }
 
     if (GICD_ISACTIVER.contains(daddr)) {
         uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
-        getActiveInt(ctx, ix) |= pkt->get<uint32_t>();
-        goto done;
+        getActiveInt(ctx, ix) |= data;
+        return;
     }
 
     if (GICD_ICACTIVER.contains(daddr)) {
         uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
-        getActiveInt(ctx, ix) &= ~pkt->get<uint32_t>();
-        goto done;
+        getActiveInt(ctx, ix) &= ~data;
+        return;
     }
 
     if (GICD_IPRIORITYR.contains(daddr)) {
         Addr int_num = daddr - GICD_IPRIORITYR.start();
-        switch(pkt->getSize()) {
+        switch(data_sz) {
           case 1:
-            getIntPriority(ctx, int_num) = pkt->get<uint8_t>();
+            getIntPriority(ctx, int_num) = data;
             break;
           case 2: {
-            auto tmp16 = pkt->get<uint16_t>();
-            getIntPriority(ctx, int_num) = bits(tmp16, 7, 0);
-            getIntPriority(ctx, int_num + 1) = bits(tmp16, 15, 8);
+            getIntPriority(ctx, int_num) = bits(data, 7, 0);
+            getIntPriority(ctx, int_num + 1) = bits(data, 15, 8);
             break;
           }
           case 4: {
-            auto tmp32 = pkt->get<uint32_t>();
-            getIntPriority(ctx, int_num) = bits(tmp32, 7, 0);
-            getIntPriority(ctx, int_num + 1) = bits(tmp32, 15, 8);
-            getIntPriority(ctx, int_num + 2) = bits(tmp32, 23, 16);
-            getIntPriority(ctx, int_num + 3) = bits(tmp32, 31, 24);
+            getIntPriority(ctx, int_num) = bits(data, 7, 0);
+            getIntPriority(ctx, int_num + 1) = bits(data, 15, 8);
+            getIntPriority(ctx, int_num + 2) = bits(data, 23, 16);
+            getIntPriority(ctx, int_num + 3) = bits(data, 31, 24);
             break;
           }
           default:
             panic("Invalid size when writing to priority regs in Gic: %d\n",
-                   pkt->getSize());
+                   data_sz);
         }
 
         updateIntState(-1);
         updateRunPri();
-        goto done;
+        return;
     }
 
     if (GICD_ITARGETSR.contains(daddr)) {
         Addr int_num = daddr - GICD_ITARGETSR.start();
         // First 31 interrupts only target single processor
         if (int_num >= SGI_MAX) {
-            if (pkt->getSize() == 1) {
-                uint8_t tmp = pkt->get<uint8_t>();
-                cpuTarget[int_num] = tmp & 0xff;
+            if (data_sz == 1) {
+                cpuTarget[int_num] = data & 0xff;
             } else {
-                assert (pkt->getSize() == 4);
+                assert (data_sz == 4);
                 int_num = mbits(int_num, 31, 2);
-                uint32_t tmp = pkt->get<uint32_t>();
+                uint32_t tmp = data;
                 cpuTarget[int_num]   = bits(tmp, 7, 0);
                 cpuTarget[int_num+1] = bits(tmp, 15, 8);
                 cpuTarget[int_num+2] = bits(tmp, 23, 16);
@@ -479,43 +492,38 @@ Pl390::writeDistributor(PacketPtr pkt)
             }
             updateIntState(int_num >> 2);
         }
-        goto done;
+        return;
     }
 
     if (GICD_ICFGR.contains(daddr)) {
         uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2;
         assert(ix < INT_BITS_MAX*2);
-        intConfig[ix] = pkt->get<uint32_t>();
-        if (pkt->get<uint32_t>() & NN_CONFIG_MASK)
+        intConfig[ix] = data;
+        if (data & NN_CONFIG_MASK)
             warn("GIC N:N mode selected and not supported at this time\n");
-        goto done;
+        return;
     }
 
     switch(daddr) {
       case GICD_CTLR:
-        enabled = pkt->get<uint32_t>();
+        enabled = data;
         DPRINTF(Interrupt, "Distributor enable flag set to = %d\n", enabled);
         break;
       case GICD_TYPER:
         /* 0x200 is a made-up flag to enable gem5 extension functionality.
          * This reg is not normally written.
          */
-        gem5ExtensionsEnabled = (
-            (pkt->get<uint32_t>() & 0x200) && haveGem5Extensions);
+        gem5ExtensionsEnabled = (data & 0x200) && haveGem5Extensions;
         DPRINTF(GIC, "gem5 extensions %s\n",
                 gem5ExtensionsEnabled ? "enabled" : "disabled");
         break;
       case GICD_SGIR:
-        softInt(ctx, pkt->get<uint32_t>());
+        softInt(ctx, data);
         break;
       default:
         panic("Tried to write Gic distributor at offset %#x\n", daddr);
         break;
     }
-
-done:
-    pkt->makeAtomicResponse();
-    return distPioDelay;
 }
 
 Tick
@@ -525,23 +533,32 @@ Pl390::writeCpu(PacketPtr pkt)
 
     assert(pkt->req->hasContextId());
     const ContextID ctx = pkt->req->contextId();
-    IAR iar;
+    const uint32_t data = pkt->get<uint32_t>();
 
     DPRINTF(GIC, "gic cpu write register cpu:%d %#x val: %#x\n",
-            ctx, daddr, pkt->get<uint32_t>());
+            ctx, daddr, data);
 
+    writeCpu(ctx, daddr, data);
+
+    pkt->makeAtomicResponse();
+    return cpuPioDelay;
+}
+
+void
+Pl390::writeCpu(ContextID ctx, Addr daddr, uint32_t data)
+{
     switch(daddr) {
       case GICC_CTLR:
-        cpuEnabled[ctx] = pkt->get<uint32_t>();
+        cpuEnabled[ctx] = data;
         break;
       case GICC_PMR:
-        cpuPriority[ctx] = pkt->get<uint32_t>();
+        cpuPriority[ctx] = data;
         break;
       case GICC_BPR:
-        cpuBpr[ctx] = pkt->get<uint32_t>();
+        cpuBpr[ctx] = data;
         break;
-      case GICC_EOIR:
-        iar = pkt->get<uint32_t>();
+      case GICC_EOIR: {
+        const IAR iar = data;
         if (iar.ack_id < SGI_MAX) {
             // Clear out the bit that corresponds to the cleared int
             uint64_t clr_int = ULL(1) << (ctx + 8 * iar.cpu_id);
@@ -569,13 +586,12 @@ Pl390::writeCpu(PacketPtr pkt)
         DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n",
                 ctx, iar.ack_id, iar.cpu_id);
         break;
+      }
       default:
         panic("Tried to write Gic cpu at offset %#x\n", daddr);
         break;
     }
     if (cpuEnabled[ctx]) updateIntState(-1);
-    pkt->makeAtomicResponse();
-    return cpuPioDelay;
 }
 
 Pl390::BankedRegs&
index 1a5248d92b3a8275fcf40468aa5bff168144822c..aa3f3c084e0bdf0cbebd7a704977a9f8590bf5b4 100644 (file)
@@ -393,21 +393,26 @@ class Pl390 : public BaseGic
      * @param pkt packet to respond to
      */
     Tick readDistributor(PacketPtr pkt);
+    uint32_t readDistributor(ContextID ctx, Addr daddr, size_t resp_sz);
 
     /** Handle a read to the cpu portion of the GIC
      * @param pkt packet to respond to
      */
     Tick readCpu(PacketPtr pkt);
+    uint32_t readCpu(ContextID ctx, Addr daddr);
 
     /** Handle a write to the distributor portion of the GIC
      * @param pkt packet to respond to
      */
     Tick writeDistributor(PacketPtr pkt);
+    void writeDistributor(ContextID ctx, Addr daddr, uint32_t data,
+                          size_t data_sz);
 
     /** Handle a write to the cpu portion of the GIC
      * @param pkt packet to respond to
      */
     Tick writeCpu(PacketPtr pkt);
+    void writeCpu(ContextID ctx, Addr daddr, uint32_t data);
 };
 
 #endif //__DEV_ARM_GIC_H__