dev-arm: Fix SGI generation
authorGiacomo Travaglini <giacomo.travaglini@arm.com>
Tue, 20 Aug 2019 11:26:17 +0000 (12:26 +0100)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Fri, 6 Sep 2019 08:32:04 +0000 (08:32 +0000)
The patch is fixing the following aspects of SGIs

* The conditons over which an SGI can be forwarded to a PE
* SGIs in AArch32 (see below)

It is in fact refactoring SGI generation under a common method in the
cpu interface. It is abandoning the implicit fallthrough mechanism not
only for cosmetic reasons, but also because checking "misc_reg ==" was
only working if the register was an AArch64 one (e.g.
MISCREG_ICC_SGI0R_EL1) and not the AArch32 counterpart (MISCREG_SGI0R).

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

index 348819316277cc0c4316a61639f24143d3b68e46..97d914568b529424446ee3fbc4ec82b77a56f50f 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2019 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2018 Metempsy Technology Consulting
  * All rights reserved.
  *
@@ -1416,68 +1428,25 @@ Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val)
       // Software Generated Interrupt Group 0 Register
       case MISCREG_ICC_SGI0R:
       case MISCREG_ICC_SGI0R_EL1:
+        generateSGI(val, Gicv3::G0S);
+        break;
 
       // Software Generated Interrupt Group 1 Register
       case MISCREG_ICC_SGI1R:
-      case MISCREG_ICC_SGI1R_EL1:
+      case MISCREG_ICC_SGI1R_EL1: {
+        Gicv3::GroupId group = inSecureState() ? Gicv3::G1S : Gicv3::G1NS;
+
+        generateSGI(val, group);
+        break;
+      }
 
       // Alias Software Generated Interrupt Group 1 Register
       case MISCREG_ICC_ASGI1R:
       case MISCREG_ICC_ASGI1R_EL1: {
-          bool ns = !inSecureState();
-          Gicv3::GroupId group;
-
-          if (misc_reg == MISCREG_ICC_SGI1R_EL1) {
-              group = ns ? Gicv3::G1NS : Gicv3::G1S;
-          } else if (misc_reg == MISCREG_ICC_ASGI1R_EL1) {
-              group = ns ? Gicv3::G1S : Gicv3::G1NS;
-          } else {
-              group = Gicv3::G0S;
-          }
-
-          if (distributor->DS && group == Gicv3::G1S) {
-              group = Gicv3::G0S;
-          }
-
-          uint8_t aff3 = bits(val, 55, 48);
-          uint8_t aff2 = bits(val, 39, 32);
-          uint8_t aff1 = bits(val, 23, 16);;
-          uint16_t target_list = bits(val, 15, 0);
-          uint32_t int_id = bits(val, 27, 24);
-          bool irm = bits(val, 40, 40);
-          uint8_t rs = bits(val, 47, 44);
-
-          for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
-              Gicv3Redistributor * redistributor_i =
-                  gic->getRedistributor(i);
-              uint32_t affinity_i = redistributor_i->getAffinity();
-
-              if (irm) {
-                  // Interrupts routed to all PEs in the system,
-                  // excluding "self"
-                  if (affinity_i == redistributor->getAffinity()) {
-                      continue;
-                  }
-              } else {
-                  // Interrupts routed to the PEs specified by
-                  // Aff3.Aff2.Aff1.<target list>
-                  if ((affinity_i >> 8) !=
-                      ((aff3 << 16) | (aff2 << 8) | (aff1 << 0))) {
-                      continue;
-                  }
-
-                  uint8_t aff0_i = bits(affinity_i, 7, 0);
-
-                  if (!(aff0_i >= rs * 16 && aff0_i < (rs + 1) * 16 &&
-                      ((0x1 << (aff0_i - rs * 16)) & target_list))) {
-                      continue;
-                  }
-              }
+        Gicv3::GroupId group = inSecureState() ? Gicv3::G1NS : Gicv3::G1S;
 
-              redistributor_i->sendSGI(int_id, group, ns);
-          }
-
-          break;
+        generateSGI(val, group);
+        break;
       }
 
       // System Register Enable Register EL1
@@ -1789,6 +1758,50 @@ Gicv3CPUInterface::virtualDropPriority()
     return 0xff;
 }
 
+void
+Gicv3CPUInterface::generateSGI(RegVal val, Gicv3::GroupId group)
+{
+    uint8_t aff3 = bits(val, 55, 48);
+    uint8_t aff2 = bits(val, 39, 32);
+    uint8_t aff1 = bits(val, 23, 16);;
+    uint16_t target_list = bits(val, 15, 0);
+    uint32_t int_id = bits(val, 27, 24);
+    bool irm = bits(val, 40, 40);
+    uint8_t rs = bits(val, 47, 44);
+
+    bool ns = !inSecureState();
+
+    for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
+        Gicv3Redistributor * redistributor_i =
+            gic->getRedistributor(i);
+        uint32_t affinity_i = redistributor_i->getAffinity();
+
+        if (irm) {
+            // Interrupts routed to all PEs in the system,
+            // excluding "self"
+            if (affinity_i == redistributor->getAffinity()) {
+                continue;
+            }
+        } else {
+            // Interrupts routed to the PEs specified by
+            // Aff3.Aff2.Aff1.<target list>
+            if ((affinity_i >> 8) !=
+                ((aff3 << 16) | (aff2 << 8) | (aff1 << 0))) {
+                continue;
+            }
+
+            uint8_t aff0_i = bits(affinity_i, 7, 0);
+
+            if (!(aff0_i >= rs * 16 && aff0_i < (rs + 1) * 16 &&
+                ((0x1 << (aff0_i - rs * 16)) & target_list))) {
+                continue;
+            }
+        }
+
+        redistributor_i->sendSGI(int_id, group, ns);
+    }
+}
+
 void
 Gicv3CPUInterface::activateIRQ(uint32_t int_id, Gicv3::GroupId group)
 {
index e6dcb51ff31819abffe121d7712faa7da7ea89fe..5c66fd75f5e26ae381fd9445d7ee229ed38df876 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2019 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2018 Metempsy Technology Consulting
  * All rights reserved.
  *
@@ -286,6 +298,7 @@ class Gicv3CPUInterface : public ArmISA::BaseISADevice, public Serializable
   protected:
 
     void activateIRQ(uint32_t intid, Gicv3::GroupId group);
+    void generateSGI(RegVal val, Gicv3::GroupId group);
     int currEL() const;
     void deactivateIRQ(uint32_t intid, Gicv3::GroupId group);
     void dropPriority(Gicv3::GroupId group);
index 37f169f1996e8ddd5db63118b0b1bf025843c444..71e74bfb8e12eba5aef595f8afcac737b22643f5 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2019 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2018 Metempsy Technology Consulting
  * All rights reserved.
  *
@@ -730,26 +742,31 @@ Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
     assert(int_id < Gicv3::SGI_MAX);
     Gicv3::GroupId int_group = getIntGroup(int_id);
 
-    // asked for secure group 1
-    // configured as group 0
-    // send group 0
-    if (int_group == Gicv3::G0S && group == Gicv3::G1S) {
-        group = Gicv3::G0S;
-    }
-
-    if (group == Gicv3::G0S and int_group != Gicv3::G0S) {
-        return;
-    }
+    bool forward = false;
 
-    if (ns && distributor->DS == 0) {
+    if (ns) {
+        // Non-Secure EL1 and EL2 access
         int nsaccess = irqNsacr[int_id];
+        if (int_group == Gicv3::G0S) {
 
-        if ((int_group == Gicv3::G0S && nsaccess < 1) ||
-            (int_group == Gicv3::G1S && nsaccess < 2)) {
-            return;
+            forward = distributor->DS || (nsaccess >= 1);
+
+        } else if (int_group == Gicv3::G1S) {
+            forward = ((group == Gicv3::G1S || group == Gicv3::G1NS ) &&
+                      nsaccess == 2);
+        } else {
+            // G1NS
+            forward = group == Gicv3::G1NS;
         }
+    } else {
+        // Secure EL1 and EL3 access
+        forward = (group == int_group) ||
+            (group == Gicv3::G1S && int_group == Gicv3::G0S &&
+            distributor->DS);
     }
 
+    if (!forward) return;
+
     irqPending[int_id] = true;
     DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
             "int_id %d (SGI) pending bit set\n", int_id);