45#include "debug/AddrRanges.hh"
46#include "debug/Drain.hh"
47#include "debug/GIC.hh"
48#include "debug/ITS.hh"
53#include "params/Gicv3Its.hh"
55#define COMMAND(x, method) { x, DispatchEntry(#x, method) }
101 addr, size, 0,
its.requestorId);
106 a.pkt->dataStatic(ptr);
113 assert(pkt->
getSize() >= size);
125 addr, size, 0,
its.requestorId);
130 a.pkt->dataStatic(ptr);
137 assert(pkt->
getSize() >= size);
156 const Addr address =
base + (device_id *
sizeof(dte));
158 DPRINTF(ITS,
"Writing DTE at address %#x: %#x\n", address, dte);
160 doWrite(yield, address, &dte,
sizeof(dte));
165 Yield &yield,
const Addr itt_base, uint32_t event_id,
ITTE itte)
167 const Addr address = itt_base + (event_id *
sizeof(itte));
169 doWrite(yield, address, &itte,
sizeof(itte));
171 DPRINTF(ITS,
"Writing ITTE at address %#x: %#x\n", address, itte);
176 Yield &yield, uint32_t collection_id,
CTE cte)
179 const Addr address =
base + (collection_id *
sizeof(cte));
181 doWrite(yield, address, &cte,
sizeof(cte));
183 DPRINTF(ITS,
"Writing CTE at address %#x: %#x\n", address, cte);
191 const Addr address =
base + (device_id *
sizeof(dte));
193 doRead(yield, address, &dte,
sizeof(dte));
195 DPRINTF(ITS,
"Reading DTE at address %#x: %#x\n", address, dte);
201 Yield &yield,
const Addr itt_base, uint32_t event_id)
204 const Addr address = itt_base + (event_id *
sizeof(itte));
206 doRead(yield, address, &itte,
sizeof(itte));
208 DPRINTF(ITS,
"Reading ITTE at address %#x: %#x\n", address, itte);
217 const Addr address =
base + (collection_id *
sizeof(cte));
219 doRead(yield, address, &cte,
sizeof(cte));
221 DPRINTF(ITS,
"Reading CTE at address %#x: %#x\n", address, cte);
229 its.pendingTranslations++;
230 its.gitsControl.quiescent = 0;
235 assert(
its.pendingTranslations >= 1);
236 its.pendingTranslations--;
237 if (!
its.pendingTranslations && !
its.pendingCommands)
238 its.gitsControl.quiescent = 1;
246 const uint32_t device_id = pkt->
req->streamId();
247 const uint32_t event_id = pkt->
getLE<uint32_t>();
251 uint32_t intid = result.first;
260 its.gitsTranslater = event_id;
269 if (
its.deviceOutOfRange(device_id)) {
275 if (!dte.valid ||
its.idOutOfRange(event_id, dte.ittRange)) {
280 const auto collection_id = itte.icid;
282 if (!itte.valid ||
its.collectionOutOfRange(collection_id)) {
293 return std::make_pair(itte.intNum,
its.getRedistributor(cte));
323 its.pendingCommands =
true;
325 its.gitsControl.quiescent = 0;
330 its.pendingCommands =
false;
332 if (!
its.pendingTranslations)
333 its.gitsControl.quiescent = 1;
340 return entry !=
cmdDispatcher.end() ? entry->second.name :
"INVALID";
352 while (
its.gitsCwriter.offset !=
its.gitsCreadr.offset) {
360 its.incrementReadPointer();
370 const Addr cmd_addr =
371 (
its.gitsCbaser.physAddr << 12) + (
its.gitsCreadr.offset << 5);
373 doRead(yield, cmd_addr, &command,
sizeof(command));
375 DPRINTF(ITS,
"Command %s read from queue at address: %#x\n",
377 DPRINTF(ITS,
"dw0: %#x dw1: %#x dw2: %#x dw3: %#x\n",
378 command.
raw[0], command.
raw[1], command.
raw[2], command.
raw[3]);
388 entry->second.exec(
this, yield, command);
390 panic(
"Unrecognized command type: %u", command.
type);
398 its.incrementReadPointer();
405 its.incrementReadPointer();
410 yield, dte.ittAddress, command.
eventId);
413 its.incrementReadPointer();
417 const auto collection_id = itte.icid;
421 its.incrementReadPointer();
426 its.getRedistributor(cte)->setClrLPI(itte.intNum,
false);
433 its.incrementReadPointer();
440 its.incrementReadPointer();
445 yield, dte.ittAddress, command.
eventId);
448 its.incrementReadPointer();
452 const auto collection_id = itte.icid;
456 its.incrementReadPointer();
460 its.getRedistributor(cte)->setClrLPI(itte.intNum,
false);
465 yield, dte.ittAddress, command.
eventId, itte);
472 its.incrementReadPointer();
479 its.incrementReadPointer();
484 yield, dte.ittAddress, command.
eventId);
487 its.incrementReadPointer();
491 const auto collection_id = itte.icid;
495 its.incrementReadPointer();
500 its.getRedistributor(cte)->setClrLPI(itte.intNum,
true);
507 its.incrementReadPointer();
514 its.incrementReadPointer();
519 yield, dte.ittAddress, command.
eventId);
522 its.incrementReadPointer();
526 const auto collection_id = itte.icid;
530 its.incrementReadPointer();
541 its.incrementReadPointer();
545 const auto icid =
bits(command.
raw[2], 15, 0);
550 its.incrementReadPointer();
561 its.incrementReadPointer();
566 cte.valid =
bits(command.
raw[2], 63);
567 cte.rdBase =
bits(command.
raw[2], 50, 16);
569 const auto icid =
bits(command.
raw[2], 15, 0);
578 its.incrementReadPointer();
583 dte.valid =
bits(command.
raw[2], 63);
584 dte.ittAddress =
mbits(command.
raw[2], 51, 8);
585 dte.ittRange =
bits(command.
raw[1], 4, 0);
594 its.incrementReadPointer();
599 its.incrementReadPointer();
608 its.incrementReadPointer();
613 yield, dte.ittAddress, command.
eventId);
616 itte.intType = Gicv3Its::PHYSICAL_INTERRUPT;
618 itte.icid =
bits(command.
raw[2], 15, 0);
621 yield, dte.ittAddress, command.
eventId, itte);
628 its.incrementReadPointer();
633 its.incrementReadPointer();
639 const auto pintid =
bits(command.
raw[1], 63, 32);
642 its.lpiOutOfRange(pintid)) {
644 its.incrementReadPointer();
649 yield, dte.ittAddress, command.
eventId);
652 itte.intType = Gicv3Its::PHYSICAL_INTERRUPT;
653 itte.intNum = pintid;
654 itte.icid =
bits(command.
raw[2], 15, 0);
657 yield, dte.ittAddress, command.
eventId, itte);
663 const uint64_t rd1 =
bits(command.
raw[2], 50, 16);
664 const uint64_t rd2 =
bits(command.
raw[3], 50, 16);
670 its.moveAllPendingState(redist1, redist2);
678 its.incrementReadPointer();
683 its.incrementReadPointer();
690 its.incrementReadPointer();
695 yield, dte.ittAddress, command.
eventId);
697 if (!itte.valid || itte.intType == Gicv3Its::VIRTUAL_INTERRUPT) {
698 its.incrementReadPointer();
702 const auto collection_id1 = itte.icid;
706 its.incrementReadPointer();
710 const auto collection_id2 =
bits(command.
raw[2], 15, 0);
714 its.incrementReadPointer();
721 if (second_redist != first_redist) {
725 first_redist->
setClrLPI(itte.intNum,
false);
726 second_redist->
setClrLPI(itte.intNum,
true);
730 itte.icid = collection_id2;
732 yield, dte.ittAddress, command.
eventId, itte);
738 warn(
"ITS %s command unimplemented", __func__);
744 panic(
"ITS %s command unimplemented", __func__);
750 panic(
"ITS %s command unimplemented", __func__);
756 panic(
"ITS %s command unimplemented", __func__);
762 panic(
"ITS %s command unimplemented", __func__);
768 panic(
"ITS %s command unimplemented", __func__);
774 panic(
"ITS %s command unimplemented", __func__);
780 panic(
"ITS %s command unimplemented", __func__);
794 pendingCommands(
false),
795 pendingTranslations(0)
797 BASER device_baser = 0;
798 device_baser.type = DEVICE_TABLE;
799 device_baser.entrySize =
sizeof(uint64_t) - 1;
800 tableBases[0] = device_baser;
802 BASER icollect_baser = 0;
803 icollect_baser.type = COLLECTION_TABLE;
804 icollect_baser.entrySize =
sizeof(uint64_t) - 1;
805 tableBases[1] = icollect_baser;
831 DPRINTF(GIC,
"%s register at addr: %#x\n", __func__,
addr);
875 value =
gic->getDistributor()->gicdPidr2;
885 auto baser_index = relative_addr /
sizeof(uint64_t);
890 panic(
"Unrecognized register access\n");
894 pkt->
setUintX(value, ByteOrder::little);
904 DPRINTF(GIC,
"%s register at addr: %#x\n", __func__,
addr);
908 assert(pkt->
getSize() ==
sizeof(uint32_t));
917 panic(
"GITS_IIDR is Read Only\n");
920 panic(
"GITS_TYPER is Read Only\n");
923 if (pkt->
getSize() ==
sizeof(uint32_t)) {
926 assert(pkt->
getSize() ==
sizeof(uint64_t));
936 assert(pkt->
getSize() ==
sizeof(uint32_t));
945 if (pkt->
getSize() ==
sizeof(uint32_t)) {
948 assert(pkt->
getSize() ==
sizeof(uint64_t));
956 assert(pkt->
getSize() ==
sizeof(uint32_t));
963 panic(
"GITS_READR is Read Only\n");
966 if (gitsControl.enabled) {
974 auto baser_index = relative_addr /
sizeof(uint64_t);
976 const uint64_t table_base =
tableBases[baser_index];
977 const uint64_t w_mask =
tableBases[baser_index].type ?
979 const uint64_t
val = pkt->
getLE<uint64_t>() & w_mask;
984 panic(
"Unrecognized register access\n");
995 const uint32_t id_bits =
gitsTyper.idBits;
996 return event_id >= (1ULL << (id_bits + 1)) ||
997 event_id >= ((1ULL << itt_range) + 1);
1003 return device_id >= (1ULL << (
gitsTyper.devBits + 1));
1017 const auto cid_bits =
gitsTyper.cil == 0 ?
1020 return collection_id >= (1ULL << cid_bits);
1037 DPRINTF(Drain,
"GICv3 ITS not drained\n");
1089 if (!gitsControl.enabled || !
gitsCbaser.valid)
1102 DPRINTF(ITS,
"Reading command from queue\n");
1109 DPRINTF(ITS,
"Waiting for pending command to finish\n");
1117 if (if_name ==
"dma") {
1157 if (
sys->isAtomicMode()) {
1159 }
else if (
sys->isTimingMode()) {
1162 panic(
"Not in timing or atomic mode\n");
1171 switch (action.
type) {
1191 panic(
"Unknown action\n");
1202 bool terminate =
false;
1205 action = proc->
run(pkt);
1207 switch (action.
type) {
1219 panic(
"Unknown action\n");
1222 }
while (!terminate);
1224 action.
delay = delay;
1232 DPRINTF(ITS,
"Starting Translation Request\n");
1243 return gic->getRedistributorByAddr(rd_base << 16);
1246 return gic->getRedistributor(rd_base);
1253 auto base_it = std::find_if(
1255 [table] (
const BASER &
b) { return b.type == table; }
1259 "ITS Table not recognised\n");
1261 const BASER
base = *base_it;
1264 switch (
base.pageSize) {
1271 panic(
"Unsupported page size\n");
1279 const uint64_t largest_lpi_id = 1ULL << (rd1->
lpiIDBits + 1);
1280 const uint64_t table_size = largest_lpi_id / 8;
1281 auto lpi_pending_table = std::make_unique<uint8_t[]>(table_size);
Addr pioAddr
Address that the device listens to.
BasicPioDevice(const Params &p, Addr size)
Tick pioDelay
Delay that the device experinces on an access.
Addr pioSize
Size that the device's address range.
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
static const uint32_t IDBITS
static const uint32_t CTLR_QUIESCENT
friend class gem5::ItsTranslation
void moveAllPendingState(Gicv3Redistributor *rd1, Gicv3Redistributor *rd2)
bool lpiOutOfRange(uint32_t intid) const
Returns TRUE if the value supplied is larger than that permitted by GICD_TYPER.IDbits or not in the L...
Port & getPort(const std::string &if_name, PortID idx) override
Get a port with a given name and index.
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
bool deviceOutOfRange(uint32_t device_id) const
Returns TRUE if the value supplied has bits above the implemented range or if the value supplied exce...
static const uint64_t BASER_WMASK_UNIMPL
static const uint32_t NUM_BASER_REGS
bool collectionOutOfRange(uint32_t collection_id) const
Returns TRUE if the value supplied has bits above the implemented range or if the value exceeds the t...
void translate(PacketPtr pkt)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
EventFunctionWrapper commandEvent
Gicv3Redistributor * getRedistributor(uint64_t rd_base)
std::vector< BASER > tableBases
bool idOutOfRange(uint32_t event_id, uint8_t itt_range) const
Returns TRUE if the eventID supplied has bits above the implemented size or above the itt_range.
ItsAction runProcessTiming(ItsProcess *proc, PacketPtr pkt)
AddrRangeList getAddrRanges() const override
Determine the address ranges that this device responds to.
ItsAction runProcess(ItsProcess *proc, PacketPtr pkt)
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
void serialize(CheckpointOut &cp) const override
Serialize an object.
Gicv3Its(const Gicv3ItsParams ¶ms)
ItsAction runProcessAtomic(ItsProcess *proc, PacketPtr pkt)
friend class gem5::ItsCommand
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
Addr pageAddress(enum ItsTables table)
bool sizeOutOfRange(uint32_t size) const
Returns TRUE if the value (size) supplied exceeds the maximum allowed by GITS_TYPER....
friend class gem5::ItsProcess
uint64_t maxCommands() const
static const uint64_t BASER_WMASK
static const AddrRange GITS_BASER
bool recvTimingResp(PacketPtr pkt)
std::queue< ItsAction > packetsToRetry
void incrementReadPointer()
uint32_t pendingTranslations
bool isPendingLPI(uint32_t intid)
static const uint32_t SMALLEST_LPI_ID
void setClrLPI(uint64_t data, bool set)
static const int INTID_SPURIOUS
void movall(Yield &yield, CommandEntry &command)
bool sizeOutOfRange(CommandEntry &command) const
void doInt(Yield &yield, CommandEntry &command)
bool idOutOfRange(CommandEntry &command, DTE dte) const
void main(Yield &yield) override
ItsCommand(Gicv3Its &_its)
void sync(Yield &yield, CommandEntry &command)
void vsync(Yield &yield, CommandEntry &command)
void invall(Yield &yield, CommandEntry &command)
void vmapp(Yield &yield, CommandEntry &command)
void readCommand(Yield &yield, CommandEntry &command)
void mapd(Yield &yield, CommandEntry &command)
void discard(Yield &yield, CommandEntry &command)
void processCommand(Yield &yield, CommandEntry &command)
void vmovp(Yield &yield, CommandEntry &command)
void vmovi(Yield &yield, CommandEntry &command)
void vmapti(Yield &yield, CommandEntry &command)
void clear(Yield &yield, CommandEntry &command)
void movi(Yield &yield, CommandEntry &command)
void mapc(Yield &yield, CommandEntry &command)
void vinvall(Yield &yield, CommandEntry &command)
void inv(Yield &yield, CommandEntry &command)
void vmapi(Yield &yield, CommandEntry &command)
static std::string commandName(uint32_t cmd)
bool deviceOutOfRange(CommandEntry &command) const
static DispatchTable cmdDispatcher
std::unordered_map< std::underlying_type< enum CommandType >::type, DispatchEntry > DispatchTable
bool collectionOutOfRange(CommandEntry &command) const
void mapi(Yield &yield, CommandEntry &command)
void mapti(Yield &yield, CommandEntry &command)
void writeIrqTranslationTable(Yield &yield, const Addr itt_base, uint32_t event_id, ITTE itte)
uint64_t readIrqCollectionTable(Yield &yield, uint32_t collection_id)
const std::string name() const
Returns the Gicv3Its name.
void terminate(Yield &yield)
Coroutine::CallerType Yield
ItsAction run(PacketPtr pkt)
void writeDeviceTable(Yield &yield, uint32_t device_id, DTE dte)
void doWrite(Yield &yield, Addr addr, void *ptr, size_t size)
ItsProcess(Gicv3Its &_its)
std::unique_ptr< Coroutine > coroutine
void doRead(Yield &yield, Addr addr, void *ptr, size_t size)
gem5::Coroutine< PacketPtr, ItsAction > Coroutine
uint64_t readIrqTranslationTable(Yield &yield, const Addr itt_base, uint32_t event_id)
virtual void main(Yield &yield)=0
uint64_t readDeviceTable(Yield &yield, uint32_t device_id)
void writeIrqCollectionTable(Yield &yield, uint32_t collection_id, CTE cte)
void main(Yield &yield) override
ItsTranslation(Gicv3Its &_its)
std::pair< uint32_t, Gicv3Redistributor * > translateLPI(Yield &yield, uint32_t device_id, uint32_t event_id)
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
void setUintX(uint64_t w, ByteOrder endian)
Set the value in the word w after truncating it to the length of the packet and then byteswapping it ...
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
void pushSenderState(SenderState *sender_state)
Push a new sender state to the packet and make the current sender state the predecessor of the new on...
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
RequestPtr req
A pointer to the original request.
void makeAtomicResponse()
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
void readBlob(Addr addr, void *p, uint64_t size) const
Higher level interfaces based on the above.
void writeBlob(Addr addr, const void *p, uint64_t size) const
Same as tryWriteBlob, but insists on success.
void memsetBlob(Addr addr, uint8_t v, uint64_t size) const
Same as tryMemsetBlob, but insists on success.
Ports are used to interface objects to each other.
#define COMMAND(x, method)
AddrRange RangeSize(Addr start, Addr size)
std::list< AddrRange > AddrRangeList
Convenience typedef for a collection of address ranges.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
constexpr T mbits(T val, unsigned first, unsigned last)
Mask off the given bits in place like bits() but without shifting.
DrainState
Object drain/handover states.
@ Draining
Draining buffers pending serialization/handover.
@ Drained
Buffers drained, ready for serialization/handover.
void schedule(Event &event, Tick when)
#define panic(...)
This implements a cprintf based panic() function.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
#define UNSERIALIZE_CONTAINER(member)
#define SERIALIZE_CONTAINER(member)
const Params & params() const
Copyright (c) 2024 Arm Limited All rights reserved.
T safe_cast(U &&ref_or_ptr)
std::shared_ptr< Request > RequestPtr
std::ostream CheckpointOut
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
uint64_t Tick
Tick count type.
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
const std::string & name()