113996Sgiacomo.travaglini@arm.com/*
213996Sgiacomo.travaglini@arm.com * Copyright (c) 2019 ARM Limited
313996Sgiacomo.travaglini@arm.com * All rights reserved
413996Sgiacomo.travaglini@arm.com *
513996Sgiacomo.travaglini@arm.com * The license below extends only to copyright in the software and shall
613996Sgiacomo.travaglini@arm.com * not be construed as granting a license to any other intellectual
713996Sgiacomo.travaglini@arm.com * property including but not limited to intellectual property relating
813996Sgiacomo.travaglini@arm.com * to a hardware implementation of the functionality of the software
913996Sgiacomo.travaglini@arm.com * licensed hereunder.  You may use the software subject to the license
1013996Sgiacomo.travaglini@arm.com * terms below provided that you ensure that this notice is replicated
1113996Sgiacomo.travaglini@arm.com * unmodified and in its entirety in all distributions of the software,
1213996Sgiacomo.travaglini@arm.com * modified or unmodified, in source code or in binary form.
1313996Sgiacomo.travaglini@arm.com *
1413996Sgiacomo.travaglini@arm.com * Redistribution and use in source and binary forms, with or without
1513996Sgiacomo.travaglini@arm.com * modification, are permitted provided that the following conditions are
1613996Sgiacomo.travaglini@arm.com * met: redistributions of source code must retain the above copyright
1713996Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer;
1813996Sgiacomo.travaglini@arm.com * redistributions in binary form must reproduce the above copyright
1913996Sgiacomo.travaglini@arm.com * notice, this list of conditions and the following disclaimer in the
2013996Sgiacomo.travaglini@arm.com * documentation and/or other materials provided with the distribution;
2113996Sgiacomo.travaglini@arm.com * neither the name of the copyright holders nor the names of its
2213996Sgiacomo.travaglini@arm.com * contributors may be used to endorse or promote products derived from
2313996Sgiacomo.travaglini@arm.com * this software without specific prior written permission.
2413996Sgiacomo.travaglini@arm.com *
2513996Sgiacomo.travaglini@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2613996Sgiacomo.travaglini@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2713996Sgiacomo.travaglini@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2813996Sgiacomo.travaglini@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2913996Sgiacomo.travaglini@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3013996Sgiacomo.travaglini@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3113996Sgiacomo.travaglini@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3213996Sgiacomo.travaglini@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3313996Sgiacomo.travaglini@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3413996Sgiacomo.travaglini@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3513996Sgiacomo.travaglini@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3613996Sgiacomo.travaglini@arm.com *
3713996Sgiacomo.travaglini@arm.com * Authors: Giacomo Travaglini
3813996Sgiacomo.travaglini@arm.com */
3913996Sgiacomo.travaglini@arm.com
4013996Sgiacomo.travaglini@arm.com#ifndef __DEV_ARM_GICV3_ITS_H__
4113996Sgiacomo.travaglini@arm.com#define __DEV_ARM_GICV3_ITS_H__
4213996Sgiacomo.travaglini@arm.com
4313996Sgiacomo.travaglini@arm.com#include <queue>
4413996Sgiacomo.travaglini@arm.com
4513996Sgiacomo.travaglini@arm.com#include "base/coroutine.hh"
4613996Sgiacomo.travaglini@arm.com#include "dev/dma_device.hh"
4713996Sgiacomo.travaglini@arm.com#include "params/Gicv3Its.hh"
4813996Sgiacomo.travaglini@arm.com
4913996Sgiacomo.travaglini@arm.comclass Gicv3;
5013996Sgiacomo.travaglini@arm.comclass Gicv3Redistributor;
5113996Sgiacomo.travaglini@arm.comclass ItsProcess;
5213996Sgiacomo.travaglini@arm.comclass ItsTranslation;
5313996Sgiacomo.travaglini@arm.comclass ItsCommand;
5413996Sgiacomo.travaglini@arm.com
5513996Sgiacomo.travaglini@arm.comenum class ItsActionType
5613996Sgiacomo.travaglini@arm.com{
5713996Sgiacomo.travaglini@arm.com    INITIAL_NOP,
5813996Sgiacomo.travaglini@arm.com    SEND_REQ,
5913996Sgiacomo.travaglini@arm.com    TERMINATE,
6013996Sgiacomo.travaglini@arm.com};
6113996Sgiacomo.travaglini@arm.com
6213996Sgiacomo.travaglini@arm.comstruct ItsAction
6313996Sgiacomo.travaglini@arm.com{
6413996Sgiacomo.travaglini@arm.com    ItsActionType type;
6513996Sgiacomo.travaglini@arm.com    PacketPtr pkt;
6613996Sgiacomo.travaglini@arm.com    Tick delay;
6713996Sgiacomo.travaglini@arm.com};
6813996Sgiacomo.travaglini@arm.com
6913996Sgiacomo.travaglini@arm.com/**
7013996Sgiacomo.travaglini@arm.com * GICv3 ITS module. This class is just modelling a pio device with its
7113996Sgiacomo.travaglini@arm.com * memory mapped registers. Most of the ITS functionalities are
7213996Sgiacomo.travaglini@arm.com * implemented as processes (ItsProcess) objects, like ItsTranslation or
7313996Sgiacomo.travaglini@arm.com * ItsCommand.
7413996Sgiacomo.travaglini@arm.com * Main job of Gicv3Its is to spawn those processes upon receival of packets.
7513996Sgiacomo.travaglini@arm.com */
7613996Sgiacomo.travaglini@arm.comclass Gicv3Its : public BasicPioDevice
7713996Sgiacomo.travaglini@arm.com{
7813996Sgiacomo.travaglini@arm.com    friend class ::ItsProcess;
7913996Sgiacomo.travaglini@arm.com    friend class ::ItsTranslation;
8013996Sgiacomo.travaglini@arm.com    friend class ::ItsCommand;
8113996Sgiacomo.travaglini@arm.com  public:
8213996Sgiacomo.travaglini@arm.com    class DataPort : public MasterPort
8313996Sgiacomo.travaglini@arm.com    {
8413996Sgiacomo.travaglini@arm.com      protected:
8513996Sgiacomo.travaglini@arm.com        Gicv3Its &its;
8613996Sgiacomo.travaglini@arm.com
8713996Sgiacomo.travaglini@arm.com      public:
8813996Sgiacomo.travaglini@arm.com        DataPort(const std::string &_name, Gicv3Its &_its) :
8913996Sgiacomo.travaglini@arm.com            MasterPort(_name, &_its),
9013996Sgiacomo.travaglini@arm.com            its(_its)
9113996Sgiacomo.travaglini@arm.com        {}
9213996Sgiacomo.travaglini@arm.com
9313996Sgiacomo.travaglini@arm.com        virtual ~DataPort() {}
9413996Sgiacomo.travaglini@arm.com
9513996Sgiacomo.travaglini@arm.com        bool recvTimingResp(PacketPtr pkt) { return its.recvTimingResp(pkt); }
9613996Sgiacomo.travaglini@arm.com        void recvReqRetry() { return its.recvReqRetry(); }
9713996Sgiacomo.travaglini@arm.com    };
9813996Sgiacomo.travaglini@arm.com
9913996Sgiacomo.travaglini@arm.com    DataPort dmaPort;
10013996Sgiacomo.travaglini@arm.com
10113996Sgiacomo.travaglini@arm.com    Port & getPort(const std::string &if_name, PortID idx) override;
10213996Sgiacomo.travaglini@arm.com    bool recvTimingResp(PacketPtr pkt);
10313996Sgiacomo.travaglini@arm.com    void recvReqRetry();
10413996Sgiacomo.travaglini@arm.com
10513996Sgiacomo.travaglini@arm.com    Gicv3Its(const Gicv3ItsParams *params);
10613996Sgiacomo.travaglini@arm.com
10713996Sgiacomo.travaglini@arm.com    void setGIC(Gicv3 *_gic);
10813996Sgiacomo.travaglini@arm.com
10913996Sgiacomo.travaglini@arm.com    static const uint32_t itsControl = 0x0;
11013996Sgiacomo.travaglini@arm.com    static const uint32_t itsTranslate = 0x10000;
11113996Sgiacomo.travaglini@arm.com
11213996Sgiacomo.travaglini@arm.com    // Address range part of Control frame
11313996Sgiacomo.travaglini@arm.com    static const AddrRange GITS_BASER;
11413996Sgiacomo.travaglini@arm.com
11513996Sgiacomo.travaglini@arm.com    static const uint32_t NUM_BASER_REGS = 8;
11613996Sgiacomo.travaglini@arm.com
11714187Sgiacomo.travaglini@arm.com    // We currently don't support two level ITS tables
11814187Sgiacomo.travaglini@arm.com    // The indirect bit is RAZ/WI for implementations that only
11914187Sgiacomo.travaglini@arm.com    // support flat tables.
12014187Sgiacomo.travaglini@arm.com    static const uint64_t BASER_INDIRECT = 0x4000000000000000;
12114187Sgiacomo.travaglini@arm.com    static const uint64_t BASER_TYPE = 0x0700000000000000;
12214187Sgiacomo.travaglini@arm.com    static const uint64_t BASER_ESZ = 0x001F000000000000;
12314187Sgiacomo.travaglini@arm.com    static const uint64_t BASER_SZ = 0x00000000000000FF;
12414187Sgiacomo.travaglini@arm.com    static const uint64_t BASER_WMASK =
12514187Sgiacomo.travaglini@arm.com        ~(BASER_INDIRECT | BASER_TYPE | BASER_ESZ);
12614187Sgiacomo.travaglini@arm.com    static const uint64_t BASER_WMASK_UNIMPL =
12714187Sgiacomo.travaglini@arm.com        ~(BASER_INDIRECT | BASER_TYPE | BASER_ESZ | BASER_SZ);
12814187Sgiacomo.travaglini@arm.com
12914181Sgiacomo.travaglini@arm.com    // GITS_CTLR.quiescent mask
13014181Sgiacomo.travaglini@arm.com    static const uint32_t CTLR_QUIESCENT;
13114181Sgiacomo.travaglini@arm.com
13213996Sgiacomo.travaglini@arm.com    enum : Addr
13313996Sgiacomo.travaglini@arm.com    {
13413996Sgiacomo.travaglini@arm.com        // Control frame
13513996Sgiacomo.travaglini@arm.com        GITS_CTLR    = itsControl + 0x0000,
13613996Sgiacomo.travaglini@arm.com        GITS_IIDR    = itsControl + 0x0004,
13713996Sgiacomo.travaglini@arm.com        GITS_TYPER   = itsControl + 0x0008,
13813996Sgiacomo.travaglini@arm.com        GITS_CBASER  = itsControl + 0x0080,
13913996Sgiacomo.travaglini@arm.com        GITS_CWRITER = itsControl + 0x0088,
14013996Sgiacomo.travaglini@arm.com        GITS_CREADR  = itsControl + 0x0090,
14114168Sgiacomo.travaglini@arm.com        GITS_PIDR2 = itsControl + 0xffe8,
14213996Sgiacomo.travaglini@arm.com
14313996Sgiacomo.travaglini@arm.com        // Translation frame
14413996Sgiacomo.travaglini@arm.com        GITS_TRANSLATER = itsTranslate + 0x0040
14513996Sgiacomo.travaglini@arm.com    };
14613996Sgiacomo.travaglini@arm.com
14713996Sgiacomo.travaglini@arm.com    AddrRangeList getAddrRanges() const override;
14813996Sgiacomo.travaglini@arm.com
14913996Sgiacomo.travaglini@arm.com    Tick read(PacketPtr pkt) override;
15013996Sgiacomo.travaglini@arm.com    Tick write(PacketPtr pkt) override;
15113996Sgiacomo.travaglini@arm.com
15213996Sgiacomo.travaglini@arm.com    DrainState drain() override;
15313996Sgiacomo.travaglini@arm.com    void serialize(CheckpointOut & cp) const override;
15413996Sgiacomo.travaglini@arm.com    void unserialize(CheckpointIn & cp) override;
15513996Sgiacomo.travaglini@arm.com
15613996Sgiacomo.travaglini@arm.com    void translate(PacketPtr pkt);
15713996Sgiacomo.travaglini@arm.com
15813996Sgiacomo.travaglini@arm.com    BitUnion32(CTLR)
15913996Sgiacomo.travaglini@arm.com        Bitfield<31> quiescent;
16013996Sgiacomo.travaglini@arm.com        Bitfield<7, 4> itsNumber;
16113996Sgiacomo.travaglini@arm.com        Bitfield<1> imDe;
16213996Sgiacomo.travaglini@arm.com        Bitfield<0> enabled;
16313996Sgiacomo.travaglini@arm.com    EndBitUnion(CTLR)
16413996Sgiacomo.travaglini@arm.com
16513996Sgiacomo.travaglini@arm.com    // Command read/write, (CREADR, CWRITER)
16613996Sgiacomo.travaglini@arm.com    BitUnion64(CRDWR)
16714180Sgiacomo.travaglini@arm.com        Bitfield<63, 32> high;
16814180Sgiacomo.travaglini@arm.com        Bitfield<31, 0> low;
16913996Sgiacomo.travaglini@arm.com        Bitfield<19, 5> offset;
17013996Sgiacomo.travaglini@arm.com        Bitfield<0> retry;
17113996Sgiacomo.travaglini@arm.com        Bitfield<0> stalled;
17213996Sgiacomo.travaglini@arm.com    EndBitUnion(CRDWR)
17313996Sgiacomo.travaglini@arm.com
17413996Sgiacomo.travaglini@arm.com    BitUnion64(CBASER)
17514180Sgiacomo.travaglini@arm.com        Bitfield<63, 32> high;
17614180Sgiacomo.travaglini@arm.com        Bitfield<31, 0> low;
17713996Sgiacomo.travaglini@arm.com        Bitfield<63> valid;
17813996Sgiacomo.travaglini@arm.com        Bitfield<61, 59> innerCache;
17913996Sgiacomo.travaglini@arm.com        Bitfield<55, 53> outerCache;
18013996Sgiacomo.travaglini@arm.com        Bitfield<51, 12> physAddr;
18113996Sgiacomo.travaglini@arm.com        Bitfield<11, 10> shareability;
18213996Sgiacomo.travaglini@arm.com        Bitfield<7, 0> size;
18313996Sgiacomo.travaglini@arm.com    EndBitUnion(CBASER)
18413996Sgiacomo.travaglini@arm.com
18513996Sgiacomo.travaglini@arm.com    BitUnion64(BASER)
18613996Sgiacomo.travaglini@arm.com        Bitfield<63> valid;
18713996Sgiacomo.travaglini@arm.com        Bitfield<62> indirect;
18813996Sgiacomo.travaglini@arm.com        Bitfield<61, 59> innerCache;
18913996Sgiacomo.travaglini@arm.com        Bitfield<58, 56> type;
19013996Sgiacomo.travaglini@arm.com        Bitfield<55, 53> outerCache;
19113996Sgiacomo.travaglini@arm.com        Bitfield<52, 48> entrySize;
19213996Sgiacomo.travaglini@arm.com        Bitfield<47, 12> physAddr;
19313996Sgiacomo.travaglini@arm.com        Bitfield<11, 10> shareability;
19413996Sgiacomo.travaglini@arm.com        Bitfield<9, 8> pageSize;
19513996Sgiacomo.travaglini@arm.com        Bitfield<7, 0> size;
19613996Sgiacomo.travaglini@arm.com    EndBitUnion(BASER)
19713996Sgiacomo.travaglini@arm.com
19813996Sgiacomo.travaglini@arm.com    BitUnion64(TYPER)
19914235Sgiacomo.travaglini@arm.com        Bitfield<63, 32> high;
20014235Sgiacomo.travaglini@arm.com        Bitfield<31, 0> low;
20113996Sgiacomo.travaglini@arm.com        Bitfield<37> vmovp;
20213996Sgiacomo.travaglini@arm.com        Bitfield<36> cil;
20313996Sgiacomo.travaglini@arm.com        Bitfield<35, 32> cidBits;
20413996Sgiacomo.travaglini@arm.com        Bitfield<31, 24> hcc;
20513996Sgiacomo.travaglini@arm.com        Bitfield<19> pta;
20613996Sgiacomo.travaglini@arm.com        Bitfield<18> seis;
20713996Sgiacomo.travaglini@arm.com        Bitfield<17, 13> devBits;
20813996Sgiacomo.travaglini@arm.com        Bitfield<12, 8> idBits;
20913996Sgiacomo.travaglini@arm.com        Bitfield<7, 4> ittEntrySize;
21013996Sgiacomo.travaglini@arm.com        Bitfield<2> cct;
21113996Sgiacomo.travaglini@arm.com        Bitfield<1> _virtual;
21213996Sgiacomo.travaglini@arm.com        Bitfield<0> physical;
21313996Sgiacomo.travaglini@arm.com    EndBitUnion(TYPER)
21413996Sgiacomo.travaglini@arm.com
21513996Sgiacomo.travaglini@arm.com    CTLR     gitsControl;
21613996Sgiacomo.travaglini@arm.com    TYPER    gitsTyper;
21713996Sgiacomo.travaglini@arm.com    CBASER   gitsCbaser;
21813996Sgiacomo.travaglini@arm.com    CRDWR    gitsCreadr;
21913996Sgiacomo.travaglini@arm.com    CRDWR    gitsCwriter;
22013996Sgiacomo.travaglini@arm.com    uint32_t gitsIidr;
22113996Sgiacomo.travaglini@arm.com    uint32_t gitsTranslater;
22213996Sgiacomo.travaglini@arm.com
22313996Sgiacomo.travaglini@arm.com    std::vector<BASER> tableBases;
22413996Sgiacomo.travaglini@arm.com
22513996Sgiacomo.travaglini@arm.com    /**
22613996Sgiacomo.travaglini@arm.com     * Returns TRUE if the eventID supplied has bits above the implemented
22713996Sgiacomo.travaglini@arm.com     * size or above the itt_range
22813996Sgiacomo.travaglini@arm.com     */
22913996Sgiacomo.travaglini@arm.com    bool idOutOfRange(uint32_t event_id, uint8_t itt_range) const;
23013996Sgiacomo.travaglini@arm.com
23113996Sgiacomo.travaglini@arm.com    /**
23213996Sgiacomo.travaglini@arm.com     * Returns TRUE if the value supplied has bits above the implemented range
23313996Sgiacomo.travaglini@arm.com     * or if the value supplied exceeds the maximum configured size in the
23413996Sgiacomo.travaglini@arm.com     * appropriate GITS_BASER<n>
23513996Sgiacomo.travaglini@arm.com     */
23613996Sgiacomo.travaglini@arm.com    bool deviceOutOfRange(uint32_t device_id) const;
23713996Sgiacomo.travaglini@arm.com
23813996Sgiacomo.travaglini@arm.com    /**
23913996Sgiacomo.travaglini@arm.com     * Returns TRUE if the value (size) supplied exceeds the maximum
24013996Sgiacomo.travaglini@arm.com     * allowed by GITS_TYPER.ID_bits. Size is the parameter which is
24113996Sgiacomo.travaglini@arm.com     * passed to the ITS via the MAPD command and is stored in the
24213996Sgiacomo.travaglini@arm.com     * DTE.ittRange field.
24313996Sgiacomo.travaglini@arm.com     */
24413996Sgiacomo.travaglini@arm.com    bool sizeOutOfRange(uint32_t size) const;
24513996Sgiacomo.travaglini@arm.com
24613996Sgiacomo.travaglini@arm.com    /**
24713996Sgiacomo.travaglini@arm.com     * Returns TRUE if the value supplied has bits above the implemented range
24813996Sgiacomo.travaglini@arm.com     * or if the value exceeds the total number of collections supported in
24913996Sgiacomo.travaglini@arm.com     * hardware and external memory
25013996Sgiacomo.travaglini@arm.com     */
25113996Sgiacomo.travaglini@arm.com    bool collectionOutOfRange(uint32_t collection_id) const;
25213996Sgiacomo.travaglini@arm.com
25313996Sgiacomo.travaglini@arm.com    /**
25413996Sgiacomo.travaglini@arm.com     * Returns TRUE if the value supplied is larger than that permitted by
25513996Sgiacomo.travaglini@arm.com     * GICD_TYPER.IDbits or not in the LPI range and is not 1023
25613996Sgiacomo.travaglini@arm.com     */
25713996Sgiacomo.travaglini@arm.com    bool lpiOutOfRange(uint32_t intid) const;
25813996Sgiacomo.travaglini@arm.com
25913996Sgiacomo.travaglini@arm.com  private: // Command
26014255Sgiacomo.travaglini@arm.com    uint64_t maxCommands() const;
26113996Sgiacomo.travaglini@arm.com    void checkCommandQueue();
26213996Sgiacomo.travaglini@arm.com    void incrementReadPointer();
26313996Sgiacomo.travaglini@arm.com
26413996Sgiacomo.travaglini@arm.com  public: // TableWalk
26513996Sgiacomo.travaglini@arm.com    BitUnion64(DTE)
26613996Sgiacomo.travaglini@arm.com        Bitfield<57, 53> ittRange;
26713996Sgiacomo.travaglini@arm.com        Bitfield<52, 1> ittAddress;
26813996Sgiacomo.travaglini@arm.com        Bitfield<0> valid;
26913996Sgiacomo.travaglini@arm.com    EndBitUnion(DTE)
27013996Sgiacomo.travaglini@arm.com
27113996Sgiacomo.travaglini@arm.com    BitUnion64(ITTE)
27213996Sgiacomo.travaglini@arm.com        Bitfield<59, 46> vpeid;
27313996Sgiacomo.travaglini@arm.com        Bitfield<45, 30> icid;
27413996Sgiacomo.travaglini@arm.com        Bitfield<29, 16> intNumHyp;
27513996Sgiacomo.travaglini@arm.com        Bitfield<15, 2> intNum;
27613996Sgiacomo.travaglini@arm.com        Bitfield<1> intType;
27713996Sgiacomo.travaglini@arm.com        Bitfield<0> valid;
27813996Sgiacomo.travaglini@arm.com    EndBitUnion(ITTE)
27913996Sgiacomo.travaglini@arm.com
28013996Sgiacomo.travaglini@arm.com    BitUnion64(CTE)
28113996Sgiacomo.travaglini@arm.com        Bitfield<40, 1> rdBase;
28213996Sgiacomo.travaglini@arm.com        Bitfield<0> valid;
28313996Sgiacomo.travaglini@arm.com    EndBitUnion(CTE)
28413996Sgiacomo.travaglini@arm.com
28513996Sgiacomo.travaglini@arm.com    enum InterruptType
28613996Sgiacomo.travaglini@arm.com    {
28713996Sgiacomo.travaglini@arm.com        VIRTUAL_INTERRUPT = 0,
28813996Sgiacomo.travaglini@arm.com        PHYSICAL_INTERRUPT = 1
28913996Sgiacomo.travaglini@arm.com    };
29013996Sgiacomo.travaglini@arm.com
29113996Sgiacomo.travaglini@arm.com  private:
29213996Sgiacomo.travaglini@arm.com    Gicv3Redistributor* getRedistributor(uint64_t rd_base);
29313996Sgiacomo.travaglini@arm.com    Gicv3Redistributor* getRedistributor(CTE cte)
29413996Sgiacomo.travaglini@arm.com    {
29513996Sgiacomo.travaglini@arm.com        return getRedistributor(cte.rdBase);
29613996Sgiacomo.travaglini@arm.com    }
29713996Sgiacomo.travaglini@arm.com
29813996Sgiacomo.travaglini@arm.com    ItsAction runProcess(ItsProcess *proc, PacketPtr pkt);
29913996Sgiacomo.travaglini@arm.com    ItsAction runProcessTiming(ItsProcess *proc, PacketPtr pkt);
30013996Sgiacomo.travaglini@arm.com    ItsAction runProcessAtomic(ItsProcess *proc, PacketPtr pkt);
30113996Sgiacomo.travaglini@arm.com
30213996Sgiacomo.travaglini@arm.com    enum ItsTables
30313996Sgiacomo.travaglini@arm.com    {
30413996Sgiacomo.travaglini@arm.com        DEVICE_TABLE = 1,
30513996Sgiacomo.travaglini@arm.com        VPE_TABLE = 2,
30613996Sgiacomo.travaglini@arm.com        TRANSLATION_TABLE = 3,
30713996Sgiacomo.travaglini@arm.com        COLLECTION_TABLE = 4
30813996Sgiacomo.travaglini@arm.com    };
30913996Sgiacomo.travaglini@arm.com
31013996Sgiacomo.travaglini@arm.com    enum PageSize
31113996Sgiacomo.travaglini@arm.com    {
31213996Sgiacomo.travaglini@arm.com        SIZE_4K,
31313996Sgiacomo.travaglini@arm.com        SIZE_16K,
31413996Sgiacomo.travaglini@arm.com        SIZE_64K
31513996Sgiacomo.travaglini@arm.com    };
31613996Sgiacomo.travaglini@arm.com
31713996Sgiacomo.travaglini@arm.com    Addr pageAddress(enum ItsTables table);
31813996Sgiacomo.travaglini@arm.com
31913996Sgiacomo.travaglini@arm.com    void moveAllPendingState(
32013996Sgiacomo.travaglini@arm.com        Gicv3Redistributor *rd1, Gicv3Redistributor *rd2);
32113996Sgiacomo.travaglini@arm.com
32213996Sgiacomo.travaglini@arm.com  private:
32313996Sgiacomo.travaglini@arm.com    std::queue<ItsAction> packetsToRetry;
32413996Sgiacomo.travaglini@arm.com    uint32_t masterId;
32513996Sgiacomo.travaglini@arm.com    Gicv3 *gic;
32613996Sgiacomo.travaglini@arm.com    EventFunctionWrapper commandEvent;
32713996Sgiacomo.travaglini@arm.com
32813996Sgiacomo.travaglini@arm.com    bool pendingCommands;
32913996Sgiacomo.travaglini@arm.com    uint32_t pendingTranslations;
33013996Sgiacomo.travaglini@arm.com};
33113996Sgiacomo.travaglini@arm.com
33213996Sgiacomo.travaglini@arm.com/**
33313996Sgiacomo.travaglini@arm.com * ItsProcess is a base coroutine wrapper which is spawned by
33413996Sgiacomo.travaglini@arm.com * the Gicv3Its module when the latter needs to perform different
33513996Sgiacomo.travaglini@arm.com * actions, like translating a peripheral's MSI into an LPI
33613996Sgiacomo.travaglini@arm.com * (See derived ItsTranslation) or processing a Command from the
33713996Sgiacomo.travaglini@arm.com * ITS queue (ItsCommand).
33813996Sgiacomo.travaglini@arm.com * The action to take is implemented by the method:
33913996Sgiacomo.travaglini@arm.com *
34013996Sgiacomo.travaglini@arm.com * virtual void main(Yield &yield) = 0;
34113996Sgiacomo.travaglini@arm.com * It's inheriting from Packet::SenderState since the generic process
34213996Sgiacomo.travaglini@arm.com * will be stopped (we are using coroutines) and sent with the packet
34313996Sgiacomo.travaglini@arm.com * to memory when doing table walks.
34413996Sgiacomo.travaglini@arm.com * When Gicv3Its receives a response, it will resume the coroutine from
34513996Sgiacomo.travaglini@arm.com * the point it stopped when yielding.
34613996Sgiacomo.travaglini@arm.com */
34713996Sgiacomo.travaglini@arm.comclass ItsProcess : public Packet::SenderState
34813996Sgiacomo.travaglini@arm.com{
34913996Sgiacomo.travaglini@arm.com  public:
35013996Sgiacomo.travaglini@arm.com    using DTE = Gicv3Its::DTE;
35113996Sgiacomo.travaglini@arm.com    using ITTE = Gicv3Its::ITTE;
35213996Sgiacomo.travaglini@arm.com    using CTE = Gicv3Its::CTE;
35313996Sgiacomo.travaglini@arm.com    using Coroutine = m5::Coroutine<PacketPtr, ItsAction>;
35413996Sgiacomo.travaglini@arm.com    using Yield = Coroutine::CallerType;
35513996Sgiacomo.travaglini@arm.com
35613996Sgiacomo.travaglini@arm.com    ItsProcess(Gicv3Its &_its);
35713996Sgiacomo.travaglini@arm.com    virtual ~ItsProcess();
35813996Sgiacomo.travaglini@arm.com
35913996Sgiacomo.travaglini@arm.com    /** Returns the Gicv3Its name. Mainly used for DPRINTS */
36013996Sgiacomo.travaglini@arm.com    const std::string name() const;
36113996Sgiacomo.travaglini@arm.com
36213996Sgiacomo.travaglini@arm.com    ItsAction run(PacketPtr pkt);
36313996Sgiacomo.travaglini@arm.com
36413996Sgiacomo.travaglini@arm.com  protected:
36513996Sgiacomo.travaglini@arm.com    void reinit();
36613996Sgiacomo.travaglini@arm.com    virtual void main(Yield &yield) = 0;
36713996Sgiacomo.travaglini@arm.com
36813996Sgiacomo.travaglini@arm.com    void writeDeviceTable(Yield &yield, uint32_t device_id, DTE dte);
36913996Sgiacomo.travaglini@arm.com
37013996Sgiacomo.travaglini@arm.com    void writeIrqTranslationTable(
37113996Sgiacomo.travaglini@arm.com        Yield &yield, const Addr itt_base, uint32_t event_id, ITTE itte);
37213996Sgiacomo.travaglini@arm.com
37313996Sgiacomo.travaglini@arm.com    void writeIrqCollectionTable(
37413996Sgiacomo.travaglini@arm.com        Yield &yield, uint32_t collection_id, CTE cte);
37513996Sgiacomo.travaglini@arm.com
37613996Sgiacomo.travaglini@arm.com    uint64_t readDeviceTable(
37713996Sgiacomo.travaglini@arm.com        Yield &yield, uint32_t device_id);
37813996Sgiacomo.travaglini@arm.com
37913996Sgiacomo.travaglini@arm.com    uint64_t readIrqTranslationTable(
38013996Sgiacomo.travaglini@arm.com        Yield &yield, const Addr itt_base, uint32_t event_id);
38113996Sgiacomo.travaglini@arm.com
38213996Sgiacomo.travaglini@arm.com    uint64_t readIrqCollectionTable(Yield &yield, uint32_t collection_id);
38313996Sgiacomo.travaglini@arm.com
38413996Sgiacomo.travaglini@arm.com    void doRead(Yield &yield, Addr addr, void *ptr, size_t size);
38513996Sgiacomo.travaglini@arm.com    void doWrite(Yield &yield, Addr addr, void *ptr, size_t size);
38613996Sgiacomo.travaglini@arm.com    void terminate(Yield &yield);
38713996Sgiacomo.travaglini@arm.com
38813996Sgiacomo.travaglini@arm.com  protected:
38913996Sgiacomo.travaglini@arm.com    Gicv3Its &its;
39013996Sgiacomo.travaglini@arm.com
39113996Sgiacomo.travaglini@arm.com  private:
39213996Sgiacomo.travaglini@arm.com    std::unique_ptr<Coroutine> coroutine;
39313996Sgiacomo.travaglini@arm.com};
39413996Sgiacomo.travaglini@arm.com
39513996Sgiacomo.travaglini@arm.com/**
39613996Sgiacomo.travaglini@arm.com * An ItsTranslation is created whenever a peripheral writes a message in
39713996Sgiacomo.travaglini@arm.com * GITS_TRANSLATER (MSI). In this case main will simply do the table walks
39813996Sgiacomo.travaglini@arm.com * until it gets a redistributor and an INTID. It will then raise the
39913996Sgiacomo.travaglini@arm.com * LPI interrupt to the target redistributor.
40013996Sgiacomo.travaglini@arm.com */
40113996Sgiacomo.travaglini@arm.comclass ItsTranslation : public ItsProcess
40213996Sgiacomo.travaglini@arm.com{
40313996Sgiacomo.travaglini@arm.com  public:
40413996Sgiacomo.travaglini@arm.com    ItsTranslation(Gicv3Its &_its);
40513996Sgiacomo.travaglini@arm.com    ~ItsTranslation();
40613996Sgiacomo.travaglini@arm.com
40713996Sgiacomo.travaglini@arm.com  protected:
40813996Sgiacomo.travaglini@arm.com    void main(Yield &yield) override;
40913996Sgiacomo.travaglini@arm.com
41013996Sgiacomo.travaglini@arm.com    std::pair<uint32_t, Gicv3Redistributor *>
41113996Sgiacomo.travaglini@arm.com    translateLPI(Yield &yield, uint32_t device_id, uint32_t event_id);
41213996Sgiacomo.travaglini@arm.com};
41313996Sgiacomo.travaglini@arm.com
41413996Sgiacomo.travaglini@arm.com/**
41513996Sgiacomo.travaglini@arm.com * An ItsCommand is created whenever there is a new command in the command
41613996Sgiacomo.travaglini@arm.com * queue. Only one command can be executed per time.
41713996Sgiacomo.travaglini@arm.com * main will firstly read the command from memory and then it will process
41813996Sgiacomo.travaglini@arm.com * it.
41913996Sgiacomo.travaglini@arm.com */
42013996Sgiacomo.travaglini@arm.comclass ItsCommand : public ItsProcess
42113996Sgiacomo.travaglini@arm.com{
42213996Sgiacomo.travaglini@arm.com  public:
42313996Sgiacomo.travaglini@arm.com    union CommandEntry
42413996Sgiacomo.travaglini@arm.com    {
42513996Sgiacomo.travaglini@arm.com        struct
42613996Sgiacomo.travaglini@arm.com        {
42713996Sgiacomo.travaglini@arm.com            uint32_t type;
42813996Sgiacomo.travaglini@arm.com            uint32_t deviceId;
42913996Sgiacomo.travaglini@arm.com            uint32_t eventId;
43013996Sgiacomo.travaglini@arm.com            uint32_t pintId;
43113996Sgiacomo.travaglini@arm.com
43213996Sgiacomo.travaglini@arm.com            uint32_t data[4];
43313996Sgiacomo.travaglini@arm.com        };
43413996Sgiacomo.travaglini@arm.com        uint64_t raw[4];
43513996Sgiacomo.travaglini@arm.com    };
43613996Sgiacomo.travaglini@arm.com
43713996Sgiacomo.travaglini@arm.com    enum CommandType : uint32_t
43813996Sgiacomo.travaglini@arm.com    {
43913996Sgiacomo.travaglini@arm.com        CLEAR = 0x04,
44013996Sgiacomo.travaglini@arm.com        DISCARD = 0x0F,
44113996Sgiacomo.travaglini@arm.com        INT = 0x03,
44213996Sgiacomo.travaglini@arm.com        INV = 0x0C,
44313996Sgiacomo.travaglini@arm.com        INVALL = 0x0D,
44413996Sgiacomo.travaglini@arm.com        MAPC = 0x09,
44513996Sgiacomo.travaglini@arm.com        MAPD = 0x08,
44613996Sgiacomo.travaglini@arm.com        MAPI = 0x0B,
44713996Sgiacomo.travaglini@arm.com        MAPTI = 0x0A,
44813996Sgiacomo.travaglini@arm.com        MOVALL = 0x0E,
44913996Sgiacomo.travaglini@arm.com        MOVI = 0x01,
45013996Sgiacomo.travaglini@arm.com        SYNC = 0x05,
45113996Sgiacomo.travaglini@arm.com        VINVALL = 0x2D,
45213996Sgiacomo.travaglini@arm.com        VMAPI = 0x2B,
45313996Sgiacomo.travaglini@arm.com        VMAPP = 0x29,
45413996Sgiacomo.travaglini@arm.com        VMAPTI = 0x2A,
45513996Sgiacomo.travaglini@arm.com        VMOVI = 0x21,
45613996Sgiacomo.travaglini@arm.com        VMOVP = 0x22,
45713996Sgiacomo.travaglini@arm.com        VSYNC = 0x25
45813996Sgiacomo.travaglini@arm.com    };
45913996Sgiacomo.travaglini@arm.com
46013996Sgiacomo.travaglini@arm.com    ItsCommand(Gicv3Its &_its);
46113996Sgiacomo.travaglini@arm.com    ~ItsCommand();
46213996Sgiacomo.travaglini@arm.com
46313996Sgiacomo.travaglini@arm.com  protected:
46413996Sgiacomo.travaglini@arm.com    /**
46513996Sgiacomo.travaglini@arm.com     * Dispatch entry is a metadata struct which contains information about
46613996Sgiacomo.travaglini@arm.com     * the command (like the name) and the function object implementing
46713996Sgiacomo.travaglini@arm.com     * the command.
46813996Sgiacomo.travaglini@arm.com     */
46913996Sgiacomo.travaglini@arm.com    struct DispatchEntry
47013996Sgiacomo.travaglini@arm.com    {
47113996Sgiacomo.travaglini@arm.com        using ExecFn = std::function<void(ItsCommand*, Yield&, CommandEntry&)>;
47213996Sgiacomo.travaglini@arm.com
47313996Sgiacomo.travaglini@arm.com        DispatchEntry(std::string _name, ExecFn _exec)
47413996Sgiacomo.travaglini@arm.com          : name(_name), exec(_exec)
47513996Sgiacomo.travaglini@arm.com        {}
47613996Sgiacomo.travaglini@arm.com
47713996Sgiacomo.travaglini@arm.com        std::string name;
47813996Sgiacomo.travaglini@arm.com        ExecFn exec;
47913996Sgiacomo.travaglini@arm.com    };
48013996Sgiacomo.travaglini@arm.com
48113996Sgiacomo.travaglini@arm.com    using DispatchTable = std::unordered_map<
48213996Sgiacomo.travaglini@arm.com        std::underlying_type<enum CommandType>::type, DispatchEntry>;
48313996Sgiacomo.travaglini@arm.com
48413996Sgiacomo.travaglini@arm.com    static DispatchTable cmdDispatcher;
48513996Sgiacomo.travaglini@arm.com
48613996Sgiacomo.travaglini@arm.com    static std::string commandName(uint32_t cmd);
48713996Sgiacomo.travaglini@arm.com
48813996Sgiacomo.travaglini@arm.com    void main(Yield &yield) override;
48913996Sgiacomo.travaglini@arm.com
49013996Sgiacomo.travaglini@arm.com    void readCommand(Yield &yield, CommandEntry &command);
49113996Sgiacomo.travaglini@arm.com    void processCommand(Yield &yield, CommandEntry &command);
49213996Sgiacomo.travaglini@arm.com
49313996Sgiacomo.travaglini@arm.com    // Commands
49413996Sgiacomo.travaglini@arm.com    void clear(Yield &yield, CommandEntry &command);
49513996Sgiacomo.travaglini@arm.com    void discard(Yield &yield, CommandEntry &command);
49613996Sgiacomo.travaglini@arm.com    void mapc(Yield &yield, CommandEntry &command);
49713996Sgiacomo.travaglini@arm.com    void mapd(Yield &yield, CommandEntry &command);
49813996Sgiacomo.travaglini@arm.com    void mapi(Yield &yield, CommandEntry &command);
49913996Sgiacomo.travaglini@arm.com    void mapti(Yield &yield, CommandEntry &command);
50013996Sgiacomo.travaglini@arm.com    void movall(Yield &yield, CommandEntry &command);
50113996Sgiacomo.travaglini@arm.com    void movi(Yield &yield, CommandEntry &command);
50213996Sgiacomo.travaglini@arm.com    void sync(Yield &yield, CommandEntry &command);
50313996Sgiacomo.travaglini@arm.com    void doInt(Yield &yield, CommandEntry &command);
50413996Sgiacomo.travaglini@arm.com    void inv(Yield &yield, CommandEntry &command);
50513996Sgiacomo.travaglini@arm.com    void invall(Yield &yield, CommandEntry &command);
50613996Sgiacomo.travaglini@arm.com    void vinvall(Yield &yield, CommandEntry &command);
50713996Sgiacomo.travaglini@arm.com    void vmapi(Yield &yield, CommandEntry &command);
50813996Sgiacomo.travaglini@arm.com    void vmapp(Yield &yield, CommandEntry &command);
50913996Sgiacomo.travaglini@arm.com    void vmapti(Yield &yield, CommandEntry &command);
51013996Sgiacomo.travaglini@arm.com    void vmovi(Yield &yield, CommandEntry &command);
51113996Sgiacomo.travaglini@arm.com    void vmovp(Yield &yield, CommandEntry &command);
51213996Sgiacomo.travaglini@arm.com    void vsync(Yield &yield, CommandEntry &command);
51313996Sgiacomo.travaglini@arm.com
51413996Sgiacomo.travaglini@arm.com  protected: // Helpers
51513996Sgiacomo.travaglini@arm.com    bool idOutOfRange(CommandEntry &command, DTE dte) const
51613996Sgiacomo.travaglini@arm.com    {
51713996Sgiacomo.travaglini@arm.com        return its.idOutOfRange(command.eventId, dte.ittRange);
51813996Sgiacomo.travaglini@arm.com    }
51913996Sgiacomo.travaglini@arm.com
52013996Sgiacomo.travaglini@arm.com    bool deviceOutOfRange(CommandEntry &command) const
52113996Sgiacomo.travaglini@arm.com    {
52213996Sgiacomo.travaglini@arm.com        return its.deviceOutOfRange(command.deviceId);
52313996Sgiacomo.travaglini@arm.com    }
52413996Sgiacomo.travaglini@arm.com
52513996Sgiacomo.travaglini@arm.com    bool sizeOutOfRange(CommandEntry &command) const
52613996Sgiacomo.travaglini@arm.com    {
52713996Sgiacomo.travaglini@arm.com        const auto size = bits(command.raw[1], 4, 0);
52813996Sgiacomo.travaglini@arm.com        const auto valid = bits(command.raw[2], 63);
52913996Sgiacomo.travaglini@arm.com        if (valid)
53013996Sgiacomo.travaglini@arm.com            return its.sizeOutOfRange(size);
53113996Sgiacomo.travaglini@arm.com        else
53213996Sgiacomo.travaglini@arm.com            return false;
53313996Sgiacomo.travaglini@arm.com    }
53413996Sgiacomo.travaglini@arm.com
53513996Sgiacomo.travaglini@arm.com    bool collectionOutOfRange(CommandEntry &command) const
53613996Sgiacomo.travaglini@arm.com    {
53713996Sgiacomo.travaglini@arm.com        return its.collectionOutOfRange(bits(command.raw[2], 15, 0));
53813996Sgiacomo.travaglini@arm.com    }
53913996Sgiacomo.travaglini@arm.com};
54013996Sgiacomo.travaglini@arm.com
54113996Sgiacomo.travaglini@arm.com#endif
542