diff options
Diffstat (limited to 'src/dev/arm/gic_pl390.hh')
-rw-r--r-- | src/dev/arm/gic_pl390.hh | 161 |
1 files changed, 115 insertions, 46 deletions
diff --git a/src/dev/arm/gic_pl390.hh b/src/dev/arm/gic_pl390.hh index a05cf43bf..e406bc260 100644 --- a/src/dev/arm/gic_pl390.hh +++ b/src/dev/arm/gic_pl390.hh @@ -42,12 +42,15 @@ /** @file - * Implementiation of a PL390 GIC + * Implementation of a PL390 GIC */ #ifndef __DEV_ARM_GIC_PL390_H__ #define __DEV_ARM_GIC_PL390_H__ +#include <vector> + +#include "base/addr_range.hh" #include "base/bitunion.hh" #include "cpu/intr_control.hh" #include "dev/arm/base_gic.hh" @@ -55,12 +58,6 @@ #include "dev/platform.hh" #include "params/Pl390.hh" -/** @todo this code only assumes one processor for now. Low word - * of intEnabled and pendingInt need to be replicated per CPU. - * bottom 31 interrupts (7 words) need to be replicated for - * for interrupt priority register, processor target registers - * interrupt config registers */ - class Pl390 : public BaseGic { protected: @@ -69,28 +66,22 @@ class Pl390 : public BaseGic GICD_CTLR = 0x000, // control register GICD_TYPER = 0x004, // controller type GICD_IIDR = 0x008, // implementer id - GICD_ISENABLER_ST = 0x100, // interrupt set enable - GICD_ISENABLER_ED = 0x17c, - GICD_ICENABLER_ST = 0x180, // interrupt clear enable - GICD_ICENABLER_ED = 0x1fc, - GICD_ISPENDR_ST = 0x200, // set pending interrupt - GICD_ISPENDR_ED = 0x27c, - GICD_ICPENDR_ST = 0x280, // clear pending interrupt - GICD_ICPENDR_ED = 0x2fc, - GICD_ISACTIVER_ST = 0x300, // active bit registers - GICD_ISACTIVER_ED = 0x37c, - GICD_IPRIORITYR_ST = 0x400, // interrupt priority registers - GICD_IPRIORITYR_ED = 0x7f8, - GICD_ITARGETSR_ST = 0x800, // processor target registers - GICD_ITARGETSR_ED = 0xbf8, - GICD_ICFGR_ST = 0xc00, // interrupt config registers - GICD_ICFGR_ED = 0xcfc, GICD_SGIR = 0xf00, // software generated interrupt DIST_SIZE = 0xfff }; - // cpu memory addressesa + static const AddrRange GICD_ISENABLER; // interrupt set enable + static const AddrRange GICD_ICENABLER; // interrupt clear enable + static const AddrRange GICD_ISPENDR; // set pending interrupt + static const AddrRange GICD_ICPENDR; // clear pending interrupt + static const AddrRange GICD_ISACTIVER; // active bit registers + static const AddrRange GICD_ICACTIVER; // clear bit registers + static const AddrRange GICD_IPRIORITYR; // interrupt priority registers + static const AddrRange GICD_ITARGETSR; // processor target registers + static const AddrRange GICD_ICFGR; // interrupt config registers + + // cpu memory addresses enum { GICC_CTLR = 0x00, // CPU control register GICC_PMR = 0x04, // Interrupt priority mask @@ -118,6 +109,7 @@ class Pl390 : public BaseGic static const int SPURIOUS_INT = 1023; static const int INT_BITS_MAX = 32; static const int INT_LINES_MAX = 1020; + static const int GLOBAL_INT_LINES = INT_LINES_MAX - SGI_MAX - PPI_MAX; BitUnion32(SWI) Bitfield<3,0> sgi_id; @@ -149,41 +141,121 @@ class Pl390 : public BaseGic /** Gic enabled */ bool enabled; + /** Are gem5 extensions available? */ + const bool haveGem5Extensions; + /** gem5 many-core extension enabled by driver */ bool gem5ExtensionsEnabled; /** Number of itLines enabled */ uint32_t itLines; - uint32_t itLinesLog2; + /** Registers "banked for each connected processor" per ARM IHI0048B */ + struct BankedRegs : public Serializable { + /** GICD_I{S,C}ENABLER0 + * interrupt enable bits for first 32 interrupts, 1b per interrupt */ + uint32_t intEnabled; - /** Are gem5 extensions available? */ - const bool haveGem5Extensions; + /** GICD_I{S,C}PENDR0 + * interrupt pending bits for first 32 interrupts, 1b per interrupt */ + uint32_t pendingInt; + + /** GICD_I{S,C}ACTIVER0 + * interrupt active bits for first 32 interrupts, 1b per interrupt */ + uint32_t activeInt; + + /** GICD_IPRIORITYR{0..7} + * interrupt priority for SGIs and PPIs */ + uint8_t intPriority[SGI_MAX + PPI_MAX]; - /** interrupt enable bits for all possible 1020 interupts. - * one bit per interrupt, 32 bit per word = 32 words */ - uint32_t intEnabled[INT_BITS_MAX]; + /** GICD_ITARGETSR{0..7} + * 8b CPU target ID for each SGI and PPI */ + uint8_t cpuTarget[SGI_MAX + PPI_MAX]; - /** interrupt pending bits for all possible 1020 interupts. - * one bit per interrupt, 32 bit per word = 32 words */ - uint32_t pendingInt[INT_BITS_MAX]; + void serialize(CheckpointOut &cp) const override; + void unserialize(CheckpointIn &cp) override; + + BankedRegs() : + intEnabled(0), pendingInt(0), activeInt(0), + intPriority {0}, cpuTarget {0} + {} + }; + std::vector<BankedRegs*> bankedRegs; - /** interrupt active bits for all possible 1020 interupts. - * one bit per interrupt, 32 bit per word = 32 words */ - uint32_t activeInt[INT_BITS_MAX]; + BankedRegs& getBankedRegs(ContextID); - /** read only running priroity register, 1 per cpu*/ + /** GICD_I{S,C}ENABLER{1..31} + * interrupt enable bits for global interrupts + * 1b per interrupt, 32 bits per word, 31 words */ + uint32_t intEnabled[INT_BITS_MAX-1]; + + uint32_t& getIntEnabled(ContextID ctx_id, uint32_t ix) { + if (ix == 0) { + return getBankedRegs(ctx_id).intEnabled; + } else { + return intEnabled[ix - 1]; + } + } + + /** GICD_I{S,C}PENDR{1..31} + * interrupt pending bits for global interrupts + * 1b per interrupt, 32 bits per word, 31 words */ + uint32_t pendingInt[INT_BITS_MAX-1]; + + uint32_t& getPendingInt(ContextID ctx_id, uint32_t ix) { + assert(ix < INT_BITS_MAX); + if (ix == 0) { + return getBankedRegs(ctx_id).pendingInt; + } else { + return pendingInt[ix - 1]; + } + } + + /** GICD_I{S,C}ACTIVER{1..31} + * interrupt active bits for global interrupts + * 1b per interrupt, 32 bits per word, 31 words */ + uint32_t activeInt[INT_BITS_MAX-1]; + + uint32_t& getActiveInt(ContextID ctx_id, uint32_t ix) { + assert(ix < INT_BITS_MAX); + if (ix == 0) { + return getBankedRegs(ctx_id).activeInt; + } else { + return activeInt[ix - 1]; + } + } + + /** read only running priority register, 1 per cpu*/ uint32_t iccrpr[CPU_MAX]; - /** an 8 bit priority (lower is higher priority) for each - * of the 1020 possible supported interrupts. + /** GICD_IPRIORITYR{8..255} + * an 8 bit priority (lower is higher priority) for each + * of the global (not replicated per CPU) interrupts. */ - uint8_t intPriority[INT_LINES_MAX]; + uint8_t intPriority[GLOBAL_INT_LINES]; + + uint8_t& getIntPriority(ContextID ctx_id, uint32_t ix) { + assert(ix < INT_LINES_MAX); + if (ix < SGI_MAX + PPI_MAX) { + return getBankedRegs(ctx_id).intPriority[ix]; + } else { + return intPriority[ix - (SGI_MAX + PPI_MAX)]; + } + } - /** an 8 bit cpu target id for each shared peripheral interrupt - * of the 1020 possible supported interrupts. + /** GICD_ITARGETSR{8..255} + * an 8 bit cpu target id for each global interrupt. */ - uint8_t cpuTarget[INT_LINES_MAX]; + uint8_t cpuTarget[GLOBAL_INT_LINES]; + + uint8_t& getCpuTarget(ContextID ctx_id, uint32_t ix) { + assert(ix < INT_LINES_MAX); + if (ix < SGI_MAX + PPI_MAX) { + return getBankedRegs(ctx_id).cpuTarget[ix]; + } else { + return cpuTarget[ix - (SGI_MAX + PPI_MAX)]; + } + } /** 2 bit per interrupt signaling if it's level or edge sensitive * and if it is 1:N or N:N */ @@ -219,9 +291,6 @@ class Pl390 : public BaseGic uint32_t cpuPpiPending[CPU_MAX]; uint32_t cpuPpiActive[CPU_MAX]; - /** Banked interrupt prioirty registers for SGIs and PPIs */ - uint8_t bankedIntPriority[CPU_MAX][SGI_MAX + PPI_MAX]; - /** IRQ Enable Used for debug */ bool irqEnable; |