Jairo Balart has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/16142

Change subject: dev-arm: LPI support for GICv3
......................................................................

dev-arm: LPI support for GICv3

Change-Id: Ia2c02cca4f95672d6361fba16201a56e2047ddb7
---
M src/dev/arm/gic_v3_redistributor.cc
M src/dev/arm/gic_v3_redistributor.hh
2 files changed, 198 insertions(+), 5 deletions(-)



diff --git a/src/dev/arm/gic_v3_redistributor.cc b/src/dev/arm/gic_v3_redistributor.cc
index ec1e388..970c93e 100644
--- a/src/dev/arm/gic_v3_redistributor.cc
+++ b/src/dev/arm/gic_v3_redistributor.cc
@@ -34,6 +34,7 @@
 #include "debug/GIC.hh"
 #include "dev/arm/gic_v3_cpu_interface.hh"
 #include "dev/arm/gic_v3_distributor.hh"
+#include "mem/fs_translating_port_proxy.hh"

 const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
         SGI_base + 0x041f);
@@ -91,6 +92,10 @@
     DPG1S = false;
     DPG1NS = false;
     DPG0 = false;
+    Enable_LPIs = false;
+    lpiConfigurationTablePtr = 0;
+    lpiIDBits = 0;
+    lpiPendingTablePtr = 0;
 }

 uint64_t
@@ -135,6 +140,10 @@
               value |= GICR_CTLR_DPG0;
           }

+          if (Enable_LPIs) {
+              value |= GICR_CTLR_ENABLE_LPIS;
+          }
+
           return value;
       }

@@ -156,17 +165,17 @@
            * Last             [4]     == X
            * (This Redistributor is the highest-numbered Redistributor in
            * a series of contiguous Redistributor pages)
-           * DirectLPI        [3]     == 0
-           * (direct injection of LPIs not supported)
+           * DirectLPI        [3]     == 1
+           * (direct injection of LPIs supported)
            * VLPIS            [1]     == 0
            * (virtual LPIs not supported)
-           * PLPIS            [0]     == 0
-           * (physical LPIs not supported)
+           * PLPIS            [0]     == 1
+           * (physical LPIs supported)
            */
           uint64_t affinity = getAffinity();
           int last = cpuId == (gic->getSystem()->numContexts() - 1);
           return (affinity << 32) | (1 << 24) | (cpuId << 8) |
-              (1 << 5) | (last << 4);
+              (1 << 5) | (last << 4) | (1 << 3) | (1 << 0);
       }

       case GICR_WAKER: // Wake Register
@@ -346,6 +355,39 @@
           return value;
       }

+ case GICR_PROPBASER: // Redistributor Properties Base Address Register
+        // OuterCache, bits [58:56]
+        //   000 Memory type defined in InnerCache field
+        // Physical_Address, bits [51:12]
+        //   Bits [51:12] of the physical address containing the LPI
+        //   Configuration table
+        // Shareability, bits [11:10]
+        //   00 Non-shareable
+        // InnerCache, bits [9:7]
+        //   000 Device-nGnRnE
+        // IDbits, bits [4:0]
+        //   limited by GICD_TYPER.IDbits
+        return lpiConfigurationTablePtr & lpiIDBits;
+
+      // Redistributor LPI Pending Table Base Address Register
+      case GICR_PENDBASER:
+        // PTZ, bit [62]
+        //   Pending Table Zero
+        // OuterCache, bits [58:56]
+        //   000 Memory type defined in InnerCache field
+        // Physical_Address, bits [51:16]
+ // Bits [51:16] of the physical address containing the LPI Pending
+        //   table
+        // Shareability, bits [11:10]
+        //   00 Non-shareable
+        // InnerCache, bits [9:7]
+        //   000 Device-nGnRnE
+        return lpiPendingTablePtr;
+
+      // Redistributor Synchronize Register
+      case GICR_SYNCR:
+        return 0;
+
       default:
         panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr);
         break;
@@ -383,6 +425,7 @@
     switch (addr) {
       case GICR_CTLR: {
           // GICR_TYPER.LPIS is 0 so Enable_LPIs is RES0
+          Enable_LPIs = data & GICR_CTLR_ENABLE_LPIS;
           DPG1S = data & GICR_CTLR_DPG1S;
           DPG1NS = data & GICR_CTLR_DPG1NS;
           DPG0 = data & GICR_CTLR_DPG0;
@@ -606,6 +649,114 @@
           break;
       }

+      case GICR_SETLPIR: // Set LPI Pending Register
+        {
+            uint32_t lpiID = data & 0xffffffff;
+            Addr lpiIDPendingEntryPtr = lpiPendingTablePtr + (lpiID / 8);
+            uint8_t lpiIDPendingEntry;
+            ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
+            tc->getVirtProxy().readBlob(lpiIDPendingEntryPtr,
+                (uint8_t*) &lpiIDPendingEntry,
+                sizeof(lpiIDPendingEntry));
+            uint8_t lpiIDPendingEntryBitPosition = lpiID % 8;
+            lpiIDPendingEntry |= 1 << (lpiIDPendingEntryBitPosition);
+            tc->getVirtProxy().writeBlob(lpiIDPendingEntryPtr,
+                (uint8_t*) &lpiIDPendingEntry,
+                sizeof(lpiIDPendingEntry));
+            break;
+        }
+
+      case GICR_CLRLPIR: // Clear LPI Pending Register
+        {
+            uint32_t lpiID = data & 0xffffffff;
+            Addr lpiIDPendingEntryPtr = lpiPendingTablePtr + (lpiID / 8);
+            uint8_t lpiIDPendingEntry;
+            ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
+            tc->getVirtProxy().readBlob(lpiIDPendingEntryPtr,
+                (uint8_t*) &lpiIDPendingEntry,
+                sizeof(lpiIDPendingEntry));
+            uint8_t lpiIDPendingEntryBitPosition = lpiID % 8;
+            lpiIDPendingEntry &= ~(1 << (lpiIDPendingEntryBitPosition));
+            tc->getVirtProxy().writeBlob(lpiIDPendingEntryPtr,
+                (uint8_t*) &lpiIDPendingEntry,
+                sizeof(lpiIDPendingEntry));
+            break;
+        }
+
+ case GICR_PROPBASER: // Redistributor Properties Base Address Register
+        {
+            // OuterCache, bits [58:56]
+            //   000 Memory type defined in InnerCache field
+            // Physical_Address, bits [51:12]
+            //   Bits [51:12] of the physical address containing the LPI
+            //   Configuration table
+            // Shareability, bits [11:10]
+            //   00 Non-shareable
+            // InnerCache, bits [9:7]
+            //   000 Device-nGnRnE
+            // IDbits, bits [4:0]
+            //   limited by GICD_TYPER.IDbits (= 0xf)
+            lpiConfigurationTablePtr = data & 0xFFFFFFFFFF000;
+            lpiIDBits = data & 0x1f;
+
+            if (lpiIDBits > 0xf)
+            {
+                lpiIDBits = 0xf;
+            }
+
+            uint32_t largestLPIID = 2 ^ (lpiIDBits + 1);
+            uint32_t numberLPIs = largestLPIID - SMALLEST_LPI_ID + 1;
+            lpiConfigurationTable.resize(numberLPIs);
+            break;
+        }
+
+      // Redistributor LPI Pending Table Base Address Register
+      case GICR_PENDBASER:
+        // PTZ, bit [62]
+        //   Pending Table Zero
+        // OuterCache, bits [58:56]
+        //   000 Memory type defined in InnerCache field
+        // Physical_Address, bits [51:16]
+ // Bits [51:16] of the physical address containing the LPI Pending
+        //   table
+        // Shareability, bits [11:10]
+        //   00 Non-shareable
+        // InnerCache, bits [9:7]
+        //   000 Device-nGnRnE
+        lpiPendingTablePtr = data & 0xFFFFFFFFF0000;
+        break;
+
+      case GICR_INVLPIR: // Redistributor Invalidate LPI Register
+        {
+            uint32_t lpiID = data & 0xffffffff;
+            uint32_t lpiTableEntryIndex = lpiID - SMALLEST_LPI_ID;
+            Addr lpiTableEntryPtr = lpiConfigurationTablePtr +
+                lpiTableEntryIndex * sizeof(LPIConfigurationTableEntry);
+            ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
+            tc->getVirtProxy().readBlob(lpiTableEntryPtr,
+                (uint8_t*) &lpiConfigurationTable[lpiTableEntryIndex],
+                sizeof(LPIConfigurationTableEntry));
+            break;
+        }
+
+      case GICR_INVALLR: // Redistributor Invalidate All Register
+        {
+            ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
+
+            for (int lpiTableEntryIndex = 0;
+                    lpiTableEntryIndex < lpiConfigurationTable.size();
+                    lpiTableEntryIndex++)
+            {
+                Addr lpiTableEntryPtr = lpiConfigurationTablePtr +
+ lpiTableEntryIndex * sizeof(LPIConfigurationTableEntry);
+                tc->getVirtProxy().readBlob(lpiTableEntryPtr,
+ (uint8_t*) &lpiConfigurationTable[lpiTableEntryIndex],
+                        sizeof(LPIConfigurationTableEntry));
+            }
+
+            break;
+        }
+
       default:
         panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr);
         break;
@@ -814,6 +965,10 @@
     SERIALIZE_SCALAR(DPG1S);
     SERIALIZE_SCALAR(DPG1NS);
     SERIALIZE_SCALAR(DPG0);
+    SERIALIZE_SCALAR(Enable_LPIs);
+    SERIALIZE_SCALAR(lpiConfigurationTablePtr);
+    SERIALIZE_SCALAR(lpiIDBits);
+    SERIALIZE_SCALAR(lpiPendingTablePtr);
 }

 void
@@ -831,4 +986,8 @@
     UNSERIALIZE_SCALAR(DPG1S);
     UNSERIALIZE_SCALAR(DPG1NS);
     UNSERIALIZE_SCALAR(DPG0);
+    UNSERIALIZE_SCALAR(Enable_LPIs);
+    UNSERIALIZE_SCALAR(lpiConfigurationTablePtr);
+    UNSERIALIZE_SCALAR(lpiIDBits);
+    UNSERIALIZE_SCALAR(lpiPendingTablePtr);
 }
diff --git a/src/dev/arm/gic_v3_redistributor.hh b/src/dev/arm/gic_v3_redistributor.hh
index 1155397..18c8d80 100644
--- a/src/dev/arm/gic_v3_redistributor.hh
+++ b/src/dev/arm/gic_v3_redistributor.hh
@@ -119,6 +119,24 @@
     // Interrupt Priority Registers
     static const AddrRange GICR_IPRIORITYR;

+    // GIC physical LPI Redistributor register
+    enum {
+        // Set LPI Pending Register
+        GICR_SETLPIR = RD_base + 0x0040,
+        // Clear LPI Pending Register
+        GICR_CLRLPIR = RD_base + 0x0048,
+        //Redistributor Properties Base Address Register
+        GICR_PROPBASER = RD_base + 0x0070,
+        // Redistributor LPI Pending Table Base Address Register
+        GICR_PENDBASER = RD_base + 0x0078,
+        // Redistributor Invalidate LPI Register
+        GICR_INVLPIR = RD_base + 0x00A0,
+        // Redistributor Invalidate All Register
+        GICR_INVALLR = RD_base + 0x00B0,
+        // Redistributor Synchronize Register
+        GICR_SYNCR = RD_base + 0x00C0,
+    };
+
     std::vector <uint8_t> irqGroup;
     std::vector <bool> irqEnabled;
     std::vector <bool> irqPending;
@@ -131,7 +149,23 @@
     bool DPG1S;
     bool DPG1NS;
     bool DPG0;
+    bool Enable_LPIs;

+    Addr lpiConfigurationTablePtr;
+    uint8_t lpiIDBits;
+    Addr lpiPendingTablePtr;
+
+    BitUnion8(LPIConfigurationTableEntry)
+        Bitfield<7, 2> priority;
+        Bitfield<1> res1;
+        Bitfield<0> enable;
+    EndBitUnion(LPIConfigurationTableEntry)
+
+    std::vector<LPIConfigurationTableEntry> lpiConfigurationTable;
+
+    static const uint32_t SMALLEST_LPI_ID = 8192;
+
+    static const uint32_t GICR_CTLR_ENABLE_LPIS = 1 << 0;
     static const uint32_t GICR_CTLR_DPG0 = 1 << 24;
     static const uint32_t GICR_CTLR_DPG1NS = 1 << 25;
     static const uint32_t GICR_CTLR_DPG1S = 1 << 26;

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/16142
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: Ia2c02cca4f95672d6361fba16201a56e2047ddb7
Gerrit-Change-Number: 16142
Gerrit-PatchSet: 1
Gerrit-Owner: Jairo Balart <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to