45#include "debug/AddrRanges.hh"
46#include "debug/Drain.hh"
47#include "debug/GIC.hh"
48#include "debug/ITS.hh"
54#define COMMAND(x, method) { x, DispatchEntry(#x, method) }
100 addr, size, 0,
its.requestorId);
105 a.pkt->dataStatic(ptr);
112 assert(pkt->
getSize() >= size);
124 addr, size, 0,
its.requestorId);
129 a.pkt->dataStatic(ptr);
136 assert(pkt->
getSize() >= size);
155 const Addr address =
base + (device_id *
sizeof(dte));
157 DPRINTF(ITS,
"Writing DTE at address %#x: %#x\n", address, dte);
159 doWrite(yield, address, &dte,
sizeof(dte));
164 Yield &yield,
const Addr itt_base, uint32_t event_id,
ITTE itte)
166 const Addr address = itt_base + (event_id *
sizeof(itte));
168 doWrite(yield, address, &itte,
sizeof(itte));
170 DPRINTF(ITS,
"Writing ITTE at address %#x: %#x\n", address, itte);
175 Yield &yield, uint32_t collection_id,
CTE cte)
178 const Addr address =
base + (collection_id *
sizeof(cte));
180 doWrite(yield, address, &cte,
sizeof(cte));
182 DPRINTF(ITS,
"Writing CTE at address %#x: %#x\n", address, cte);
190 const Addr address =
base + (device_id *
sizeof(dte));
192 doRead(yield, address, &dte,
sizeof(dte));
194 DPRINTF(ITS,
"Reading DTE at address %#x: %#x\n", address, dte);
200 Yield &yield,
const Addr itt_base, uint32_t event_id)
203 const Addr address = itt_base + (event_id *
sizeof(itte));
205 doRead(yield, address, &itte,
sizeof(itte));
207 DPRINTF(ITS,
"Reading ITTE at address %#x: %#x\n", address, itte);
216 const Addr address =
base + (collection_id *
sizeof(cte));
218 doRead(yield, address, &cte,
sizeof(cte));
220 DPRINTF(ITS,
"Reading CTE at address %#x: %#x\n", address, cte);
228 its.pendingTranslations++;
229 its.gitsControl.quiescent = 0;
234 assert(
its.pendingTranslations >= 1);
235 its.pendingTranslations--;
236 if (!
its.pendingTranslations && !
its.pendingCommands)
237 its.gitsControl.quiescent = 1;
245 const uint32_t device_id = pkt->
req->streamId();
246 const uint32_t event_id = pkt->
getLE<uint32_t>();
250 uint32_t intid = result.first;
259 its.gitsTranslater = event_id;
268 if (
its.deviceOutOfRange(device_id)) {
274 if (!dte.valid ||
its.idOutOfRange(event_id, dte.ittRange)) {
279 const auto collection_id = itte.icid;
281 if (!itte.valid ||
its.collectionOutOfRange(collection_id)) {
292 return std::make_pair(itte.intNum,
its.getRedistributor(cte));
322 its.pendingCommands =
true;
324 its.gitsControl.quiescent = 0;
329 its.pendingCommands =
false;
331 if (!
its.pendingTranslations)
332 its.gitsControl.quiescent = 1;
339 return entry !=
cmdDispatcher.end() ? entry->second.name :
"INVALID";
351 while (
its.gitsCwriter.offset !=
its.gitsCreadr.offset) {
359 its.incrementReadPointer();
369 const Addr cmd_addr =
370 (
its.gitsCbaser.physAddr << 12) + (
its.gitsCreadr.offset << 5);
372 doRead(yield, cmd_addr, &command,
sizeof(command));
374 DPRINTF(ITS,
"Command %s read from queue at address: %#x\n",
376 DPRINTF(ITS,
"dw0: %#x dw1: %#x dw2: %#x dw3: %#x\n",
377 command.
raw[0], command.
raw[1], command.
raw[2], command.
raw[3]);
387 entry->second.exec(
this, yield, command);
389 panic(
"Unrecognized command type: %u", command.
type);
397 its.incrementReadPointer();
404 its.incrementReadPointer();
409 yield, dte.ittAddress, command.
eventId);
412 its.incrementReadPointer();
416 const auto collection_id = itte.icid;
420 its.incrementReadPointer();
425 its.getRedistributor(cte)->setClrLPI(itte.intNum,
false);
432 its.incrementReadPointer();
439 its.incrementReadPointer();
444 yield, dte.ittAddress, command.
eventId);
447 its.incrementReadPointer();
451 const auto collection_id = itte.icid;
455 its.incrementReadPointer();
459 its.getRedistributor(cte)->setClrLPI(itte.intNum,
false);
464 yield, dte.ittAddress, command.
eventId, itte);
471 its.incrementReadPointer();
478 its.incrementReadPointer();
483 yield, dte.ittAddress, command.
eventId);
486 its.incrementReadPointer();
490 const auto collection_id = itte.icid;
494 its.incrementReadPointer();
499 its.getRedistributor(cte)->setClrLPI(itte.intNum,
true);
506 its.incrementReadPointer();
513 its.incrementReadPointer();
518 yield, dte.ittAddress, command.
eventId);
521 its.incrementReadPointer();
525 const auto collection_id = itte.icid;
529 its.incrementReadPointer();
540 its.incrementReadPointer();
544 const auto icid =
bits(command.
raw[2], 15, 0);
549 its.incrementReadPointer();
560 its.incrementReadPointer();
565 cte.valid =
bits(command.
raw[2], 63);
566 cte.rdBase =
bits(command.
raw[2], 50, 16);
568 const auto icid =
bits(command.
raw[2], 15, 0);
577 its.incrementReadPointer();
582 dte.valid =
bits(command.
raw[2], 63);
583 dte.ittAddress =
mbits(command.
raw[2], 51, 8);
584 dte.ittRange =
bits(command.
raw[1], 4, 0);
593 its.incrementReadPointer();
598 its.incrementReadPointer();
607 its.incrementReadPointer();
612 yield, dte.ittAddress, command.
eventId);
615 itte.intType = Gicv3Its::PHYSICAL_INTERRUPT;
617 itte.icid =
bits(command.
raw[2], 15, 0);
620 yield, dte.ittAddress, command.
eventId, itte);
627 its.incrementReadPointer();
632 its.incrementReadPointer();
638 const auto pintid =
bits(command.
raw[1], 63, 32);
641 its.lpiOutOfRange(pintid)) {
643 its.incrementReadPointer();
648 yield, dte.ittAddress, command.
eventId);
651 itte.intType = Gicv3Its::PHYSICAL_INTERRUPT;
652 itte.intNum = pintid;
653 itte.icid =
bits(command.
raw[2], 15, 0);
656 yield, dte.ittAddress, command.
eventId, itte);
662 const uint64_t rd1 =
bits(command.
raw[2], 50, 16);
663 const uint64_t rd2 =
bits(command.
raw[3], 50, 16);
669 its.moveAllPendingState(redist1, redist2);
677 its.incrementReadPointer();
682 its.incrementReadPointer();
689 its.incrementReadPointer();
694 yield, dte.ittAddress, command.
eventId);
696 if (!itte.valid || itte.intType == Gicv3Its::VIRTUAL_INTERRUPT) {
697 its.incrementReadPointer();
701 const auto collection_id1 = itte.icid;
705 its.incrementReadPointer();
709 const auto collection_id2 =
bits(command.
raw[2], 15, 0);
713 its.incrementReadPointer();
720 if (second_redist != first_redist) {
724 first_redist->
setClrLPI(itte.intNum,
false);
725 second_redist->
setClrLPI(itte.intNum,
true);
729 itte.icid = collection_id2;
731 yield, dte.ittAddress, command.
eventId, itte);
737 warn(
"ITS %s command unimplemented", __func__);
743 panic(
"ITS %s command unimplemented", __func__);
749 panic(
"ITS %s command unimplemented", __func__);
755 panic(
"ITS %s command unimplemented", __func__);
761 panic(
"ITS %s command unimplemented", __func__);
767 panic(
"ITS %s command unimplemented", __func__);
773 panic(
"ITS %s command unimplemented", __func__);
779 panic(
"ITS %s command unimplemented", __func__);
793 pendingCommands(
false),
794 pendingTranslations(0)
796 BASER device_baser = 0;
797 device_baser.type = DEVICE_TABLE;
798 device_baser.entrySize =
sizeof(uint64_t) - 1;
799 tableBases[0] = device_baser;
801 BASER icollect_baser = 0;
802 icollect_baser.type = COLLECTION_TABLE;
803 icollect_baser.entrySize =
sizeof(uint64_t) - 1;
804 tableBases[1] = icollect_baser;
830 DPRINTF(GIC,
"%s register at addr: %#x\n", __func__,
addr);
874 value =
gic->getDistributor()->gicdPidr2;
884 auto baser_index = relative_addr /
sizeof(uint64_t);
889 panic(
"Unrecognized register access\n");
893 pkt->
setUintX(value, ByteOrder::little);
903 DPRINTF(GIC,
"%s register at addr: %#x\n", __func__,
addr);
907 assert(pkt->
getSize() ==
sizeof(uint32_t));
916 panic(
"GITS_IIDR is Read Only\n");
919 panic(
"GITS_TYPER is Read Only\n");
922 if (pkt->
getSize() ==
sizeof(uint32_t)) {
925 assert(pkt->
getSize() ==
sizeof(uint64_t));
935 assert(pkt->
getSize() ==
sizeof(uint32_t));
944 if (pkt->
getSize() ==
sizeof(uint32_t)) {
947 assert(pkt->
getSize() ==
sizeof(uint64_t));
955 assert(pkt->
getSize() ==
sizeof(uint32_t));
962 panic(
"GITS_READR is Read Only\n");
965 if (gitsControl.enabled) {
973 auto baser_index = relative_addr /
sizeof(uint64_t);
975 const uint64_t table_base =
tableBases[baser_index];
976 const uint64_t w_mask =
tableBases[baser_index].type ?
978 const uint64_t
val = pkt->
getLE<uint64_t>() & w_mask;
983 panic(
"Unrecognized register access\n");
994 const uint32_t id_bits =
gitsTyper.idBits;
995 return event_id >= (1ULL << (id_bits + 1)) ||
996 event_id >= ((1ULL << itt_range) + 1);
1002 return device_id >= (1ULL << (
gitsTyper.devBits + 1));
1016 const auto cid_bits =
gitsTyper.cil == 0 ?
1019 return collection_id >= (1ULL << cid_bits);
1036 DPRINTF(Drain,
"GICv3 ITS not drained\n");
1088 if (!gitsControl.enabled || !
gitsCbaser.valid)
1101 DPRINTF(ITS,
"Reading command from queue\n");
1108 DPRINTF(ITS,
"Waiting for pending command to finish\n");
1116 if (if_name ==
"dma") {
1156 if (
sys->isAtomicMode()) {
1158 }
else if (
sys->isTimingMode()) {
1161 panic(
"Not in timing or atomic mode\n");
1170 switch (action.
type) {
1190 panic(
"Unknown action\n");
1201 bool terminate =
false;
1204 action = proc->
run(pkt);
1206 switch (action.
type) {
1218 panic(
"Unknown action\n");
1221 }
while (!terminate);
1223 action.
delay = delay;
1231 DPRINTF(ITS,
"Starting Translation Request\n");
1242 return gic->getRedistributorByAddr(rd_base << 16);
1245 return gic->getRedistributor(rd_base);
1252 auto base_it = std::find_if(
1254 [table] (
const BASER &
b) { return b.type == table; }
1258 "ITS Table not recognised\n");
1260 const BASER
base = *base_it;
1263 switch (
base.pageSize) {
1270 panic(
"Unsupported page size\n");
1278 const uint64_t largest_lpi_id = 1ULL << (rd1->
lpiIDBits + 1);
1279 const uint64_t table_size = largest_lpi_id / 8;
1280 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()