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