diff options
Diffstat (limited to 'src/dev/arm')
-rw-r--r-- | src/dev/arm/gic_v2.cc | 13 | ||||
-rw-r--r-- | src/dev/arm/gic_v2.hh | 21 |
2 files changed, 31 insertions, 3 deletions
diff --git a/src/dev/arm/gic_v2.cc b/src/dev/arm/gic_v2.cc index 92949a34f..01358b732 100644 --- a/src/dev/arm/gic_v2.cc +++ b/src/dev/arm/gic_v2.cc @@ -161,7 +161,9 @@ uint32_t GicV2::readDistributor(ContextID ctx, Addr daddr, size_t resp_sz) { if (GICD_IGROUPR.contains(daddr)) { - return 0; // unimplemented; RAZ (read as zero) + uint32_t ix = (daddr - GICD_IGROUPR.start()) >> 2; + assert(ix < 32); + return getIntGroup(ctx, ix); } if (GICD_ISENABLER.contains(daddr)) { @@ -415,7 +417,10 @@ GicV2::writeDistributor(ContextID ctx, Addr daddr, uint32_t data, size_t data_sz) { if (GICD_IGROUPR.contains(daddr)) { - return; // unimplemented; WI (writes ignored) + uint32_t ix = (daddr - GICD_IGROUPR.start()) >> 2; + assert(ix < 32); + getIntGroup(ctx, ix) |= data; + return; } if (GICD_ISENABLER.contains(daddr)) { @@ -938,6 +943,7 @@ GicV2::serialize(CheckpointOut &cp) const SERIALIZE_ARRAY(intEnabled, INT_BITS_MAX-1); SERIALIZE_ARRAY(pendingInt, INT_BITS_MAX-1); SERIALIZE_ARRAY(activeInt, INT_BITS_MAX-1); + SERIALIZE_ARRAY(intGroup, INT_BITS_MAX-1); SERIALIZE_ARRAY(iccrpr, CPU_MAX); SERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES); SERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES); @@ -967,6 +973,7 @@ GicV2::BankedRegs::serialize(CheckpointOut &cp) const SERIALIZE_SCALAR(intEnabled); SERIALIZE_SCALAR(pendingInt); SERIALIZE_SCALAR(activeInt); + SERIALIZE_SCALAR(intGroup); SERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX); } @@ -980,6 +987,7 @@ GicV2::unserialize(CheckpointIn &cp) UNSERIALIZE_ARRAY(intEnabled, INT_BITS_MAX-1); UNSERIALIZE_ARRAY(pendingInt, INT_BITS_MAX-1); UNSERIALIZE_ARRAY(activeInt, INT_BITS_MAX-1); + UNSERIALIZE_ARRAY(intGroup, INT_BITS_MAX-1); UNSERIALIZE_ARRAY(iccrpr, CPU_MAX); UNSERIALIZE_ARRAY(intPriority, GLOBAL_INT_LINES); UNSERIALIZE_ARRAY(cpuTarget, GLOBAL_INT_LINES); @@ -1024,6 +1032,7 @@ GicV2::BankedRegs::unserialize(CheckpointIn &cp) UNSERIALIZE_SCALAR(intEnabled); UNSERIALIZE_SCALAR(pendingInt); UNSERIALIZE_SCALAR(activeInt); + UNSERIALIZE_SCALAR(intGroup); UNSERIALIZE_ARRAY(intPriority, SGI_MAX + PPI_MAX); } diff --git a/src/dev/arm/gic_v2.hh b/src/dev/arm/gic_v2.hh index 2057e7d5b..4ca2f38e2 100644 --- a/src/dev/arm/gic_v2.hh +++ b/src/dev/arm/gic_v2.hh @@ -194,6 +194,10 @@ class GicV2 : public BaseGic, public BaseGicRegisters * interrupt active bits for first 32 interrupts, 1b per interrupt */ uint32_t activeInt; + /** GICD_IGROUPR0 + * interrupt group bits for first 32 interrupts, 1b per interrupt */ + uint32_t intGroup; + /** GICD_IPRIORITYR{0..7} * interrupt priority for SGIs and PPIs */ uint8_t intPriority[SGI_MAX + PPI_MAX]; @@ -202,7 +206,8 @@ class GicV2 : public BaseGic, public BaseGicRegisters void unserialize(CheckpointIn &cp) override; BankedRegs() : - intEnabled(0), pendingInt(0), activeInt(0), intPriority {0} + intEnabled(0), pendingInt(0), activeInt(0), + intGroup(0), intPriority {0} {} }; std::vector<BankedRegs*> bankedRegs; @@ -250,6 +255,20 @@ class GicV2 : public BaseGic, public BaseGicRegisters } } + /** GICD_IGROUPR{1..31} + * interrupt group bits for global interrupts + * 1b per interrupt, 32 bits per word, 31 words */ + uint32_t intGroup[INT_BITS_MAX-1]; + + uint32_t& getIntGroup(ContextID ctx, uint32_t ix) { + assert(ix < INT_BITS_MAX); + if (ix == 0) { + return getBankedRegs(ctx).intGroup; + } else { + return intGroup[ix - 1]; + } + } + /** read only running priority register, 1 per cpu*/ uint32_t iccrpr[CPU_MAX]; |