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) }
64 : its(_its), coroutine(nullptr)
105 a.pkt->dataStatic(ptr);
112 assert(pkt->
getSize() >= size);
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);
229 its.gitsControl.quiescent = 0;
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;
279 const auto collection_id = itte.icid;
324 its.gitsControl.quiescent = 0;
332 its.gitsControl.quiescent = 1;
339 return entry !=
cmdDispatcher.end() ? entry->second.name :
"INVALID";
369 const Addr cmd_addr =
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);
409 yield, dte.ittAddress, command.
eventId);
416 const auto collection_id = itte.icid;
444 yield, dte.ittAddress, command.
eventId);
451 const auto collection_id = itte.icid;
464 yield, dte.ittAddress, command.
eventId, itte);
483 yield, dte.ittAddress, command.
eventId);
490 const auto collection_id = itte.icid;
518 yield, dte.ittAddress, command.
eventId);
525 const auto collection_id = itte.icid;
544 const auto icid =
bits(command.
raw[2], 15, 0);
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);
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);
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);
638 const auto pintid =
bits(command.
raw[1], 63, 32);
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);
694 yield, dte.ittAddress, command.
eventId);
696 if (!itte.valid || itte.intType == Gicv3Its::VIRTUAL_INTERRUPT) {
701 const auto collection_id1 = itte.icid;
709 const auto collection_id2 =
bits(command.
raw[2], 15, 0);
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__);
784 dmaPort(
name() +
".dma", *this),
785 gitsControl(CTLR_QUIESCENT),
786 gitsTyper(params.gits_typer),
787 gitsCbaser(0), gitsCreadr(0),
788 gitsCwriter(0), gitsIidr(0),
789 tableBases(NUM_BASER_REGS, 0),
790 requestorId(params.
system->getRequestorId(this)),
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);
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") {
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");
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 uint8_t lpi_pending_table[largest_lpi_id / 8];
1284 sizeof(lpi_pending_table));
1288 sizeof(lpi_pending_table));
1293 0,
sizeof(lpi_pending_table));
Addr pioAddr
Address that the device listens to.
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...
CallerType: A reference to an object of this class will be passed to the coroutine task.
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
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....
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)
Gicv3Redistributor * getRedistributor(ContextID context_id) const
Gicv3Distributor * getDistributor() const
static const int INTID_SPURIOUS
Gicv3Redistributor * getRedistributorByAddr(Addr address) const
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)
ItsProcess is a base coroutine wrapper which is spawned by the Gicv3Its module when the latter needs ...
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)
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)
virtual std::string name() const
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.
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time,...
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
bool isAtomicMode() const
Is the system in atomic mode?
bool isTimingMode() const
Is the system in timing mode?
#define COMMAND(x, method)
AddrRange RangeSize(Addr start, Addr size)
bool contains(const Addr &a) const
Determine if the range contains an address.
Addr start() const
Get the start address of the range.
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.
std::enable_if_t<!std::is_same_v< T, void >, T > get()
get() is the way we can extrapolate arguments from the coroutine caller.
DrainState
Object drain/handover states.
@ Draining
Draining buffers pending serialization/handover.
@ Drained
Buffers drained, ready for serialization/handover.
bool scheduled() const
Determine if the current event is scheduled.
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)
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria 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()