[gem5-dev] Change in gem5/gem5[develop]: dev-arm: Implement Level Sensitive PPIs in GICv2
Giacomo Travaglini has submitted this change. ( https://gem5-review.googlesource.com/c/public/gem5/+/31056 ) Change subject: dev-arm: Implement Level Sensitive PPIs in GICv2 .. dev-arm: Implement Level Sensitive PPIs in GICv2 JIRA: https://gem5.atlassian.net/browse/GEM5-667 Change-Id: I9ae40f08f4a1de95469ff5ed6788354abafc Signed-off-by: Giacomo Travaglini Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/31056 Reviewed-by: Hsuan Hsu Reviewed-by: Andreas Sandberg Maintainer: Andreas Sandberg Tested-by: kokoro --- M src/dev/arm/gic_v2.cc M src/dev/arm/gic_v2.hh 2 files changed, 38 insertions(+), 13 deletions(-) Approvals: Andreas Sandberg: Looks good to me, approved; Looks good to me, approved Hsuan Hsu: Looks good to me, approved kokoro: Regressions pass diff --git a/src/dev/arm/gic_v2.cc b/src/dev/arm/gic_v2.cc index 302da2f..1a6954d 100644 --- a/src/dev/arm/gic_v2.cc +++ b/src/dev/arm/gic_v2.cc @@ -343,7 +343,9 @@ 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 @@ 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 @@ 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 @@ 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 @@ SERIALIZE_SCALAR(pendingInt); SERIALIZE_SCALAR(activeInt); SERIALIZE_SCALAR(intGroup); +SERIALIZE_ARRAY(intConfig, 2); SERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX); } @@ -1033,7 +1045,7 @@ 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 @@ UNSERIALIZE_SCALAR(pendingInt); UNSERIALIZE_SCALAR(activeInt); UNSERIALIZE_SCALAR(intGroup); +UNSERIALIZE_ARRAY(intConfig, 2); UNSERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX); } diff --git a/src/dev/arm/gic_v2.hh b/src/dev/arm/gic_v2.hh index aefa938..54c95f9 100644 --- a/src/dev/arm/gic_v2.hh +++ b/src/dev/arm/gic_v2.hh @@ -192,6 +192,10 @@ * 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 @@ BankedRegs() : intEnabled(0), pendingInt(0), activeInt(0), -intGroup(0), intPriority {0} +intGroup(0), intConfig {0}, intPriority {0} {} }; std::vector bankedRegs; @@ -281,18 +285,26 @@ } } -/** 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];
[gem5-dev] Change in gem5/gem5[develop]: dev-arm: Implement Level Sensitive PPIs in GICv2
Giacomo Travaglini has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/31056 ) Change subject: dev-arm: Implement Level Sensitive PPIs in GICv2 .. dev-arm: Implement Level Sensitive PPIs in GICv2 JIRA: https://gem5.atlassian.net/browse/GEM5-667 Change-Id: I9ae40f08f4a1de95469ff5ed6788354abafc Signed-off-by: Giacomo Travaglini --- M src/dev/arm/gic_v2.cc M src/dev/arm/gic_v2.hh 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/dev/arm/gic_v2.cc b/src/dev/arm/gic_v2.cc index 302da2f..1a6954d 100644 --- a/src/dev/arm/gic_v2.cc +++ b/src/dev/arm/gic_v2.cc @@ -343,7 +343,9 @@ 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 @@ 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 @@ 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 @@ 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 @@ SERIALIZE_SCALAR(pendingInt); SERIALIZE_SCALAR(activeInt); SERIALIZE_SCALAR(intGroup); +SERIALIZE_ARRAY(intConfig, 2); SERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX); } @@ -1033,7 +1045,7 @@ 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 @@ UNSERIALIZE_SCALAR(pendingInt); UNSERIALIZE_SCALAR(activeInt); UNSERIALIZE_SCALAR(intGroup); +UNSERIALIZE_ARRAY(intConfig, 2); UNSERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX); } diff --git a/src/dev/arm/gic_v2.hh b/src/dev/arm/gic_v2.hh index aefa938..54c95f9 100644 --- a/src/dev/arm/gic_v2.hh +++ b/src/dev/arm/gic_v2.hh @@ -192,6 +192,10 @@ * 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 @@ BankedRegs() : intEnabled(0), pendingInt(0), activeInt(0), -intGroup(0), intPriority {0} +intGroup(0), intConfig {0}, intPriority {0} {} }; std::vector bankedRegs; @@ -281,18 +285,26 @@ } } -/** 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 in