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]);
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;
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
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);
SERIALIZE_SCALAR(pendingInt);
SERIALIZE_SCALAR(activeInt);
SERIALIZE_SCALAR(intGroup);
+ SERIALIZE_ARRAY(intConfig, 2);
SERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX);
}
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);
UNSERIALIZE_SCALAR(pendingInt);
UNSERIALIZE_SCALAR(activeInt);
UNSERIALIZE_SCALAR(intGroup);
+ UNSERIALIZE_ARRAY(intConfig, 2);
UNSERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX);
}
* 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];
BankedRegs() :
intEnabled(0), pendingInt(0), activeInt(0),
- intGroup(0), intPriority {0}
+ intGroup(0), intConfig {0}, intPriority {0}
{}
};
std::vector<BankedRegs*> bankedRegs;
}
}
- /** 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}