dev-arm: Implement Level Sensitive PPIs in GICv2
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>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user