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