gic_v3_its.cc revision 14168
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#include "dev/arm/gic_v3_its.hh"
4113996Sgiacomo.travaglini@arm.com
4213996Sgiacomo.travaglini@arm.com#include "debug/AddrRanges.hh"
4313996Sgiacomo.travaglini@arm.com#include "debug/Drain.hh"
4413996Sgiacomo.travaglini@arm.com#include "debug/GIC.hh"
4513996Sgiacomo.travaglini@arm.com#include "debug/ITS.hh"
4613996Sgiacomo.travaglini@arm.com#include "dev/arm/gic_v3.hh"
4713996Sgiacomo.travaglini@arm.com#include "dev/arm/gic_v3_distributor.hh"
4813996Sgiacomo.travaglini@arm.com#include "dev/arm/gic_v3_redistributor.hh"
4913996Sgiacomo.travaglini@arm.com#include "mem/packet_access.hh"
5013996Sgiacomo.travaglini@arm.com
5113996Sgiacomo.travaglini@arm.com#define COMMAND(x, method) { x, DispatchEntry(#x, method) }
5213996Sgiacomo.travaglini@arm.com
5313996Sgiacomo.travaglini@arm.comconst AddrRange Gicv3Its::GITS_BASER(0x0100, 0x0138);
5413996Sgiacomo.travaglini@arm.com
5513996Sgiacomo.travaglini@arm.comItsProcess::ItsProcess(Gicv3Its &_its)
5613996Sgiacomo.travaglini@arm.com  : its(_its), coroutine(nullptr)
5713996Sgiacomo.travaglini@arm.com{
5813996Sgiacomo.travaglini@arm.com}
5913996Sgiacomo.travaglini@arm.com
6013996Sgiacomo.travaglini@arm.comItsProcess::~ItsProcess()
6113996Sgiacomo.travaglini@arm.com{
6213996Sgiacomo.travaglini@arm.com}
6313996Sgiacomo.travaglini@arm.com
6413996Sgiacomo.travaglini@arm.comvoid
6513996Sgiacomo.travaglini@arm.comItsProcess::reinit()
6613996Sgiacomo.travaglini@arm.com{
6713996Sgiacomo.travaglini@arm.com    coroutine.reset(new Coroutine(
6813996Sgiacomo.travaglini@arm.com        std::bind(&ItsProcess::main, this, std::placeholders::_1)));
6913996Sgiacomo.travaglini@arm.com}
7013996Sgiacomo.travaglini@arm.com
7113996Sgiacomo.travaglini@arm.comconst std::string
7213996Sgiacomo.travaglini@arm.comItsProcess::name() const
7313996Sgiacomo.travaglini@arm.com{
7413996Sgiacomo.travaglini@arm.com    return its.name();
7513996Sgiacomo.travaglini@arm.com}
7613996Sgiacomo.travaglini@arm.com
7713996Sgiacomo.travaglini@arm.comItsAction
7813996Sgiacomo.travaglini@arm.comItsProcess::run(PacketPtr pkt)
7913996Sgiacomo.travaglini@arm.com{
8013996Sgiacomo.travaglini@arm.com    assert(coroutine != nullptr);
8113996Sgiacomo.travaglini@arm.com    assert(*coroutine);
8213996Sgiacomo.travaglini@arm.com    return (*coroutine)(pkt).get();
8313996Sgiacomo.travaglini@arm.com}
8413996Sgiacomo.travaglini@arm.com
8513996Sgiacomo.travaglini@arm.comvoid
8613996Sgiacomo.travaglini@arm.comItsProcess::doRead(Yield &yield, Addr addr, void *ptr, size_t size)
8713996Sgiacomo.travaglini@arm.com{
8813996Sgiacomo.travaglini@arm.com    ItsAction a;
8913996Sgiacomo.travaglini@arm.com    a.type = ItsActionType::SEND_REQ;
9013996Sgiacomo.travaglini@arm.com
9113996Sgiacomo.travaglini@arm.com    RequestPtr req = std::make_shared<Request>(
9213996Sgiacomo.travaglini@arm.com        addr, size, 0, its.masterId);
9313996Sgiacomo.travaglini@arm.com
9413996Sgiacomo.travaglini@arm.com    req->taskId(ContextSwitchTaskId::DMA);
9513996Sgiacomo.travaglini@arm.com
9613996Sgiacomo.travaglini@arm.com    a.pkt = new Packet(req, MemCmd::ReadReq);
9713996Sgiacomo.travaglini@arm.com    a.pkt->dataStatic(ptr);
9813996Sgiacomo.travaglini@arm.com
9913996Sgiacomo.travaglini@arm.com    a.delay = 0;
10013996Sgiacomo.travaglini@arm.com
10113996Sgiacomo.travaglini@arm.com    PacketPtr pkt = yield(a).get();
10213996Sgiacomo.travaglini@arm.com
10313996Sgiacomo.travaglini@arm.com    assert(pkt);
10413996Sgiacomo.travaglini@arm.com    assert(pkt->getSize() >= size);
10513996Sgiacomo.travaglini@arm.com
10613996Sgiacomo.travaglini@arm.com    delete pkt;
10713996Sgiacomo.travaglini@arm.com}
10813996Sgiacomo.travaglini@arm.com
10913996Sgiacomo.travaglini@arm.comvoid
11013996Sgiacomo.travaglini@arm.comItsProcess::doWrite(Yield &yield, Addr addr, void *ptr, size_t size)
11113996Sgiacomo.travaglini@arm.com{
11213996Sgiacomo.travaglini@arm.com    ItsAction a;
11313996Sgiacomo.travaglini@arm.com    a.type = ItsActionType::SEND_REQ;
11413996Sgiacomo.travaglini@arm.com
11513996Sgiacomo.travaglini@arm.com    RequestPtr req = std::make_shared<Request>(
11613996Sgiacomo.travaglini@arm.com        addr, size, 0, its.masterId);
11713996Sgiacomo.travaglini@arm.com
11813996Sgiacomo.travaglini@arm.com    req->taskId(ContextSwitchTaskId::DMA);
11913996Sgiacomo.travaglini@arm.com
12013996Sgiacomo.travaglini@arm.com    a.pkt = new Packet(req, MemCmd::WriteReq);
12113996Sgiacomo.travaglini@arm.com    a.pkt->dataStatic(ptr);
12213996Sgiacomo.travaglini@arm.com
12313996Sgiacomo.travaglini@arm.com    a.delay = 0;
12413996Sgiacomo.travaglini@arm.com
12513996Sgiacomo.travaglini@arm.com    PacketPtr pkt = yield(a).get();
12613996Sgiacomo.travaglini@arm.com
12713996Sgiacomo.travaglini@arm.com    assert(pkt);
12813996Sgiacomo.travaglini@arm.com    assert(pkt->getSize() >= size);
12913996Sgiacomo.travaglini@arm.com
13013996Sgiacomo.travaglini@arm.com    delete pkt;
13113996Sgiacomo.travaglini@arm.com}
13213996Sgiacomo.travaglini@arm.com
13313996Sgiacomo.travaglini@arm.comvoid
13413996Sgiacomo.travaglini@arm.comItsProcess::terminate(Yield &yield)
13513996Sgiacomo.travaglini@arm.com{
13613996Sgiacomo.travaglini@arm.com    ItsAction a;
13713996Sgiacomo.travaglini@arm.com    a.type = ItsActionType::TERMINATE;
13813996Sgiacomo.travaglini@arm.com    a.pkt = NULL;
13913996Sgiacomo.travaglini@arm.com    a.delay = 0;
14013996Sgiacomo.travaglini@arm.com    yield(a);
14113996Sgiacomo.travaglini@arm.com}
14213996Sgiacomo.travaglini@arm.com
14313996Sgiacomo.travaglini@arm.comvoid
14413996Sgiacomo.travaglini@arm.comItsProcess::writeDeviceTable(Yield &yield, uint32_t device_id, DTE dte)
14513996Sgiacomo.travaglini@arm.com{
14613996Sgiacomo.travaglini@arm.com    const Addr base = its.pageAddress(Gicv3Its::DEVICE_TABLE);
14713996Sgiacomo.travaglini@arm.com    const Addr address = base + device_id;
14813996Sgiacomo.travaglini@arm.com
14913996Sgiacomo.travaglini@arm.com    DPRINTF(ITS, "Writing DTE at address %#x: %#x\n", address, dte);
15013996Sgiacomo.travaglini@arm.com
15113996Sgiacomo.travaglini@arm.com    doWrite(yield, address, &dte, sizeof(dte));
15213996Sgiacomo.travaglini@arm.com}
15313996Sgiacomo.travaglini@arm.com
15413996Sgiacomo.travaglini@arm.comvoid
15513996Sgiacomo.travaglini@arm.comItsProcess::writeIrqTranslationTable(
15613996Sgiacomo.travaglini@arm.com    Yield &yield, const Addr itt_base, uint32_t event_id, ITTE itte)
15713996Sgiacomo.travaglini@arm.com{
15813996Sgiacomo.travaglini@arm.com    const Addr address = itt_base + event_id;
15913996Sgiacomo.travaglini@arm.com
16013996Sgiacomo.travaglini@arm.com    doWrite(yield, address, &itte, sizeof(itte));
16113996Sgiacomo.travaglini@arm.com
16213996Sgiacomo.travaglini@arm.com    DPRINTF(ITS, "Writing ITTE at address %#x: %#x\n", address, itte);
16313996Sgiacomo.travaglini@arm.com}
16413996Sgiacomo.travaglini@arm.com
16513996Sgiacomo.travaglini@arm.comvoid
16613996Sgiacomo.travaglini@arm.comItsProcess::writeIrqCollectionTable(
16713996Sgiacomo.travaglini@arm.com    Yield &yield, uint32_t collection_id, CTE cte)
16813996Sgiacomo.travaglini@arm.com{
16913996Sgiacomo.travaglini@arm.com    const Addr base = its.pageAddress(Gicv3Its::COLLECTION_TABLE);
17013996Sgiacomo.travaglini@arm.com    const Addr address = base + collection_id;
17113996Sgiacomo.travaglini@arm.com
17213996Sgiacomo.travaglini@arm.com    doWrite(yield, address, &cte, sizeof(cte));
17313996Sgiacomo.travaglini@arm.com
17413996Sgiacomo.travaglini@arm.com    DPRINTF(ITS, "Writing CTE at address %#x: %#x\n", address, cte);
17513996Sgiacomo.travaglini@arm.com}
17613996Sgiacomo.travaglini@arm.com
17713996Sgiacomo.travaglini@arm.comuint64_t
17813996Sgiacomo.travaglini@arm.comItsProcess::readDeviceTable(Yield &yield, uint32_t device_id)
17913996Sgiacomo.travaglini@arm.com{
18013996Sgiacomo.travaglini@arm.com    const Addr base = its.pageAddress(Gicv3Its::DEVICE_TABLE);
18113996Sgiacomo.travaglini@arm.com    const Addr address = base + device_id;
18213996Sgiacomo.travaglini@arm.com
18313996Sgiacomo.travaglini@arm.com    uint64_t dte;
18413996Sgiacomo.travaglini@arm.com    doRead(yield, address, &dte, sizeof(dte));
18513996Sgiacomo.travaglini@arm.com
18613996Sgiacomo.travaglini@arm.com    DPRINTF(ITS, "Reading DTE at address %#x: %#x\n", address, dte);
18713996Sgiacomo.travaglini@arm.com    return dte;
18813996Sgiacomo.travaglini@arm.com}
18913996Sgiacomo.travaglini@arm.com
19013996Sgiacomo.travaglini@arm.comuint64_t
19113996Sgiacomo.travaglini@arm.comItsProcess::readIrqTranslationTable(
19213996Sgiacomo.travaglini@arm.com    Yield &yield, const Addr itt_base, uint32_t event_id)
19313996Sgiacomo.travaglini@arm.com{
19413996Sgiacomo.travaglini@arm.com    const Addr address = itt_base + event_id;
19513996Sgiacomo.travaglini@arm.com
19613996Sgiacomo.travaglini@arm.com    uint64_t itte;
19713996Sgiacomo.travaglini@arm.com    doRead(yield, address, &itte, sizeof(itte));
19813996Sgiacomo.travaglini@arm.com
19913996Sgiacomo.travaglini@arm.com    DPRINTF(ITS, "Reading ITTE at address %#x: %#x\n", address, itte);
20013996Sgiacomo.travaglini@arm.com    return itte;
20113996Sgiacomo.travaglini@arm.com}
20213996Sgiacomo.travaglini@arm.com
20313996Sgiacomo.travaglini@arm.comuint64_t
20413996Sgiacomo.travaglini@arm.comItsProcess::readIrqCollectionTable(Yield &yield, uint32_t collection_id)
20513996Sgiacomo.travaglini@arm.com{
20613996Sgiacomo.travaglini@arm.com    const Addr base = its.pageAddress(Gicv3Its::COLLECTION_TABLE);
20713996Sgiacomo.travaglini@arm.com    const Addr address = base + collection_id;
20813996Sgiacomo.travaglini@arm.com
20913996Sgiacomo.travaglini@arm.com    uint64_t cte;
21013996Sgiacomo.travaglini@arm.com    doRead(yield, address, &cte, sizeof(cte));
21113996Sgiacomo.travaglini@arm.com
21213996Sgiacomo.travaglini@arm.com    DPRINTF(ITS, "Reading CTE at address %#x: %#x\n", address, cte);
21313996Sgiacomo.travaglini@arm.com    return cte;
21413996Sgiacomo.travaglini@arm.com}
21513996Sgiacomo.travaglini@arm.com
21613996Sgiacomo.travaglini@arm.comItsTranslation::ItsTranslation(Gicv3Its &_its)
21713996Sgiacomo.travaglini@arm.com  : ItsProcess(_its)
21813996Sgiacomo.travaglini@arm.com{
21913996Sgiacomo.travaglini@arm.com    reinit();
22013996Sgiacomo.travaglini@arm.com    its.pendingTranslations++;
22113996Sgiacomo.travaglini@arm.com}
22213996Sgiacomo.travaglini@arm.com
22313996Sgiacomo.travaglini@arm.comItsTranslation::~ItsTranslation()
22413996Sgiacomo.travaglini@arm.com{
22513996Sgiacomo.travaglini@arm.com    assert(its.pendingTranslations >= 1);
22613996Sgiacomo.travaglini@arm.com    its.pendingTranslations--;
22713996Sgiacomo.travaglini@arm.com}
22813996Sgiacomo.travaglini@arm.com
22913996Sgiacomo.travaglini@arm.comvoid
23013996Sgiacomo.travaglini@arm.comItsTranslation::main(Yield &yield)
23113996Sgiacomo.travaglini@arm.com{
23213996Sgiacomo.travaglini@arm.com    PacketPtr pkt = yield.get();
23313996Sgiacomo.travaglini@arm.com
23413996Sgiacomo.travaglini@arm.com    const uint32_t device_id = pkt->req->streamId();
23513996Sgiacomo.travaglini@arm.com    const uint32_t event_id = pkt->getLE<uint32_t>();
23613996Sgiacomo.travaglini@arm.com
23713996Sgiacomo.travaglini@arm.com    auto result = translateLPI(yield, device_id, event_id);
23813996Sgiacomo.travaglini@arm.com
23913996Sgiacomo.travaglini@arm.com    uint32_t intid = result.first;
24013996Sgiacomo.travaglini@arm.com    Gicv3Redistributor *redist = result.second;
24113996Sgiacomo.travaglini@arm.com
24213996Sgiacomo.travaglini@arm.com    // Set the LPI in the redistributor
24313996Sgiacomo.travaglini@arm.com    redist->setClrLPI(intid, true);
24413996Sgiacomo.travaglini@arm.com
24513996Sgiacomo.travaglini@arm.com    // Update the value in GITS_TRANSLATER only once we know
24613996Sgiacomo.travaglini@arm.com    // there was no error in the tranlation process (before
24713996Sgiacomo.travaglini@arm.com    // terminating the translation
24813996Sgiacomo.travaglini@arm.com    its.gitsTranslater = event_id;
24913996Sgiacomo.travaglini@arm.com
25013996Sgiacomo.travaglini@arm.com    terminate(yield);
25113996Sgiacomo.travaglini@arm.com}
25213996Sgiacomo.travaglini@arm.com
25313996Sgiacomo.travaglini@arm.comstd::pair<uint32_t, Gicv3Redistributor *>
25413996Sgiacomo.travaglini@arm.comItsTranslation::translateLPI(Yield &yield, uint32_t device_id,
25513996Sgiacomo.travaglini@arm.com                             uint32_t event_id)
25613996Sgiacomo.travaglini@arm.com{
25713996Sgiacomo.travaglini@arm.com    if (its.deviceOutOfRange(device_id)) {
25813996Sgiacomo.travaglini@arm.com        terminate(yield);
25913996Sgiacomo.travaglini@arm.com    }
26013996Sgiacomo.travaglini@arm.com
26113996Sgiacomo.travaglini@arm.com    DTE dte = readDeviceTable(yield, device_id);
26213996Sgiacomo.travaglini@arm.com
26313996Sgiacomo.travaglini@arm.com    if (!dte.valid || its.idOutOfRange(event_id, dte.ittRange)) {
26413996Sgiacomo.travaglini@arm.com        terminate(yield);
26513996Sgiacomo.travaglini@arm.com    }
26613996Sgiacomo.travaglini@arm.com
26713996Sgiacomo.travaglini@arm.com    ITTE itte = readIrqTranslationTable(yield, dte.ittAddress, event_id);
26813996Sgiacomo.travaglini@arm.com    const auto collection_id = itte.icid;
26913996Sgiacomo.travaglini@arm.com
27013996Sgiacomo.travaglini@arm.com    if (!itte.valid || its.collectionOutOfRange(collection_id)) {
27113996Sgiacomo.travaglini@arm.com        terminate(yield);
27213996Sgiacomo.travaglini@arm.com    }
27313996Sgiacomo.travaglini@arm.com
27413996Sgiacomo.travaglini@arm.com    CTE cte = readIrqCollectionTable(yield, collection_id);
27513996Sgiacomo.travaglini@arm.com
27613996Sgiacomo.travaglini@arm.com    if (!cte.valid) {
27713996Sgiacomo.travaglini@arm.com        terminate(yield);
27813996Sgiacomo.travaglini@arm.com    }
27913996Sgiacomo.travaglini@arm.com
28013996Sgiacomo.travaglini@arm.com    // Returning the INTID and the target Redistributor
28113996Sgiacomo.travaglini@arm.com    return std::make_pair(itte.intNum, its.getRedistributor(cte));
28213996Sgiacomo.travaglini@arm.com}
28313996Sgiacomo.travaglini@arm.com
28413996Sgiacomo.travaglini@arm.comItsCommand::DispatchTable ItsCommand::cmdDispatcher =
28513996Sgiacomo.travaglini@arm.com{
28613996Sgiacomo.travaglini@arm.com    COMMAND(CLEAR, &ItsCommand::clear),
28713996Sgiacomo.travaglini@arm.com    COMMAND(DISCARD, &ItsCommand::discard),
28813996Sgiacomo.travaglini@arm.com    COMMAND(INT, &ItsCommand::doInt),
28913996Sgiacomo.travaglini@arm.com    COMMAND(INV, &ItsCommand::inv),
29013996Sgiacomo.travaglini@arm.com    COMMAND(INVALL, &ItsCommand::invall),
29113996Sgiacomo.travaglini@arm.com    COMMAND(MAPC, &ItsCommand::mapc),
29213996Sgiacomo.travaglini@arm.com    COMMAND(MAPD, &ItsCommand::mapd),
29313996Sgiacomo.travaglini@arm.com    COMMAND(MAPI, &ItsCommand::mapi),
29413996Sgiacomo.travaglini@arm.com    COMMAND(MAPTI, &ItsCommand::mapti),
29513996Sgiacomo.travaglini@arm.com    COMMAND(MOVALL, &ItsCommand::movall),
29613996Sgiacomo.travaglini@arm.com    COMMAND(MOVI, &ItsCommand::movi),
29713996Sgiacomo.travaglini@arm.com    COMMAND(SYNC, &ItsCommand::sync),
29813996Sgiacomo.travaglini@arm.com    COMMAND(VINVALL, &ItsCommand::vinvall),
29913996Sgiacomo.travaglini@arm.com    COMMAND(VMAPI, &ItsCommand::vmapi),
30013996Sgiacomo.travaglini@arm.com    COMMAND(VMAPP, &ItsCommand::vmapp),
30113996Sgiacomo.travaglini@arm.com    COMMAND(VMAPTI, &ItsCommand::vmapti),
30213996Sgiacomo.travaglini@arm.com    COMMAND(VMOVI, &ItsCommand::vmovi),
30313996Sgiacomo.travaglini@arm.com    COMMAND(VMOVP, &ItsCommand::vmovp),
30413996Sgiacomo.travaglini@arm.com    COMMAND(VSYNC, &ItsCommand::vsync),
30513996Sgiacomo.travaglini@arm.com};
30613996Sgiacomo.travaglini@arm.com
30713996Sgiacomo.travaglini@arm.comItsCommand::ItsCommand(Gicv3Its &_its)
30813996Sgiacomo.travaglini@arm.com  : ItsProcess(_its)
30913996Sgiacomo.travaglini@arm.com{
31013996Sgiacomo.travaglini@arm.com    reinit();
31113996Sgiacomo.travaglini@arm.com    its.pendingCommands = true;
31213996Sgiacomo.travaglini@arm.com}
31313996Sgiacomo.travaglini@arm.com
31413996Sgiacomo.travaglini@arm.comItsCommand::~ItsCommand()
31513996Sgiacomo.travaglini@arm.com{
31613996Sgiacomo.travaglini@arm.com    its.pendingCommands = false;
31713996Sgiacomo.travaglini@arm.com}
31813996Sgiacomo.travaglini@arm.com
31913996Sgiacomo.travaglini@arm.comstd::string
32013996Sgiacomo.travaglini@arm.comItsCommand::commandName(uint32_t cmd)
32113996Sgiacomo.travaglini@arm.com{
32213996Sgiacomo.travaglini@arm.com    const auto entry = cmdDispatcher.find(cmd);
32313996Sgiacomo.travaglini@arm.com    return entry != cmdDispatcher.end() ? entry->second.name : "INVALID";
32413996Sgiacomo.travaglini@arm.com}
32513996Sgiacomo.travaglini@arm.com
32613996Sgiacomo.travaglini@arm.comvoid
32713996Sgiacomo.travaglini@arm.comItsCommand::main(Yield &yield)
32813996Sgiacomo.travaglini@arm.com{
32913996Sgiacomo.travaglini@arm.com    ItsAction a;
33013996Sgiacomo.travaglini@arm.com    a.type = ItsActionType::INITIAL_NOP;
33113996Sgiacomo.travaglini@arm.com    a.pkt = nullptr;
33213996Sgiacomo.travaglini@arm.com    a.delay = 0;
33313996Sgiacomo.travaglini@arm.com    yield(a);
33413996Sgiacomo.travaglini@arm.com
33513996Sgiacomo.travaglini@arm.com    while (its.gitsCwriter.offset != its.gitsCreadr.offset) {
33613996Sgiacomo.travaglini@arm.com        CommandEntry command;
33713996Sgiacomo.travaglini@arm.com
33813996Sgiacomo.travaglini@arm.com        // Reading the command from CMDQ
33913996Sgiacomo.travaglini@arm.com        readCommand(yield, command);
34013996Sgiacomo.travaglini@arm.com
34113996Sgiacomo.travaglini@arm.com        processCommand(yield, command);
34213996Sgiacomo.travaglini@arm.com
34313996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
34413996Sgiacomo.travaglini@arm.com    }
34513996Sgiacomo.travaglini@arm.com
34613996Sgiacomo.travaglini@arm.com    terminate(yield);
34713996Sgiacomo.travaglini@arm.com}
34813996Sgiacomo.travaglini@arm.com
34913996Sgiacomo.travaglini@arm.comvoid
35013996Sgiacomo.travaglini@arm.comItsCommand::readCommand(Yield &yield, CommandEntry &command)
35113996Sgiacomo.travaglini@arm.com{
35213996Sgiacomo.travaglini@arm.com    // read the command pointed by GITS_CREADR
35313996Sgiacomo.travaglini@arm.com    const Addr cmd_addr =
35413996Sgiacomo.travaglini@arm.com        (its.gitsCbaser.physAddr << 12) + (its.gitsCreadr.offset << 5);
35513996Sgiacomo.travaglini@arm.com
35613996Sgiacomo.travaglini@arm.com    doRead(yield, cmd_addr, &command, sizeof(command));
35713996Sgiacomo.travaglini@arm.com
35813996Sgiacomo.travaglini@arm.com    DPRINTF(ITS, "Command %s read from queue at address: %#x\n",
35913996Sgiacomo.travaglini@arm.com            commandName(command.type), cmd_addr);
36013996Sgiacomo.travaglini@arm.com    DPRINTF(ITS, "dw0: %#x dw1: %#x dw2: %#x dw3: %#x\n",
36113996Sgiacomo.travaglini@arm.com            command.raw[0], command.raw[1], command.raw[2], command.raw[3]);
36213996Sgiacomo.travaglini@arm.com}
36313996Sgiacomo.travaglini@arm.com
36413996Sgiacomo.travaglini@arm.comvoid
36513996Sgiacomo.travaglini@arm.comItsCommand::processCommand(Yield &yield, CommandEntry &command)
36613996Sgiacomo.travaglini@arm.com{
36713996Sgiacomo.travaglini@arm.com    const auto entry = cmdDispatcher.find(command.type);
36813996Sgiacomo.travaglini@arm.com
36913996Sgiacomo.travaglini@arm.com    if (entry != cmdDispatcher.end()) {
37013996Sgiacomo.travaglini@arm.com        // Execute the command
37113996Sgiacomo.travaglini@arm.com        entry->second.exec(this, yield, command);
37213996Sgiacomo.travaglini@arm.com    } else {
37313996Sgiacomo.travaglini@arm.com        panic("Unrecognized command type: %u", command.type);
37413996Sgiacomo.travaglini@arm.com    }
37513996Sgiacomo.travaglini@arm.com}
37613996Sgiacomo.travaglini@arm.com
37713996Sgiacomo.travaglini@arm.comvoid
37813996Sgiacomo.travaglini@arm.comItsCommand::clear(Yield &yield, CommandEntry &command)
37913996Sgiacomo.travaglini@arm.com{
38013996Sgiacomo.travaglini@arm.com    if (deviceOutOfRange(command)) {
38113996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
38213996Sgiacomo.travaglini@arm.com        terminate(yield);
38313996Sgiacomo.travaglini@arm.com    }
38413996Sgiacomo.travaglini@arm.com
38513996Sgiacomo.travaglini@arm.com    DTE dte = readDeviceTable(yield, command.deviceId);
38613996Sgiacomo.travaglini@arm.com
38713996Sgiacomo.travaglini@arm.com    if (!dte.valid || idOutOfRange(command, dte)) {
38813996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
38913996Sgiacomo.travaglini@arm.com        terminate(yield);
39013996Sgiacomo.travaglini@arm.com    }
39113996Sgiacomo.travaglini@arm.com
39213996Sgiacomo.travaglini@arm.com    ITTE itte = readIrqTranslationTable(
39313996Sgiacomo.travaglini@arm.com        yield, dte.ittAddress, command.eventId);
39413996Sgiacomo.travaglini@arm.com
39513996Sgiacomo.travaglini@arm.com    if (!itte.valid) {
39613996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
39713996Sgiacomo.travaglini@arm.com        terminate(yield);
39813996Sgiacomo.travaglini@arm.com    }
39913996Sgiacomo.travaglini@arm.com
40013996Sgiacomo.travaglini@arm.com    const auto collection_id = itte.icid;
40113996Sgiacomo.travaglini@arm.com    CTE cte = readIrqCollectionTable(yield, collection_id);
40213996Sgiacomo.travaglini@arm.com
40313996Sgiacomo.travaglini@arm.com    if (!cte.valid) {
40413996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
40513996Sgiacomo.travaglini@arm.com        terminate(yield);
40613996Sgiacomo.travaglini@arm.com    }
40713996Sgiacomo.travaglini@arm.com
40813996Sgiacomo.travaglini@arm.com    // Clear the LPI in the redistributor
40913996Sgiacomo.travaglini@arm.com    its.getRedistributor(cte)->setClrLPI(itte.intNum, false);
41013996Sgiacomo.travaglini@arm.com}
41113996Sgiacomo.travaglini@arm.com
41213996Sgiacomo.travaglini@arm.comvoid
41313996Sgiacomo.travaglini@arm.comItsCommand::discard(Yield &yield, CommandEntry &command)
41413996Sgiacomo.travaglini@arm.com{
41513996Sgiacomo.travaglini@arm.com    if (deviceOutOfRange(command)) {
41613996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
41713996Sgiacomo.travaglini@arm.com        terminate(yield);
41813996Sgiacomo.travaglini@arm.com    }
41913996Sgiacomo.travaglini@arm.com
42013996Sgiacomo.travaglini@arm.com    DTE dte = readDeviceTable(yield, command.deviceId);
42113996Sgiacomo.travaglini@arm.com
42213996Sgiacomo.travaglini@arm.com    if (!dte.valid || idOutOfRange(command, dte)) {
42313996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
42413996Sgiacomo.travaglini@arm.com        terminate(yield);
42513996Sgiacomo.travaglini@arm.com    }
42613996Sgiacomo.travaglini@arm.com
42713996Sgiacomo.travaglini@arm.com    ITTE itte = readIrqTranslationTable(
42813996Sgiacomo.travaglini@arm.com        yield, dte.ittAddress, command.eventId);
42913996Sgiacomo.travaglini@arm.com
43013996Sgiacomo.travaglini@arm.com    if (!itte.valid) {
43113996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
43213996Sgiacomo.travaglini@arm.com        terminate(yield);
43313996Sgiacomo.travaglini@arm.com    }
43413996Sgiacomo.travaglini@arm.com
43513996Sgiacomo.travaglini@arm.com    const auto collection_id = itte.icid;
43613996Sgiacomo.travaglini@arm.com    Gicv3Its::CTE cte = readIrqCollectionTable(yield, collection_id);
43713996Sgiacomo.travaglini@arm.com
43813996Sgiacomo.travaglini@arm.com    if (!cte.valid) {
43913996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
44013996Sgiacomo.travaglini@arm.com        terminate(yield);
44113996Sgiacomo.travaglini@arm.com    }
44213996Sgiacomo.travaglini@arm.com
44313996Sgiacomo.travaglini@arm.com    its.getRedistributor(cte)->setClrLPI(itte.intNum, false);
44413996Sgiacomo.travaglini@arm.com
44513996Sgiacomo.travaglini@arm.com    // Then removes the mapping from the ITT (invalidating)
44613996Sgiacomo.travaglini@arm.com    itte.valid = 0;
44713996Sgiacomo.travaglini@arm.com    writeIrqTranslationTable(
44813996Sgiacomo.travaglini@arm.com        yield, dte.ittAddress, command.eventId, itte);
44913996Sgiacomo.travaglini@arm.com}
45013996Sgiacomo.travaglini@arm.com
45113996Sgiacomo.travaglini@arm.comvoid
45213996Sgiacomo.travaglini@arm.comItsCommand::doInt(Yield &yield, CommandEntry &command)
45313996Sgiacomo.travaglini@arm.com{
45413996Sgiacomo.travaglini@arm.com    if (deviceOutOfRange(command)) {
45513996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
45613996Sgiacomo.travaglini@arm.com        terminate(yield);
45713996Sgiacomo.travaglini@arm.com    }
45813996Sgiacomo.travaglini@arm.com
45913996Sgiacomo.travaglini@arm.com    DTE dte = readDeviceTable(yield, command.deviceId);
46013996Sgiacomo.travaglini@arm.com
46113996Sgiacomo.travaglini@arm.com    if (!dte.valid || idOutOfRange(command, dte)) {
46213996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
46313996Sgiacomo.travaglini@arm.com        terminate(yield);
46413996Sgiacomo.travaglini@arm.com    }
46513996Sgiacomo.travaglini@arm.com
46613996Sgiacomo.travaglini@arm.com    ITTE itte = readIrqTranslationTable(
46713996Sgiacomo.travaglini@arm.com        yield, dte.ittAddress, command.eventId);
46813996Sgiacomo.travaglini@arm.com
46913996Sgiacomo.travaglini@arm.com    if (!itte.valid) {
47013996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
47113996Sgiacomo.travaglini@arm.com        terminate(yield);
47213996Sgiacomo.travaglini@arm.com    }
47313996Sgiacomo.travaglini@arm.com
47413996Sgiacomo.travaglini@arm.com    const auto collection_id = itte.icid;
47513996Sgiacomo.travaglini@arm.com    CTE cte = readIrqCollectionTable(yield, collection_id);
47613996Sgiacomo.travaglini@arm.com
47713996Sgiacomo.travaglini@arm.com    if (!cte.valid) {
47813996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
47913996Sgiacomo.travaglini@arm.com        terminate(yield);
48013996Sgiacomo.travaglini@arm.com    }
48113996Sgiacomo.travaglini@arm.com
48213996Sgiacomo.travaglini@arm.com    // Set the LPI in the redistributor
48313996Sgiacomo.travaglini@arm.com    its.getRedistributor(cte)->setClrLPI(itte.intNum, true);
48413996Sgiacomo.travaglini@arm.com}
48513996Sgiacomo.travaglini@arm.com
48613996Sgiacomo.travaglini@arm.comvoid
48713996Sgiacomo.travaglini@arm.comItsCommand::inv(Yield &yield, CommandEntry &command)
48813996Sgiacomo.travaglini@arm.com{
48913996Sgiacomo.travaglini@arm.com    if (deviceOutOfRange(command)) {
49013996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
49113996Sgiacomo.travaglini@arm.com        terminate(yield);
49213996Sgiacomo.travaglini@arm.com    }
49313996Sgiacomo.travaglini@arm.com
49413996Sgiacomo.travaglini@arm.com    DTE dte = readDeviceTable(yield, command.deviceId);
49513996Sgiacomo.travaglini@arm.com
49613996Sgiacomo.travaglini@arm.com    if (!dte.valid || idOutOfRange(command, dte)) {
49713996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
49813996Sgiacomo.travaglini@arm.com        terminate(yield);
49913996Sgiacomo.travaglini@arm.com    }
50013996Sgiacomo.travaglini@arm.com
50113996Sgiacomo.travaglini@arm.com    ITTE itte = readIrqTranslationTable(
50213996Sgiacomo.travaglini@arm.com        yield, dte.ittAddress, command.eventId);
50313996Sgiacomo.travaglini@arm.com
50413996Sgiacomo.travaglini@arm.com    if (!itte.valid) {
50513996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
50613996Sgiacomo.travaglini@arm.com        terminate(yield);
50713996Sgiacomo.travaglini@arm.com    }
50813996Sgiacomo.travaglini@arm.com
50913996Sgiacomo.travaglini@arm.com    const auto collection_id = itte.icid;
51013996Sgiacomo.travaglini@arm.com    CTE cte = readIrqCollectionTable(yield, collection_id);
51113996Sgiacomo.travaglini@arm.com
51213996Sgiacomo.travaglini@arm.com    if (!cte.valid) {
51313996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
51413996Sgiacomo.travaglini@arm.com        terminate(yield);
51513996Sgiacomo.travaglini@arm.com    }
51613996Sgiacomo.travaglini@arm.com    // Do nothing since caching is currently not supported in
51713996Sgiacomo.travaglini@arm.com    // Redistributor
51813996Sgiacomo.travaglini@arm.com}
51913996Sgiacomo.travaglini@arm.com
52013996Sgiacomo.travaglini@arm.comvoid
52113996Sgiacomo.travaglini@arm.comItsCommand::invall(Yield &yield, CommandEntry &command)
52213996Sgiacomo.travaglini@arm.com{
52313996Sgiacomo.travaglini@arm.com    if (collectionOutOfRange(command)) {
52413996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
52513996Sgiacomo.travaglini@arm.com        terminate(yield);
52613996Sgiacomo.travaglini@arm.com    }
52713996Sgiacomo.travaglini@arm.com
52813996Sgiacomo.travaglini@arm.com    const auto icid = bits(command.raw[2], 15, 0);
52913996Sgiacomo.travaglini@arm.com
53013996Sgiacomo.travaglini@arm.com    CTE cte = readIrqCollectionTable(yield, icid);
53113996Sgiacomo.travaglini@arm.com
53213996Sgiacomo.travaglini@arm.com    if (!cte.valid) {
53313996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
53413996Sgiacomo.travaglini@arm.com        terminate(yield);
53513996Sgiacomo.travaglini@arm.com    }
53613996Sgiacomo.travaglini@arm.com    // Do nothing since caching is currently not supported in
53713996Sgiacomo.travaglini@arm.com    // Redistributor
53813996Sgiacomo.travaglini@arm.com}
53913996Sgiacomo.travaglini@arm.com
54013996Sgiacomo.travaglini@arm.comvoid
54113996Sgiacomo.travaglini@arm.comItsCommand::mapc(Yield &yield, CommandEntry &command)
54213996Sgiacomo.travaglini@arm.com{
54313996Sgiacomo.travaglini@arm.com    if (collectionOutOfRange(command)) {
54413996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
54513996Sgiacomo.travaglini@arm.com        terminate(yield);
54613996Sgiacomo.travaglini@arm.com    }
54713996Sgiacomo.travaglini@arm.com
54813996Sgiacomo.travaglini@arm.com    CTE cte = 0;
54913996Sgiacomo.travaglini@arm.com    cte.valid = bits(command.raw[2], 63);
55013996Sgiacomo.travaglini@arm.com    cte.rdBase = bits(command.raw[2], 50, 16);
55113996Sgiacomo.travaglini@arm.com
55213996Sgiacomo.travaglini@arm.com    const auto icid = bits(command.raw[2], 15, 0);
55313996Sgiacomo.travaglini@arm.com
55413996Sgiacomo.travaglini@arm.com    writeIrqCollectionTable(yield, icid, cte);
55513996Sgiacomo.travaglini@arm.com}
55613996Sgiacomo.travaglini@arm.com
55713996Sgiacomo.travaglini@arm.comvoid
55813996Sgiacomo.travaglini@arm.comItsCommand::mapd(Yield &yield, CommandEntry &command)
55913996Sgiacomo.travaglini@arm.com{
56013996Sgiacomo.travaglini@arm.com    if (deviceOutOfRange(command) || sizeOutOfRange(command)) {
56113996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
56213996Sgiacomo.travaglini@arm.com        terminate(yield);
56313996Sgiacomo.travaglini@arm.com    }
56413996Sgiacomo.travaglini@arm.com
56513996Sgiacomo.travaglini@arm.com    DTE dte = 0;
56613996Sgiacomo.travaglini@arm.com    dte.valid = bits(command.raw[2], 63);
56713996Sgiacomo.travaglini@arm.com    dte.ittAddress = mbits(command.raw[2], 51, 8);
56813996Sgiacomo.travaglini@arm.com    dte.ittRange = bits(command.raw[1], 4, 0);
56913996Sgiacomo.travaglini@arm.com
57013996Sgiacomo.travaglini@arm.com    writeDeviceTable(yield, command.deviceId, dte);
57113996Sgiacomo.travaglini@arm.com}
57213996Sgiacomo.travaglini@arm.com
57313996Sgiacomo.travaglini@arm.comvoid
57413996Sgiacomo.travaglini@arm.comItsCommand::mapi(Yield &yield, CommandEntry &command)
57513996Sgiacomo.travaglini@arm.com{
57613996Sgiacomo.travaglini@arm.com    if (deviceOutOfRange(command)) {
57713996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
57813996Sgiacomo.travaglini@arm.com        terminate(yield);
57913996Sgiacomo.travaglini@arm.com    }
58013996Sgiacomo.travaglini@arm.com
58113996Sgiacomo.travaglini@arm.com    if (collectionOutOfRange(command)) {
58213996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
58313996Sgiacomo.travaglini@arm.com        terminate(yield);
58413996Sgiacomo.travaglini@arm.com    }
58513996Sgiacomo.travaglini@arm.com
58613996Sgiacomo.travaglini@arm.com    DTE dte = readDeviceTable(yield, command.deviceId);
58713996Sgiacomo.travaglini@arm.com
58813996Sgiacomo.travaglini@arm.com    if (!dte.valid || idOutOfRange(command, dte) ||
58913996Sgiacomo.travaglini@arm.com        its.lpiOutOfRange(command.eventId)) {
59013996Sgiacomo.travaglini@arm.com
59113996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
59213996Sgiacomo.travaglini@arm.com        terminate(yield);
59313996Sgiacomo.travaglini@arm.com    }
59413996Sgiacomo.travaglini@arm.com
59513996Sgiacomo.travaglini@arm.com    Gicv3Its::ITTE itte = readIrqTranslationTable(
59613996Sgiacomo.travaglini@arm.com        yield, dte.ittAddress, command.eventId);
59713996Sgiacomo.travaglini@arm.com
59813996Sgiacomo.travaglini@arm.com    itte.valid = 1;
59913996Sgiacomo.travaglini@arm.com    itte.intType = Gicv3Its::PHYSICAL_INTERRUPT;
60013996Sgiacomo.travaglini@arm.com    itte.intNum = command.eventId;
60113996Sgiacomo.travaglini@arm.com    itte.icid = bits(command.raw[2], 15, 0);
60213996Sgiacomo.travaglini@arm.com
60313996Sgiacomo.travaglini@arm.com    writeIrqTranslationTable(
60413996Sgiacomo.travaglini@arm.com        yield, dte.ittAddress, command.eventId, itte);
60513996Sgiacomo.travaglini@arm.com}
60613996Sgiacomo.travaglini@arm.com
60713996Sgiacomo.travaglini@arm.comvoid
60813996Sgiacomo.travaglini@arm.comItsCommand::mapti(Yield &yield, CommandEntry &command)
60913996Sgiacomo.travaglini@arm.com{
61013996Sgiacomo.travaglini@arm.com    if (deviceOutOfRange(command)) {
61113996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
61213996Sgiacomo.travaglini@arm.com        terminate(yield);
61313996Sgiacomo.travaglini@arm.com    }
61413996Sgiacomo.travaglini@arm.com
61513996Sgiacomo.travaglini@arm.com    if (collectionOutOfRange(command)) {
61613996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
61713996Sgiacomo.travaglini@arm.com        terminate(yield);
61813996Sgiacomo.travaglini@arm.com    }
61913996Sgiacomo.travaglini@arm.com
62013996Sgiacomo.travaglini@arm.com    DTE dte = readDeviceTable(yield, command.deviceId);
62113996Sgiacomo.travaglini@arm.com
62213996Sgiacomo.travaglini@arm.com    const auto pintid = bits(command.raw[1], 63, 32);
62313996Sgiacomo.travaglini@arm.com
62413996Sgiacomo.travaglini@arm.com    if (!dte.valid || idOutOfRange(command, dte) ||
62513996Sgiacomo.travaglini@arm.com        its.lpiOutOfRange(pintid)) {
62613996Sgiacomo.travaglini@arm.com
62713996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
62813996Sgiacomo.travaglini@arm.com        terminate(yield);
62913996Sgiacomo.travaglini@arm.com    }
63013996Sgiacomo.travaglini@arm.com
63113996Sgiacomo.travaglini@arm.com    ITTE itte = readIrqTranslationTable(
63213996Sgiacomo.travaglini@arm.com        yield, dte.ittAddress, command.eventId);
63313996Sgiacomo.travaglini@arm.com
63413996Sgiacomo.travaglini@arm.com    itte.valid = 1;
63513996Sgiacomo.travaglini@arm.com    itte.intType = Gicv3Its::PHYSICAL_INTERRUPT;
63613996Sgiacomo.travaglini@arm.com    itte.intNum = pintid;
63713996Sgiacomo.travaglini@arm.com    itte.icid = bits(command.raw[2], 15, 0);
63813996Sgiacomo.travaglini@arm.com
63913996Sgiacomo.travaglini@arm.com    writeIrqTranslationTable(
64013996Sgiacomo.travaglini@arm.com        yield, dte.ittAddress, command.eventId, itte);
64113996Sgiacomo.travaglini@arm.com}
64213996Sgiacomo.travaglini@arm.com
64313996Sgiacomo.travaglini@arm.comvoid
64413996Sgiacomo.travaglini@arm.comItsCommand::movall(Yield &yield, CommandEntry &command)
64513996Sgiacomo.travaglini@arm.com{
64613996Sgiacomo.travaglini@arm.com    const uint64_t rd1 = bits(command.raw[2], 50, 16);
64713996Sgiacomo.travaglini@arm.com    const uint64_t rd2 = bits(command.raw[3], 50, 16);
64813996Sgiacomo.travaglini@arm.com
64913996Sgiacomo.travaglini@arm.com    if (rd1 != rd2) {
65013996Sgiacomo.travaglini@arm.com        Gicv3Redistributor * redist1 = its.getRedistributor(rd1);
65113996Sgiacomo.travaglini@arm.com        Gicv3Redistributor * redist2 = its.getRedistributor(rd2);
65213996Sgiacomo.travaglini@arm.com
65313996Sgiacomo.travaglini@arm.com        its.moveAllPendingState(redist1, redist2);
65413996Sgiacomo.travaglini@arm.com    }
65513996Sgiacomo.travaglini@arm.com}
65613996Sgiacomo.travaglini@arm.com
65713996Sgiacomo.travaglini@arm.comvoid
65813996Sgiacomo.travaglini@arm.comItsCommand::movi(Yield &yield, CommandEntry &command)
65913996Sgiacomo.travaglini@arm.com{
66013996Sgiacomo.travaglini@arm.com    if (deviceOutOfRange(command)) {
66113996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
66213996Sgiacomo.travaglini@arm.com        terminate(yield);
66313996Sgiacomo.travaglini@arm.com    }
66413996Sgiacomo.travaglini@arm.com
66513996Sgiacomo.travaglini@arm.com    if (collectionOutOfRange(command)) {
66613996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
66713996Sgiacomo.travaglini@arm.com        terminate(yield);
66813996Sgiacomo.travaglini@arm.com    }
66913996Sgiacomo.travaglini@arm.com
67013996Sgiacomo.travaglini@arm.com    DTE dte = readDeviceTable(yield, command.deviceId);
67113996Sgiacomo.travaglini@arm.com
67213996Sgiacomo.travaglini@arm.com    if (!dte.valid || idOutOfRange(command, dte)) {
67313996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
67413996Sgiacomo.travaglini@arm.com        terminate(yield);
67513996Sgiacomo.travaglini@arm.com    }
67613996Sgiacomo.travaglini@arm.com
67713996Sgiacomo.travaglini@arm.com    ITTE itte = readIrqTranslationTable(
67813996Sgiacomo.travaglini@arm.com        yield, dte.ittAddress, command.eventId);
67913996Sgiacomo.travaglini@arm.com
68013996Sgiacomo.travaglini@arm.com    if (!itte.valid || itte.intType == Gicv3Its::VIRTUAL_INTERRUPT) {
68113996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
68213996Sgiacomo.travaglini@arm.com        terminate(yield);
68313996Sgiacomo.travaglini@arm.com    }
68413996Sgiacomo.travaglini@arm.com
68513996Sgiacomo.travaglini@arm.com    const auto collection_id1 = itte.icid;
68613996Sgiacomo.travaglini@arm.com    CTE cte1 = readIrqCollectionTable(yield, collection_id1);
68713996Sgiacomo.travaglini@arm.com
68813996Sgiacomo.travaglini@arm.com    if (!cte1.valid) {
68913996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
69013996Sgiacomo.travaglini@arm.com        terminate(yield);
69113996Sgiacomo.travaglini@arm.com    }
69213996Sgiacomo.travaglini@arm.com
69313996Sgiacomo.travaglini@arm.com    const auto collection_id2 = bits(command.raw[2], 15, 0);
69413996Sgiacomo.travaglini@arm.com    CTE cte2 = readIrqCollectionTable(yield, collection_id2);
69513996Sgiacomo.travaglini@arm.com
69613996Sgiacomo.travaglini@arm.com    if (!cte2.valid) {
69713996Sgiacomo.travaglini@arm.com        its.incrementReadPointer();
69813996Sgiacomo.travaglini@arm.com        terminate(yield);
69913996Sgiacomo.travaglini@arm.com    }
70013996Sgiacomo.travaglini@arm.com
70113996Sgiacomo.travaglini@arm.com    Gicv3Redistributor *first_redist = its.getRedistributor(cte1);
70213996Sgiacomo.travaglini@arm.com    Gicv3Redistributor *second_redist = its.getRedistributor(cte2);
70313996Sgiacomo.travaglini@arm.com
70413996Sgiacomo.travaglini@arm.com    if (second_redist != first_redist) {
70513996Sgiacomo.travaglini@arm.com        // move pending state of the interrupt from one redistributor
70613996Sgiacomo.travaglini@arm.com        // to the other.
70713996Sgiacomo.travaglini@arm.com        if (first_redist->isPendingLPI(itte.intNum)) {
70813996Sgiacomo.travaglini@arm.com            first_redist->setClrLPI(itte.intNum, false);
70913996Sgiacomo.travaglini@arm.com            second_redist->setClrLPI(itte.intNum, true);
71013996Sgiacomo.travaglini@arm.com        }
71113996Sgiacomo.travaglini@arm.com    }
71213996Sgiacomo.travaglini@arm.com
71313996Sgiacomo.travaglini@arm.com    itte.icid = collection_id2;
71413996Sgiacomo.travaglini@arm.com    writeIrqTranslationTable(
71513996Sgiacomo.travaglini@arm.com        yield, dte.ittAddress, command.eventId, itte);
71613996Sgiacomo.travaglini@arm.com}
71713996Sgiacomo.travaglini@arm.com
71813996Sgiacomo.travaglini@arm.comvoid
71913996Sgiacomo.travaglini@arm.comItsCommand::sync(Yield &yield, CommandEntry &command)
72013996Sgiacomo.travaglini@arm.com{
72113996Sgiacomo.travaglini@arm.com    warn("ITS %s command unimplemented", __func__);
72213996Sgiacomo.travaglini@arm.com}
72313996Sgiacomo.travaglini@arm.com
72413996Sgiacomo.travaglini@arm.comvoid
72513996Sgiacomo.travaglini@arm.comItsCommand::vinvall(Yield &yield, CommandEntry &command)
72613996Sgiacomo.travaglini@arm.com{
72713996Sgiacomo.travaglini@arm.com    panic("ITS %s command unimplemented", __func__);
72813996Sgiacomo.travaglini@arm.com}
72913996Sgiacomo.travaglini@arm.com
73013996Sgiacomo.travaglini@arm.comvoid
73113996Sgiacomo.travaglini@arm.comItsCommand::vmapi(Yield &yield, CommandEntry &command)
73213996Sgiacomo.travaglini@arm.com{
73313996Sgiacomo.travaglini@arm.com    panic("ITS %s command unimplemented", __func__);
73413996Sgiacomo.travaglini@arm.com}
73513996Sgiacomo.travaglini@arm.com
73613996Sgiacomo.travaglini@arm.comvoid
73713996Sgiacomo.travaglini@arm.comItsCommand::vmapp(Yield &yield, CommandEntry &command)
73813996Sgiacomo.travaglini@arm.com{
73913996Sgiacomo.travaglini@arm.com    panic("ITS %s command unimplemented", __func__);
74013996Sgiacomo.travaglini@arm.com}
74113996Sgiacomo.travaglini@arm.com
74213996Sgiacomo.travaglini@arm.comvoid
74313996Sgiacomo.travaglini@arm.comItsCommand::vmapti(Yield &yield, CommandEntry &command)
74413996Sgiacomo.travaglini@arm.com{
74513996Sgiacomo.travaglini@arm.com    panic("ITS %s command unimplemented", __func__);
74613996Sgiacomo.travaglini@arm.com}
74713996Sgiacomo.travaglini@arm.com
74813996Sgiacomo.travaglini@arm.comvoid
74913996Sgiacomo.travaglini@arm.comItsCommand::vmovi(Yield &yield, CommandEntry &command)
75013996Sgiacomo.travaglini@arm.com{
75113996Sgiacomo.travaglini@arm.com    panic("ITS %s command unimplemented", __func__);
75213996Sgiacomo.travaglini@arm.com}
75313996Sgiacomo.travaglini@arm.com
75413996Sgiacomo.travaglini@arm.comvoid
75513996Sgiacomo.travaglini@arm.comItsCommand::vmovp(Yield &yield, CommandEntry &command)
75613996Sgiacomo.travaglini@arm.com{
75713996Sgiacomo.travaglini@arm.com    panic("ITS %s command unimplemented", __func__);
75813996Sgiacomo.travaglini@arm.com}
75913996Sgiacomo.travaglini@arm.com
76013996Sgiacomo.travaglini@arm.comvoid
76113996Sgiacomo.travaglini@arm.comItsCommand::vsync(Yield &yield, CommandEntry &command)
76213996Sgiacomo.travaglini@arm.com{
76313996Sgiacomo.travaglini@arm.com    panic("ITS %s command unimplemented", __func__);
76413996Sgiacomo.travaglini@arm.com}
76513996Sgiacomo.travaglini@arm.com
76613996Sgiacomo.travaglini@arm.comGicv3Its::Gicv3Its(const Gicv3ItsParams *params)
76713996Sgiacomo.travaglini@arm.com : BasicPioDevice(params, params->pio_size),
76813996Sgiacomo.travaglini@arm.com   dmaPort(name() + ".dma", *this),
76913996Sgiacomo.travaglini@arm.com   gitsControl(0x1),
77013996Sgiacomo.travaglini@arm.com   gitsTyper(params->gits_typer),
77113996Sgiacomo.travaglini@arm.com   gitsCbaser(0), gitsCreadr(0),
77213996Sgiacomo.travaglini@arm.com   gitsCwriter(0), gitsIidr(0),
77313996Sgiacomo.travaglini@arm.com   masterId(params->system->getMasterId(this)),
77413996Sgiacomo.travaglini@arm.com   gic(nullptr),
77513996Sgiacomo.travaglini@arm.com   commandEvent([this] { checkCommandQueue(); }, name()),
77613996Sgiacomo.travaglini@arm.com   pendingCommands(false),
77713996Sgiacomo.travaglini@arm.com   pendingTranslations(0)
77813996Sgiacomo.travaglini@arm.com{
77913996Sgiacomo.travaglini@arm.com    for (auto idx = 0; idx < NUM_BASER_REGS; idx++) {
78013996Sgiacomo.travaglini@arm.com        BASER gits_baser = 0;
78113996Sgiacomo.travaglini@arm.com        gits_baser.type = idx;
78213996Sgiacomo.travaglini@arm.com        gits_baser.entrySize = sizeof(uint64_t) - 1;
78313996Sgiacomo.travaglini@arm.com        tableBases.push_back(gits_baser);
78413996Sgiacomo.travaglini@arm.com    }
78513996Sgiacomo.travaglini@arm.com}
78613996Sgiacomo.travaglini@arm.com
78713996Sgiacomo.travaglini@arm.comvoid
78813996Sgiacomo.travaglini@arm.comGicv3Its::setGIC(Gicv3 *_gic)
78913996Sgiacomo.travaglini@arm.com{
79013996Sgiacomo.travaglini@arm.com    assert(!gic);
79113996Sgiacomo.travaglini@arm.com    gic = _gic;
79213996Sgiacomo.travaglini@arm.com}
79313996Sgiacomo.travaglini@arm.com
79413996Sgiacomo.travaglini@arm.comAddrRangeList
79513996Sgiacomo.travaglini@arm.comGicv3Its::getAddrRanges() const
79613996Sgiacomo.travaglini@arm.com{
79713996Sgiacomo.travaglini@arm.com    assert(pioSize != 0);
79813996Sgiacomo.travaglini@arm.com    AddrRangeList ranges;
79913996Sgiacomo.travaglini@arm.com    DPRINTF(AddrRanges, "registering range: %#x-%#x\n", pioAddr, pioSize);
80013996Sgiacomo.travaglini@arm.com    ranges.push_back(RangeSize(pioAddr, pioSize));
80113996Sgiacomo.travaglini@arm.com    return ranges;
80213996Sgiacomo.travaglini@arm.com}
80313996Sgiacomo.travaglini@arm.com
80413996Sgiacomo.travaglini@arm.comTick
80513996Sgiacomo.travaglini@arm.comGicv3Its::read(PacketPtr pkt)
80613996Sgiacomo.travaglini@arm.com{
80713996Sgiacomo.travaglini@arm.com    const Addr addr = pkt->getAddr() - pioAddr;
80813996Sgiacomo.travaglini@arm.com    uint64_t value = 0;
80913996Sgiacomo.travaglini@arm.com
81013996Sgiacomo.travaglini@arm.com    DPRINTF(GIC, "%s register at addr: %#x\n", __func__, addr);
81113996Sgiacomo.travaglini@arm.com
81213996Sgiacomo.travaglini@arm.com    switch (addr) {
81313996Sgiacomo.travaglini@arm.com      case GITS_CTLR:
81413996Sgiacomo.travaglini@arm.com        value = gitsControl;
81513996Sgiacomo.travaglini@arm.com        break;
81613996Sgiacomo.travaglini@arm.com
81713996Sgiacomo.travaglini@arm.com      case GITS_IIDR:
81813996Sgiacomo.travaglini@arm.com        value = gitsIidr;
81913996Sgiacomo.travaglini@arm.com        break;
82013996Sgiacomo.travaglini@arm.com
82113996Sgiacomo.travaglini@arm.com      case GITS_TYPER:
82213996Sgiacomo.travaglini@arm.com        value = gitsTyper;
82313996Sgiacomo.travaglini@arm.com        break;
82413996Sgiacomo.travaglini@arm.com
82513996Sgiacomo.travaglini@arm.com      case GITS_CBASER:
82613996Sgiacomo.travaglini@arm.com        value = gitsCbaser;
82713996Sgiacomo.travaglini@arm.com        break;
82813996Sgiacomo.travaglini@arm.com
82913996Sgiacomo.travaglini@arm.com      case GITS_CWRITER:
83013996Sgiacomo.travaglini@arm.com        value = gitsCwriter;
83113996Sgiacomo.travaglini@arm.com        break;
83213996Sgiacomo.travaglini@arm.com
83313996Sgiacomo.travaglini@arm.com      case GITS_CREADR:
83413996Sgiacomo.travaglini@arm.com        value = gitsCreadr;
83513996Sgiacomo.travaglini@arm.com        break;
83613996Sgiacomo.travaglini@arm.com
83714168Sgiacomo.travaglini@arm.com      case GITS_PIDR2:
83814168Sgiacomo.travaglini@arm.com        value = gic->getDistributor()->gicdPidr2;
83914168Sgiacomo.travaglini@arm.com        break;
84014168Sgiacomo.travaglini@arm.com
84113996Sgiacomo.travaglini@arm.com      case GITS_TRANSLATER:
84213996Sgiacomo.travaglini@arm.com        value = gitsTranslater;
84313996Sgiacomo.travaglini@arm.com        break;
84413996Sgiacomo.travaglini@arm.com
84513996Sgiacomo.travaglini@arm.com      default:
84613996Sgiacomo.travaglini@arm.com        if (GITS_BASER.contains(addr)) {
84713996Sgiacomo.travaglini@arm.com            auto relative_addr = addr - GITS_BASER.start();
84813996Sgiacomo.travaglini@arm.com            auto baser_index = relative_addr / sizeof(uint64_t);
84913996Sgiacomo.travaglini@arm.com
85013996Sgiacomo.travaglini@arm.com            value = tableBases[baser_index];
85113996Sgiacomo.travaglini@arm.com            break;
85213996Sgiacomo.travaglini@arm.com        } else {
85313996Sgiacomo.travaglini@arm.com            panic("Unrecognized register access\n");
85413996Sgiacomo.travaglini@arm.com        }
85513996Sgiacomo.travaglini@arm.com    }
85613996Sgiacomo.travaglini@arm.com
85713996Sgiacomo.travaglini@arm.com    pkt->setUintX(value, LittleEndianByteOrder);
85813996Sgiacomo.travaglini@arm.com    pkt->makeAtomicResponse();
85913996Sgiacomo.travaglini@arm.com    return pioDelay;
86013996Sgiacomo.travaglini@arm.com}
86113996Sgiacomo.travaglini@arm.com
86213996Sgiacomo.travaglini@arm.comTick
86313996Sgiacomo.travaglini@arm.comGicv3Its::write(PacketPtr pkt)
86413996Sgiacomo.travaglini@arm.com{
86513996Sgiacomo.travaglini@arm.com    Addr addr = pkt->getAddr() - pioAddr;
86613996Sgiacomo.travaglini@arm.com
86713996Sgiacomo.travaglini@arm.com    DPRINTF(GIC, "%s register at addr: %#x\n", __func__, addr);
86813996Sgiacomo.travaglini@arm.com
86913996Sgiacomo.travaglini@arm.com    switch (addr) {
87013996Sgiacomo.travaglini@arm.com      case GITS_CTLR:
87113996Sgiacomo.travaglini@arm.com        assert(pkt->getSize() == sizeof(uint32_t));
87213996Sgiacomo.travaglini@arm.com        gitsControl = pkt->getLE<uint32_t>();
87313996Sgiacomo.travaglini@arm.com        break;
87413996Sgiacomo.travaglini@arm.com
87513996Sgiacomo.travaglini@arm.com      case GITS_IIDR:
87613996Sgiacomo.travaglini@arm.com        panic("GITS_IIDR is Read Only\n");
87713996Sgiacomo.travaglini@arm.com
87813996Sgiacomo.travaglini@arm.com      case GITS_TYPER:
87913996Sgiacomo.travaglini@arm.com        panic("GITS_TYPER is Read Only\n");
88013996Sgiacomo.travaglini@arm.com
88113996Sgiacomo.travaglini@arm.com      case GITS_CBASER:
88213996Sgiacomo.travaglini@arm.com        assert(pkt->getSize() == sizeof(uint64_t));
88313996Sgiacomo.travaglini@arm.com        gitsCbaser = pkt->getLE<uint64_t>();
88413996Sgiacomo.travaglini@arm.com        gitsCreadr = 0; // Cleared when CBASER gets written
88513996Sgiacomo.travaglini@arm.com
88613996Sgiacomo.travaglini@arm.com        checkCommandQueue();
88713996Sgiacomo.travaglini@arm.com        break;
88813996Sgiacomo.travaglini@arm.com
88913996Sgiacomo.travaglini@arm.com      case GITS_CWRITER:
89013996Sgiacomo.travaglini@arm.com        assert(pkt->getSize() == sizeof(uint64_t));
89113996Sgiacomo.travaglini@arm.com        gitsCwriter = pkt->getLE<uint64_t>();
89213996Sgiacomo.travaglini@arm.com
89313996Sgiacomo.travaglini@arm.com        checkCommandQueue();
89413996Sgiacomo.travaglini@arm.com        break;
89513996Sgiacomo.travaglini@arm.com
89613996Sgiacomo.travaglini@arm.com      case GITS_CREADR:
89713996Sgiacomo.travaglini@arm.com        panic("GITS_READR is Read Only\n");
89813996Sgiacomo.travaglini@arm.com
89913996Sgiacomo.travaglini@arm.com      case GITS_TRANSLATER:
90013996Sgiacomo.travaglini@arm.com        if (gitsControl.enabled) {
90113996Sgiacomo.travaglini@arm.com            translate(pkt);
90213996Sgiacomo.travaglini@arm.com        }
90313996Sgiacomo.travaglini@arm.com        break;
90413996Sgiacomo.travaglini@arm.com
90513996Sgiacomo.travaglini@arm.com      default:
90613996Sgiacomo.travaglini@arm.com        if (GITS_BASER.contains(addr)) {
90713996Sgiacomo.travaglini@arm.com            auto relative_addr = addr - GITS_BASER.start();
90813996Sgiacomo.travaglini@arm.com            auto baser_index = relative_addr / sizeof(uint64_t);
90913996Sgiacomo.travaglini@arm.com
91013996Sgiacomo.travaglini@arm.com            BASER val = pkt->getLE<uint64_t>();
91113996Sgiacomo.travaglini@arm.com
91213996Sgiacomo.travaglini@arm.com            panic_if(val.indirect,
91313996Sgiacomo.travaglini@arm.com                "We currently don't support two level ITS tables");
91413996Sgiacomo.travaglini@arm.com
91513996Sgiacomo.travaglini@arm.com            tableBases[baser_index] = val;
91613996Sgiacomo.travaglini@arm.com            break;
91713996Sgiacomo.travaglini@arm.com        } else {
91813996Sgiacomo.travaglini@arm.com            panic("Unrecognized register access\n");
91913996Sgiacomo.travaglini@arm.com        }
92013996Sgiacomo.travaglini@arm.com    }
92113996Sgiacomo.travaglini@arm.com
92213996Sgiacomo.travaglini@arm.com    pkt->makeAtomicResponse();
92313996Sgiacomo.travaglini@arm.com    return pioDelay;
92413996Sgiacomo.travaglini@arm.com}
92513996Sgiacomo.travaglini@arm.com
92613996Sgiacomo.travaglini@arm.combool
92713996Sgiacomo.travaglini@arm.comGicv3Its::idOutOfRange(uint32_t event_id, uint8_t itt_range) const
92813996Sgiacomo.travaglini@arm.com{
92913996Sgiacomo.travaglini@arm.com    const uint32_t id_bits = gitsTyper.idBits;
93013996Sgiacomo.travaglini@arm.com    return event_id >= (1ULL << (id_bits + 1)) ||
93113996Sgiacomo.travaglini@arm.com        event_id >= ((1ULL << itt_range) + 1);
93213996Sgiacomo.travaglini@arm.com}
93313996Sgiacomo.travaglini@arm.com
93413996Sgiacomo.travaglini@arm.combool
93513996Sgiacomo.travaglini@arm.comGicv3Its::deviceOutOfRange(uint32_t device_id) const
93613996Sgiacomo.travaglini@arm.com{
93713996Sgiacomo.travaglini@arm.com    return device_id >= (1ULL << (gitsTyper.devBits + 1));
93813996Sgiacomo.travaglini@arm.com}
93913996Sgiacomo.travaglini@arm.com
94013996Sgiacomo.travaglini@arm.combool
94113996Sgiacomo.travaglini@arm.comGicv3Its::sizeOutOfRange(uint32_t size) const
94213996Sgiacomo.travaglini@arm.com{
94313996Sgiacomo.travaglini@arm.com    return size > gitsTyper.idBits;
94413996Sgiacomo.travaglini@arm.com}
94513996Sgiacomo.travaglini@arm.com
94613996Sgiacomo.travaglini@arm.combool
94713996Sgiacomo.travaglini@arm.comGicv3Its::collectionOutOfRange(uint32_t collection_id) const
94813996Sgiacomo.travaglini@arm.com{
94913996Sgiacomo.travaglini@arm.com    // If GITS_TYPER.CIL == 0, ITS supports 16-bit CollectionID
95013996Sgiacomo.travaglini@arm.com    // Otherwise, #bits is specified by GITS_TYPER.CIDbits
95113996Sgiacomo.travaglini@arm.com    const auto cid_bits = gitsTyper.cil == 0 ?
95213996Sgiacomo.travaglini@arm.com        16 : gitsTyper.cidBits + 1;
95313996Sgiacomo.travaglini@arm.com
95413996Sgiacomo.travaglini@arm.com    return collection_id >= (1ULL << cid_bits);
95513996Sgiacomo.travaglini@arm.com}
95613996Sgiacomo.travaglini@arm.com
95713996Sgiacomo.travaglini@arm.combool
95813996Sgiacomo.travaglini@arm.comGicv3Its::lpiOutOfRange(uint32_t intid) const
95913996Sgiacomo.travaglini@arm.com{
96013996Sgiacomo.travaglini@arm.com    return intid >= (1ULL << (Gicv3Distributor::IDBITS + 1)) ||
96113996Sgiacomo.travaglini@arm.com           (intid < Gicv3Redistributor::SMALLEST_LPI_ID &&
96213996Sgiacomo.travaglini@arm.com            intid != Gicv3::INTID_SPURIOUS);
96313996Sgiacomo.travaglini@arm.com}
96413996Sgiacomo.travaglini@arm.com
96513996Sgiacomo.travaglini@arm.comDrainState
96613996Sgiacomo.travaglini@arm.comGicv3Its::drain()
96713996Sgiacomo.travaglini@arm.com{
96813996Sgiacomo.travaglini@arm.com    if (!pendingCommands && !pendingTranslations) {
96913996Sgiacomo.travaglini@arm.com        return DrainState::Drained;
97013996Sgiacomo.travaglini@arm.com    } else {
97113996Sgiacomo.travaglini@arm.com        DPRINTF(Drain, "GICv3 ITS not drained\n");
97213996Sgiacomo.travaglini@arm.com        return DrainState::Draining;
97313996Sgiacomo.travaglini@arm.com    }
97413996Sgiacomo.travaglini@arm.com}
97513996Sgiacomo.travaglini@arm.com
97613996Sgiacomo.travaglini@arm.comvoid
97713996Sgiacomo.travaglini@arm.comGicv3Its::serialize(CheckpointOut & cp) const
97813996Sgiacomo.travaglini@arm.com{
97913996Sgiacomo.travaglini@arm.com    SERIALIZE_SCALAR(gitsControl);
98013996Sgiacomo.travaglini@arm.com    SERIALIZE_SCALAR(gitsTyper);
98113996Sgiacomo.travaglini@arm.com    SERIALIZE_SCALAR(gitsCbaser);
98213996Sgiacomo.travaglini@arm.com    SERIALIZE_SCALAR(gitsCreadr);
98313996Sgiacomo.travaglini@arm.com    SERIALIZE_SCALAR(gitsCwriter);
98413996Sgiacomo.travaglini@arm.com    SERIALIZE_SCALAR(gitsIidr);
98513996Sgiacomo.travaglini@arm.com
98613996Sgiacomo.travaglini@arm.com    SERIALIZE_CONTAINER(tableBases);
98713996Sgiacomo.travaglini@arm.com}
98813996Sgiacomo.travaglini@arm.com
98913996Sgiacomo.travaglini@arm.comvoid
99013996Sgiacomo.travaglini@arm.comGicv3Its::unserialize(CheckpointIn & cp)
99113996Sgiacomo.travaglini@arm.com{
99213996Sgiacomo.travaglini@arm.com    UNSERIALIZE_SCALAR(gitsControl);
99313996Sgiacomo.travaglini@arm.com    UNSERIALIZE_SCALAR(gitsTyper);
99413996Sgiacomo.travaglini@arm.com    UNSERIALIZE_SCALAR(gitsCbaser);
99513996Sgiacomo.travaglini@arm.com    UNSERIALIZE_SCALAR(gitsCreadr);
99613996Sgiacomo.travaglini@arm.com    UNSERIALIZE_SCALAR(gitsCwriter);
99713996Sgiacomo.travaglini@arm.com    UNSERIALIZE_SCALAR(gitsIidr);
99813996Sgiacomo.travaglini@arm.com
99913996Sgiacomo.travaglini@arm.com    UNSERIALIZE_CONTAINER(tableBases);
100013996Sgiacomo.travaglini@arm.com}
100113996Sgiacomo.travaglini@arm.com
100213996Sgiacomo.travaglini@arm.comvoid
100313996Sgiacomo.travaglini@arm.comGicv3Its::incrementReadPointer()
100413996Sgiacomo.travaglini@arm.com{
100513996Sgiacomo.travaglini@arm.com    // Make the reader point to the next element
100613996Sgiacomo.travaglini@arm.com    gitsCreadr.offset = gitsCreadr.offset + 1;
100713996Sgiacomo.travaglini@arm.com
100813996Sgiacomo.travaglini@arm.com    // Check for wrapping
100913996Sgiacomo.travaglini@arm.com    auto queue_end = (4096 * (gitsCbaser.size + 1));
101013996Sgiacomo.travaglini@arm.com
101113996Sgiacomo.travaglini@arm.com    if (gitsCreadr.offset == queue_end) {
101213996Sgiacomo.travaglini@arm.com        gitsCreadr.offset = 0;
101313996Sgiacomo.travaglini@arm.com    }
101413996Sgiacomo.travaglini@arm.com}
101513996Sgiacomo.travaglini@arm.com
101613996Sgiacomo.travaglini@arm.comvoid
101713996Sgiacomo.travaglini@arm.comGicv3Its::checkCommandQueue()
101813996Sgiacomo.travaglini@arm.com{
101913996Sgiacomo.travaglini@arm.com    if (!gitsControl.enabled || !gitsCbaser.valid)
102013996Sgiacomo.travaglini@arm.com        return;
102113996Sgiacomo.travaglini@arm.com
102213996Sgiacomo.travaglini@arm.com    if (gitsCwriter.offset != gitsCreadr.offset) {
102313996Sgiacomo.travaglini@arm.com        // writer and reader pointing to different command
102413996Sgiacomo.travaglini@arm.com        // entries: queue not empty.
102513996Sgiacomo.travaglini@arm.com        DPRINTF(ITS, "Reading command from queue\n");
102613996Sgiacomo.travaglini@arm.com
102713996Sgiacomo.travaglini@arm.com        if (!pendingCommands) {
102813996Sgiacomo.travaglini@arm.com            auto *cmd_proc = new ItsCommand(*this);
102913996Sgiacomo.travaglini@arm.com
103013996Sgiacomo.travaglini@arm.com            runProcess(cmd_proc, nullptr);
103113996Sgiacomo.travaglini@arm.com        } else {
103213996Sgiacomo.travaglini@arm.com            DPRINTF(ITS, "Waiting for pending command to finish\n");
103313996Sgiacomo.travaglini@arm.com        }
103413996Sgiacomo.travaglini@arm.com    }
103513996Sgiacomo.travaglini@arm.com}
103613996Sgiacomo.travaglini@arm.com
103713996Sgiacomo.travaglini@arm.comPort &
103813996Sgiacomo.travaglini@arm.comGicv3Its::getPort(const std::string &if_name, PortID idx)
103913996Sgiacomo.travaglini@arm.com{
104013996Sgiacomo.travaglini@arm.com    if (if_name == "dma") {
104113996Sgiacomo.travaglini@arm.com        return dmaPort;
104213996Sgiacomo.travaglini@arm.com    }
104313996Sgiacomo.travaglini@arm.com    return BasicPioDevice::getPort(if_name, idx);
104413996Sgiacomo.travaglini@arm.com}
104513996Sgiacomo.travaglini@arm.com
104613996Sgiacomo.travaglini@arm.comvoid
104713996Sgiacomo.travaglini@arm.comGicv3Its::recvReqRetry()
104813996Sgiacomo.travaglini@arm.com{
104913996Sgiacomo.travaglini@arm.com    assert(!packetsToRetry.empty());
105013996Sgiacomo.travaglini@arm.com
105113996Sgiacomo.travaglini@arm.com    while (!packetsToRetry.empty()) {
105213996Sgiacomo.travaglini@arm.com        ItsAction a = packetsToRetry.front();
105313996Sgiacomo.travaglini@arm.com
105413996Sgiacomo.travaglini@arm.com        assert(a.type == ItsActionType::SEND_REQ);
105513996Sgiacomo.travaglini@arm.com
105613996Sgiacomo.travaglini@arm.com        if (!dmaPort.sendTimingReq(a.pkt))
105713996Sgiacomo.travaglini@arm.com            break;
105813996Sgiacomo.travaglini@arm.com
105913996Sgiacomo.travaglini@arm.com        packetsToRetry.pop();
106013996Sgiacomo.travaglini@arm.com    }
106113996Sgiacomo.travaglini@arm.com}
106213996Sgiacomo.travaglini@arm.com
106313996Sgiacomo.travaglini@arm.combool
106413996Sgiacomo.travaglini@arm.comGicv3Its::recvTimingResp(PacketPtr pkt)
106513996Sgiacomo.travaglini@arm.com{
106613996Sgiacomo.travaglini@arm.com    // @todo: We need to pay for this and not just zero it out
106713996Sgiacomo.travaglini@arm.com    pkt->headerDelay = pkt->payloadDelay = 0;
106813996Sgiacomo.travaglini@arm.com
106913996Sgiacomo.travaglini@arm.com    ItsProcess *proc =
107013996Sgiacomo.travaglini@arm.com        safe_cast<ItsProcess *>(pkt->popSenderState());
107113996Sgiacomo.travaglini@arm.com
107213996Sgiacomo.travaglini@arm.com    runProcessTiming(proc, pkt);
107313996Sgiacomo.travaglini@arm.com
107413996Sgiacomo.travaglini@arm.com    return true;
107513996Sgiacomo.travaglini@arm.com}
107613996Sgiacomo.travaglini@arm.com
107713996Sgiacomo.travaglini@arm.comItsAction
107813996Sgiacomo.travaglini@arm.comGicv3Its::runProcess(ItsProcess *proc, PacketPtr pkt)
107913996Sgiacomo.travaglini@arm.com{
108013996Sgiacomo.travaglini@arm.com    if (sys->isAtomicMode()) {
108113996Sgiacomo.travaglini@arm.com        return runProcessAtomic(proc, pkt);
108213996Sgiacomo.travaglini@arm.com    } else if (sys->isTimingMode()) {
108313996Sgiacomo.travaglini@arm.com        return runProcessTiming(proc, pkt);
108413996Sgiacomo.travaglini@arm.com    } else {
108513996Sgiacomo.travaglini@arm.com        panic("Not in timing or atomic mode\n");
108613996Sgiacomo.travaglini@arm.com    }
108713996Sgiacomo.travaglini@arm.com}
108813996Sgiacomo.travaglini@arm.com
108913996Sgiacomo.travaglini@arm.comItsAction
109013996Sgiacomo.travaglini@arm.comGicv3Its::runProcessTiming(ItsProcess *proc, PacketPtr pkt)
109113996Sgiacomo.travaglini@arm.com{
109213996Sgiacomo.travaglini@arm.com    ItsAction action = proc->run(pkt);
109313996Sgiacomo.travaglini@arm.com
109413996Sgiacomo.travaglini@arm.com    switch (action.type) {
109513996Sgiacomo.travaglini@arm.com      case ItsActionType::SEND_REQ:
109613996Sgiacomo.travaglini@arm.com        action.pkt->pushSenderState(proc);
109713996Sgiacomo.travaglini@arm.com
109813996Sgiacomo.travaglini@arm.com        if (packetsToRetry.empty() &&
109913996Sgiacomo.travaglini@arm.com            dmaPort.sendTimingReq(action.pkt)) {
110013996Sgiacomo.travaglini@arm.com
110113996Sgiacomo.travaglini@arm.com        } else {
110213996Sgiacomo.travaglini@arm.com            packetsToRetry.push(action);
110313996Sgiacomo.travaglini@arm.com        }
110413996Sgiacomo.travaglini@arm.com        break;
110513996Sgiacomo.travaglini@arm.com
110613996Sgiacomo.travaglini@arm.com      case ItsActionType::TERMINATE:
110713996Sgiacomo.travaglini@arm.com        delete proc;
110813996Sgiacomo.travaglini@arm.com        if (!pendingCommands && !commandEvent.scheduled()) {
110913996Sgiacomo.travaglini@arm.com            schedule(commandEvent, clockEdge());
111013996Sgiacomo.travaglini@arm.com        }
111113996Sgiacomo.travaglini@arm.com        break;
111213996Sgiacomo.travaglini@arm.com
111313996Sgiacomo.travaglini@arm.com      default:
111413996Sgiacomo.travaglini@arm.com        panic("Unknown action\n");
111513996Sgiacomo.travaglini@arm.com    }
111613996Sgiacomo.travaglini@arm.com
111713996Sgiacomo.travaglini@arm.com    return action;
111813996Sgiacomo.travaglini@arm.com}
111913996Sgiacomo.travaglini@arm.com
112013996Sgiacomo.travaglini@arm.comItsAction
112113996Sgiacomo.travaglini@arm.comGicv3Its::runProcessAtomic(ItsProcess *proc, PacketPtr pkt)
112213996Sgiacomo.travaglini@arm.com{
112313996Sgiacomo.travaglini@arm.com    ItsAction action;
112413996Sgiacomo.travaglini@arm.com    Tick delay = 0;
112513996Sgiacomo.travaglini@arm.com    bool terminate = false;
112613996Sgiacomo.travaglini@arm.com
112713996Sgiacomo.travaglini@arm.com    do {
112813996Sgiacomo.travaglini@arm.com        action = proc->run(pkt);
112913996Sgiacomo.travaglini@arm.com
113013996Sgiacomo.travaglini@arm.com        switch (action.type) {
113113996Sgiacomo.travaglini@arm.com          case ItsActionType::SEND_REQ:
113213996Sgiacomo.travaglini@arm.com            delay += dmaPort.sendAtomic(action.pkt);
113313996Sgiacomo.travaglini@arm.com            pkt = action.pkt;
113413996Sgiacomo.travaglini@arm.com            break;
113513996Sgiacomo.travaglini@arm.com
113613996Sgiacomo.travaglini@arm.com          case ItsActionType::TERMINATE:
113713996Sgiacomo.travaglini@arm.com            delete proc;
113813996Sgiacomo.travaglini@arm.com            terminate = true;
113913996Sgiacomo.travaglini@arm.com            break;
114013996Sgiacomo.travaglini@arm.com
114113996Sgiacomo.travaglini@arm.com          default:
114213996Sgiacomo.travaglini@arm.com            panic("Unknown action\n");
114313996Sgiacomo.travaglini@arm.com        }
114413996Sgiacomo.travaglini@arm.com
114513996Sgiacomo.travaglini@arm.com    } while (!terminate);
114613996Sgiacomo.travaglini@arm.com
114713996Sgiacomo.travaglini@arm.com    action.delay = delay;
114813996Sgiacomo.travaglini@arm.com
114913996Sgiacomo.travaglini@arm.com    return action;
115013996Sgiacomo.travaglini@arm.com}
115113996Sgiacomo.travaglini@arm.com
115213996Sgiacomo.travaglini@arm.comvoid
115313996Sgiacomo.travaglini@arm.comGicv3Its::translate(PacketPtr pkt)
115413996Sgiacomo.travaglini@arm.com{
115513996Sgiacomo.travaglini@arm.com    DPRINTF(ITS, "Starting Translation Request\n");
115613996Sgiacomo.travaglini@arm.com
115713996Sgiacomo.travaglini@arm.com    auto *proc = new ItsTranslation(*this);
115813996Sgiacomo.travaglini@arm.com    runProcess(proc, pkt);
115913996Sgiacomo.travaglini@arm.com}
116013996Sgiacomo.travaglini@arm.com
116113996Sgiacomo.travaglini@arm.comGicv3Redistributor*
116213996Sgiacomo.travaglini@arm.comGicv3Its::getRedistributor(uint64_t rd_base)
116313996Sgiacomo.travaglini@arm.com{
116413996Sgiacomo.travaglini@arm.com    if (gitsTyper.pta == 1) {
116513996Sgiacomo.travaglini@arm.com        // RDBase is a redistributor address
116613996Sgiacomo.travaglini@arm.com        return gic->getRedistributorByAddr(rd_base << 16);
116713996Sgiacomo.travaglini@arm.com    } else {
116813996Sgiacomo.travaglini@arm.com        // RDBase is a redistributor number
116913996Sgiacomo.travaglini@arm.com        return gic->getRedistributor(rd_base);
117013996Sgiacomo.travaglini@arm.com    }
117113996Sgiacomo.travaglini@arm.com}
117213996Sgiacomo.travaglini@arm.com
117313996Sgiacomo.travaglini@arm.comAddr
117413996Sgiacomo.travaglini@arm.comGicv3Its::pageAddress(Gicv3Its::ItsTables table)
117513996Sgiacomo.travaglini@arm.com{
117613996Sgiacomo.travaglini@arm.com    const BASER base = tableBases[table];
117713996Sgiacomo.travaglini@arm.com    // real address depends on page size
117813996Sgiacomo.travaglini@arm.com    switch (base.pageSize) {
117913996Sgiacomo.travaglini@arm.com      case SIZE_4K:
118013996Sgiacomo.travaglini@arm.com      case SIZE_16K:
118113996Sgiacomo.travaglini@arm.com        return mbits(base, 47, 12);
118213996Sgiacomo.travaglini@arm.com      case SIZE_64K:
118313996Sgiacomo.travaglini@arm.com        return mbits(base, 47, 16) | (bits(base, 15, 12) << 48);
118413996Sgiacomo.travaglini@arm.com      default:
118513996Sgiacomo.travaglini@arm.com        panic("Unsupported page size\n");
118613996Sgiacomo.travaglini@arm.com    }
118713996Sgiacomo.travaglini@arm.com}
118813996Sgiacomo.travaglini@arm.com
118913996Sgiacomo.travaglini@arm.comvoid
119013996Sgiacomo.travaglini@arm.comGicv3Its::moveAllPendingState(
119113996Sgiacomo.travaglini@arm.com    Gicv3Redistributor *rd1, Gicv3Redistributor *rd2)
119213996Sgiacomo.travaglini@arm.com{
119313996Sgiacomo.travaglini@arm.com    const uint64_t largest_lpi_id = 1ULL << (rd1->lpiIDBits + 1);
119413996Sgiacomo.travaglini@arm.com    uint8_t lpi_pending_table[largest_lpi_id / 8];
119513996Sgiacomo.travaglini@arm.com
119613996Sgiacomo.travaglini@arm.com    // Copying the pending table from redistributor 1 to redistributor 2
119713996Sgiacomo.travaglini@arm.com    rd1->memProxy->readBlob(
119813996Sgiacomo.travaglini@arm.com        rd1->lpiPendingTablePtr, (uint8_t *)lpi_pending_table,
119913996Sgiacomo.travaglini@arm.com        sizeof(lpi_pending_table));
120013996Sgiacomo.travaglini@arm.com
120113996Sgiacomo.travaglini@arm.com    rd2->memProxy->writeBlob(
120213996Sgiacomo.travaglini@arm.com        rd2->lpiPendingTablePtr, (uint8_t *)lpi_pending_table,
120313996Sgiacomo.travaglini@arm.com        sizeof(lpi_pending_table));
120413996Sgiacomo.travaglini@arm.com
120513996Sgiacomo.travaglini@arm.com    // Clearing pending table in redistributor 2
120613996Sgiacomo.travaglini@arm.com    rd1->memProxy->memsetBlob(
120713996Sgiacomo.travaglini@arm.com        rd1->lpiPendingTablePtr,
120813996Sgiacomo.travaglini@arm.com        0, sizeof(lpi_pending_table));
120913996Sgiacomo.travaglini@arm.com
121013996Sgiacomo.travaglini@arm.com    rd2->updateAndInformCPUInterface();
121113996Sgiacomo.travaglini@arm.com}
121213996Sgiacomo.travaglini@arm.com
121313996Sgiacomo.travaglini@arm.comGicv3Its *
121413996Sgiacomo.travaglini@arm.comGicv3ItsParams::create()
121513996Sgiacomo.travaglini@arm.com{
121613996Sgiacomo.travaglini@arm.com    return new Gicv3Its(this);
121713996Sgiacomo.travaglini@arm.com}
1218