/* * Copyright (c) 2018 Metempsy Technology Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer; * redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution; * neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Authors: Jairo Balart */ #ifndef __DEV_ARM_GICV3_REDISTRIBUTOR_H__ #define __DEV_ARM_GICV3_REDISTRIBUTOR_H__ #include "base/addr_range.hh" #include "dev/arm/gic_v3.hh" #include "sim/serialize.hh" class Gicv3CPUInterface; class Gicv3Distributor; class Gicv3Redistributor : public Serializable { private: friend class Gicv3CPUInterface; friend class Gicv3Distributor; protected: Gicv3 * gic; Gicv3Distributor * distributor; Gicv3CPUInterface * cpuInterface; uint32_t cpuId; PortProxy * memProxy; /* * GICv3 defines 2 contiguous 64KB frames for each redistributor. * Order of frames must be RD_base, SGI_base. */ static const uint32_t RD_base = 0x0; static const uint32_t SGI_base = 0x10000; enum { // Control Register GICR_CTLR = RD_base + 0x0000, // Implementer Identification Register GICR_IIDR = RD_base + 0x0004, // Type Register GICR_TYPER = RD_base + 0x0008, // Wake Register GICR_WAKER = RD_base + 0x0014, // Peripheral ID0 Register GICR_PIDR0 = RD_base + 0xffe0, // Peripheral ID1 Register GICR_PIDR1 = RD_base + 0xffe4, // Peripheral ID2 Register GICR_PIDR2 = RD_base + 0xffe8, // Peripheral ID3 Register GICR_PIDR3 = RD_base + 0xffec, // Peripheral ID4 Register GICR_PIDR4 = RD_base + 0xffd0, // Peripheral ID5 Register GICR_PIDR5 = RD_base + 0xffd4, // Peripheral ID6 Register GICR_PIDR6 = RD_base + 0xffd8, // Peripheral ID7 Register GICR_PIDR7 = RD_base + 0xffdc, }; static const uint32_t GICR_WAKER_ProcessorSleep = 1 << 1; static const uint32_t GICR_WAKER_ChildrenAsleep = 1 << 2; bool peInLowPowerState; enum { // Interrupt Group Register 0 GICR_IGROUPR0 = SGI_base + 0x0080, // Interrupt Set-Enable Register 0 GICR_ISENABLER0 = SGI_base + 0x0100, // Interrupt Clear-Enable Register 0 GICR_ICENABLER0 = SGI_base + 0x0180, // Interrupt Set-Pending Register 0 GICR_ISPENDR0 = SGI_base + 0x0200, // Interrupt Clear-Pending Register 0 GICR_ICPENDR0 = SGI_base + 0x0280, // Interrupt Set-Active Register 0 GICR_ISACTIVER0 = SGI_base + 0x0300, // Interrupt Clear-Active Register 0 GICR_ICACTIVER0 = SGI_base + 0x0380, // SGI Configuration Register GICR_ICFGR0 = SGI_base + 0x0c00, // PPI Configuration Register GICR_ICFGR1 = SGI_base + 0x0c04, // Interrupt Group Modifier Register 0 GICR_IGRPMODR0 = SGI_base + 0x0d00, // Non-secure Access Control Register GICR_NSACR = SGI_base + 0x0e00, }; // Interrupt Priority Registers static const AddrRange GICR_IPRIORITYR; // GIC physical LPI Redistributor register enum { // Set LPI Pending Register GICR_SETLPIR = RD_base + 0x0040, // Clear LPI Pending Register GICR_CLRLPIR = RD_base + 0x0048, //Redistributor Properties Base Address Register GICR_PROPBASER = RD_base + 0x0070, // Redistributor LPI Pending Table Base Address Register GICR_PENDBASER = RD_base + 0x0078, // Redistributor Invalidate LPI Register GICR_INVLPIR = RD_base + 0x00A0, // Redistributor Invalidate All Register GICR_INVALLR = RD_base + 0x00B0, // Redistributor Synchronize Register GICR_SYNCR = RD_base + 0x00C0, }; std::vector irqGroup; std::vector irqEnabled; std::vector irqPending; std::vector irqActive; std::vector irqPriority; std::vector irqConfig; std::vector irqGrpmod; std::vector irqNsacr; bool DPG1S; bool DPG1NS; bool DPG0; bool EnableLPIs; Addr lpiConfigurationTablePtr; uint8_t lpiIDBits; Addr lpiPendingTablePtr; BitUnion8(LPIConfigurationTableEntry) Bitfield<7, 2> priority; Bitfield<1> res1; Bitfield<0> enable; EndBitUnion(LPIConfigurationTableEntry) static const uint32_t GICR_CTLR_ENABLE_LPIS = 1 << 0; static const uint32_t GICR_CTLR_DPG0 = 1 << 24; static const uint32_t GICR_CTLR_DPG1NS = 1 << 25; static const uint32_t GICR_CTLR_DPG1S = 1 << 26; public: /* * GICv3 defines only 2 64K consecutive frames for the redistributor * (RD_base and SGI_base) but we are using 2 extra 64K stride frames * to match GICv4 that defines 4 64K consecutive frames for them. * Note this must match with DTB/DTS GIC node definition and boot * loader code. */ const uint32_t addrRangeSize; static const uint32_t SMALLEST_LPI_ID = 8192; void activateIRQ(uint32_t int_id); bool canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) const; void deactivateIRQ(uint32_t int_id); inline Gicv3CPUInterface * getCPUInterface() const { return cpuInterface; } uint32_t processorNumber() const { return cpuId; } Gicv3::GroupId getIntGroup(int int_id) const; Gicv3::IntStatus intStatus(uint32_t int_id) const; uint8_t readEntryLPI(uint32_t intid); void writeEntryLPI(uint32_t intid, uint8_t lpi_entry); bool isPendingLPI(uint32_t intid); void setClrLPI(uint64_t data, bool set); void reset(); void sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns); void serialize(CheckpointOut & cp) const override; void unserialize(CheckpointIn & cp) override; void update(); void updateAndInformCPUInterface(); public: Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id); uint32_t getAffinity() const; void init(); void initState(); uint64_t read(Addr addr, size_t size, bool is_secure_access); void sendPPInt(uint32_t int_id); void write(Addr addr, uint64_t data, size_t size, bool is_secure_access); }; #endif //__DEV_ARM_GICV3_REDISTRIBUTOR_H__