From 01c695d5d37228f4bb81483d2dda68e73a8f5f58 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 7 Jul 2020 12:41:52 +0100 Subject: [PATCH] dev-arm: Implement Level Sensitive PPIs in GICv2 JIRA: https://gem5.atlassian.net/browse/GEM5-667 Change-Id: I9ae411110f08f4a1de95469ff5ed6788354abafc 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 --- src/dev/arm/gic_v2.cc | 29 +++++++++++++++++++++-------- src/dev/arm/gic_v2.hh | 22 +++++++++++++++++----- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/dev/arm/gic_v2.cc b/src/dev/arm/gic_v2.cc index 302da2f26..1a6954d6e 100644 --- a/src/dev/arm/gic_v2.cc +++ b/src/dev/arm/gic_v2.cc @@ -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); } diff --git a/src/dev/arm/gic_v2.hh b/src/dev/arm/gic_v2.hh index aefa938cb..54c95f93a 100644 --- a/src/dev/arm/gic_v2.hh +++ b/src/dev/arm/gic_v2.hh @@ -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; @@ -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} -- 2.30.2