42 #include "debug/AddrRanges.hh" 43 #include "debug/Drain.hh" 44 #include "debug/GIC.hh" 45 #include "debug/ITS.hh" 51 #define COMMAND(x, method) { x, DispatchEntry(#x, method) } 58 : its(_its), coroutine(nullptr)
149 const Addr address = base + (device_id *
sizeof(dte));
151 DPRINTF(ITS,
"Writing DTE at address %#x: %#x\n", address, dte);
153 doWrite(yield, address, &dte,
sizeof(dte));
158 Yield &yield,
const Addr itt_base, uint32_t event_id,
ITTE itte)
160 const Addr address = itt_base + (event_id *
sizeof(itte));
162 doWrite(yield, address, &itte,
sizeof(itte));
164 DPRINTF(ITS,
"Writing ITTE at address %#x: %#x\n", address, itte);
169 Yield &yield, uint32_t collection_id,
CTE cte)
172 const Addr address = base + (collection_id *
sizeof(cte));
174 doWrite(yield, address, &cte,
sizeof(cte));
176 DPRINTF(ITS,
"Writing CTE at address %#x: %#x\n", address, cte);
184 const Addr address = base + (device_id *
sizeof(dte));
186 doRead(yield, address, &dte,
sizeof(dte));
188 DPRINTF(ITS,
"Reading DTE at address %#x: %#x\n", address, dte);
194 Yield &yield,
const Addr itt_base, uint32_t event_id)
197 const Addr address = itt_base + (event_id *
sizeof(itte));
199 doRead(yield, address, &itte,
sizeof(itte));
201 DPRINTF(ITS,
"Reading ITTE at address %#x: %#x\n", address, itte);
210 const Addr address = base + (collection_id *
sizeof(cte));
212 doRead(yield, address, &cte,
sizeof(cte));
214 DPRINTF(ITS,
"Reading CTE at address %#x: %#x\n", address, cte);
223 its.gitsControl.quiescent = 0;
231 its.gitsControl.quiescent = 1;
239 const uint32_t device_id = pkt->
req->streamId();
240 const uint32_t event_id = pkt->
getLE<uint32_t>();
244 uint32_t intid = result.first;
273 const auto collection_id = itte.icid;
318 its.gitsControl.quiescent = 0;
326 its.gitsControl.quiescent = 1;
333 return entry !=
cmdDispatcher.end() ? entry->second.name :
"INVALID";
363 const Addr cmd_addr =
366 doRead(yield, cmd_addr, &command,
sizeof(command));
368 DPRINTF(ITS,
"Command %s read from queue at address: %#x\n",
370 DPRINTF(ITS,
"dw0: %#x dw1: %#x dw2: %#x dw3: %#x\n",
371 command.
raw[0], command.
raw[1], command.
raw[2], command.
raw[3]);
381 entry->second.exec(
this, yield, command);
383 panic(
"Unrecognized command type: %u", command.
type);
403 yield, dte.ittAddress, command.
eventId);
410 const auto collection_id = itte.icid;
438 yield, dte.ittAddress, command.
eventId);
445 const auto collection_id = itte.icid;
458 yield, dte.ittAddress, command.
eventId, itte);
477 yield, dte.ittAddress, command.
eventId);
484 const auto collection_id = itte.icid;
512 yield, dte.ittAddress, command.
eventId);
519 const auto collection_id = itte.icid;
559 cte.valid =
bits(command.
raw[2], 63);
560 cte.rdBase =
bits(command.
raw[2], 50, 16);
576 dte.valid =
bits(command.
raw[2], 63);
577 dte.ittAddress =
mbits(command.
raw[2], 51, 8);
578 dte.ittRange =
bits(command.
raw[1], 4, 0);
606 yield, dte.ittAddress, command.
eventId);
609 itte.intType = Gicv3Its::PHYSICAL_INTERRUPT;
611 itte.icid =
bits(command.
raw[2], 15, 0);
614 yield, dte.ittAddress, command.
eventId, itte);
632 const auto pintid =
bits(command.
raw[1], 63, 32);
642 yield, dte.ittAddress, command.
eventId);
645 itte.intType = Gicv3Its::PHYSICAL_INTERRUPT;
646 itte.intNum = pintid;
647 itte.icid =
bits(command.
raw[2], 15, 0);
650 yield, dte.ittAddress, command.
eventId, itte);
656 const uint64_t rd1 =
bits(command.
raw[2], 50, 16);
657 const uint64_t rd2 =
bits(command.
raw[3], 50, 16);
688 yield, dte.ittAddress, command.
eventId);
690 if (!itte.valid || itte.intType == Gicv3Its::VIRTUAL_INTERRUPT) {
695 const auto collection_id1 = itte.icid;
703 const auto collection_id2 =
bits(command.
raw[2], 15, 0);
714 if (second_redist != first_redist) {
718 first_redist->
setClrLPI(itte.intNum,
false);
719 second_redist->
setClrLPI(itte.intNum,
true);
723 itte.icid = collection_id2;
725 yield, dte.ittAddress, command.
eventId, itte);
731 warn(
"ITS %s command unimplemented", __func__);
737 panic(
"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__);
790 BASER device_baser = 0;
792 device_baser.entrySize =
sizeof(uint64_t) - 1;
795 BASER icollect_baser = 0;
797 icollect_baser.entrySize =
sizeof(uint64_t) - 1;
824 DPRINTF(GIC,
"%s register at addr: %#x\n", __func__, addr);
878 auto baser_index = relative_addr /
sizeof(uint64_t);
883 panic(
"Unrecognized register access\n");
897 DPRINTF(GIC,
"%s register at addr: %#x\n", __func__, addr);
901 assert(pkt->
getSize() ==
sizeof(uint32_t));
910 panic(
"GITS_IIDR is Read Only\n");
913 panic(
"GITS_TYPER is Read Only\n");
916 if (pkt->
getSize() ==
sizeof(uint32_t)) {
919 assert(pkt->
getSize() ==
sizeof(uint64_t));
929 assert(pkt->
getSize() ==
sizeof(uint32_t));
938 if (pkt->
getSize() ==
sizeof(uint32_t)) {
941 assert(pkt->
getSize() ==
sizeof(uint64_t));
949 assert(pkt->
getSize() ==
sizeof(uint32_t));
956 panic(
"GITS_READR is Read Only\n");
959 if (gitsControl.enabled) {
967 auto baser_index = relative_addr /
sizeof(uint64_t);
969 const uint64_t table_base =
tableBases[baser_index];
970 const uint64_t w_mask =
tableBases[baser_index].type ?
972 const uint64_t
val = pkt->
getLE<uint64_t>() & w_mask;
977 panic(
"Unrecognized register access\n");
988 const uint32_t id_bits =
gitsTyper.idBits;
989 return event_id >= (1
ULL << (id_bits + 1)) ||
990 event_id >= ((1
ULL << itt_range) + 1);
1010 const auto cid_bits =
gitsTyper.cil == 0 ?
1013 return collection_id >= (1
ULL << cid_bits);
1030 DPRINTF(Drain,
"GICv3 ITS not drained\n");
1082 if (!gitsControl.enabled || !
gitsCbaser.valid)
1095 DPRINTF(ITS,
"Reading command from queue\n");
1102 DPRINTF(ITS,
"Waiting for pending command to finish\n");
1110 if (if_name ==
"dma") {
1155 panic(
"Not in timing or atomic mode\n");
1164 switch (action.
type) {
1184 panic(
"Unknown action\n");
1195 bool terminate =
false;
1198 action = proc->
run(pkt);
1200 switch (action.
type) {
1212 panic(
"Unknown action\n");
1215 }
while (!terminate);
1217 action.
delay = delay;
1225 DPRINTF(ITS,
"Starting Translation Request\n");
1246 auto base_it = std::find_if(
1248 [table] (
const BASER &
b) {
return b.type == table; }
1252 "ITS Table not recognised\n");
1254 const BASER
base = *base_it;
1257 switch (base.pageSize) {
1260 return mbits(base, 47, 12);
1262 return mbits(base, 47, 16) | (
bits(base, 15, 12) << 48);
1264 panic(
"Unsupported page size\n");
1272 const uint64_t largest_lpi_id = 1
ULL << (rd1->
lpiIDBits + 1);
1273 uint8_t lpi_pending_table[largest_lpi_id / 8];
1278 sizeof(lpi_pending_table));
1282 sizeof(lpi_pending_table));
1287 0,
sizeof(lpi_pending_table));
1293 Gicv3ItsParams::create()
#define panic(...)
This implements a cprintf based panic() function.
AddrRange RangeSize(Addr start, Addr size)
Gicv3Its(const Gicv3ItsParams *params)
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 ...
Ports are used to interface objects to each other.
void serialize(CheckpointOut &cp) const override
Serialize an object.
bool deviceOutOfRange(CommandEntry &command) const
void doInt(Yield &yield, CommandEntry &command)
ItsAction runProcessAtomic(ItsProcess *proc, PacketPtr pkt)
void terminate(Yield &yield)
void sync(Yield &yield, CommandEntry &command)
std::vector< BASER > tableBases
Port & getPort(const std::string &if_name, PortID idx) override
Get a port with a given name and index.
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...
bool isPendingLPI(uint32_t intid)
DrainState
Object drain/handover states.
static const AddrRange GITS_BASER
std::pair< uint32_t, Gicv3Redistributor * > translateLPI(Yield &yield, uint32_t device_id, uint32_t event_id)
AddrRangeList getAddrRanges() const override
Every PIO device is obliged to provide an implementation that returns the address ranges the device r...
Addr pageAddress(enum ItsTables table)
void processCommand(Yield &yield, CommandEntry &command)
uint64_t readDeviceTable(Yield &yield, uint32_t device_id)
bool contains(const Addr &a) const
Determine if the range contains an address.
std::shared_ptr< Request > RequestPtr
m5::Coroutine< PacketPtr, ItsAction > Coroutine
virtual void main(Yield &yield)=0
ItsAction runProcessTiming(ItsProcess *proc, PacketPtr pkt)
void mapi(Yield &yield, CommandEntry &command)
Gicv3Redistributor * getRedistributorByAddr(Addr address) const
EventFunctionWrapper commandEvent
uint64_t readIrqTranslationTable(Yield &yield, const Addr itt_base, uint32_t event_id)
bool sizeOutOfRange(uint32_t size) const
Returns TRUE if the value (size) supplied exceeds the maximum allowed by GITS_TYPER.ID_bits.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the slave port by calling its corresponding receive function...
void writeIrqCollectionTable(Yield &yield, uint32_t collection_id, CTE cte)
An ItsTranslation is created whenever a peripheral writes a message in GITS_TRANSLATER (MSI)...
static const uint32_t NUM_BASER_REGS
bool sizeOutOfRange(CommandEntry &command) const
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
CallerType: A reference to an object of this class will be passed to the coroutine task...
RequestPtr req
A pointer to the original request.
void moveAllPendingState(Gicv3Redistributor *rd1, Gicv3Redistributor *rd2)
void invall(Yield &yield, CommandEntry &command)
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
#define UNSERIALIZE_SCALAR(scalar)
static const uint64_t BASER_WMASK
bool recvTimingResp(PacketPtr pkt)
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...
#define SERIALIZE_CONTAINER(member)
bool isAtomicMode() const
Is the system in atomic mode?
static std::string commandName(uint32_t cmd)
static const uint64_t BASER_WMASK_UNIMPL
bool scheduled() const
Determine if the current event is scheduled.
void mapti(Yield &yield, CommandEntry &command)
Addr pioSize
Size that the device's address range.
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
uint64_t readIrqCollectionTable(Yield &yield, uint32_t collection_id)
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
void makeAtomicResponse()
std::unordered_map< std::underlying_type< enum CommandType >::type, DispatchEntry > DispatchTable
void memsetBlob(Addr addr, uint8_t v, int size) const
Same as tryMemsetBlob, but insists on success.
uint64_t Tick
Tick count type.
static const uint32_t IDBITS
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...
void setClrLPI(uint64_t data, bool set)
const Params * params() const
void clear(Yield &yield, CommandEntry &command)
ItsProcess is a base coroutine wrapper which is spawned by the Gicv3Its module when the latter needs ...
An ItsCommand is created whenever there is a new command in the command queue.
void discard(Yield &yield, CommandEntry &command)
bool collectionOutOfRange(CommandEntry &command) const
#define UNSERIALIZE_CONTAINER(member)
ItsAction runProcess(ItsProcess *proc, PacketPtr pkt)
static const int INTID_SPURIOUS
Gicv3Redistributor * getRedistributor(ContextID context_id) const
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
ItsCommand(Gicv3Its &_its)
Draining buffers pending serialization/handover.
#define ULL(N)
uint64_t constant
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
virtual const std::string name() const
void mapc(Yield &yield, CommandEntry &command)
void main(Yield &yield) override
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
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...
std::unique_ptr< Coroutine > coroutine
void mapd(Yield &yield, CommandEntry &command)
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
uint64_t maxCommands() const
void vmapi(Yield &yield, CommandEntry &command)
#define SERIALIZE_SCALAR(scalar)
void vinvall(Yield &yield, CommandEntry &command)
void incrementReadPointer()
void inv(Yield &yield, CommandEntry &command)
static const uint32_t SMALLEST_LPI_ID
std::queue< ItsAction > packetsToRetry
void vmapti(Yield &yield, CommandEntry &command)
static const uint32_t CTLR_QUIESCENT
void translate(PacketPtr pkt)
std::ostream CheckpointOut
void vmapp(Yield &yield, CommandEntry &command)
void readCommand(Yield &yield, CommandEntry &command)
void main(Yield &yield) override
#define COMMAND(x, method)
ItsProcess(Gicv3Its &_its)
Tick pioDelay
Delay that the device experinces on an access.
void writeDeviceTable(Yield &yield, uint32_t device_id, DTE dte)
void schedule(Event &event, Tick when)
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
void movi(Yield &yield, CommandEntry &command)
void movall(Yield &yield, CommandEntry &command)
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
std::enable_if<!std::is_same< T, void >::value, T >::type get()
get() is the way we can extrapolate arguments from the coroutine caller.
Gicv3Redistributor * getRedistributor(uint64_t rd_base)
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...
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
static DispatchTable cmdDispatcher
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...
Addr start() const
Get the start address of the range.
void doWrite(Yield &yield, Addr addr, void *ptr, size_t size)
const std::string name() const
Returns the Gicv3Its name.
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
void writeIrqTranslationTable(Yield &yield, const Addr itt_base, uint32_t event_id, ITTE itte)
void vmovp(Yield &yield, CommandEntry &command)
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
bool isTimingMode() const
Is the system in timing mode?
DrainState drain() override
Notify an object that it needs to drain its state.
T mbits(T val, int first, int last)
Mask off the given bits in place like bits() but without shifting.
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
ItsAction run(PacketPtr pkt)
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time...
void vmovi(Yield &yield, CommandEntry &command)
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Addr pioAddr
Address that the device listens to.
bool idOutOfRange(CommandEntry &command, DTE dte) const
uint32_t pendingTranslations
ItsTranslation(Gicv3Its &_its)
void doRead(Yield &yield, Addr addr, void *ptr, size_t size)
ProbePointArg< PacketInfo > Packet
Packet probe point.
void vsync(Yield &yield, CommandEntry &command)
Gicv3Distributor * getDistributor() const