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