40 #include "debug/AddrRanges.hh" 41 #include "debug/Drain.hh" 42 #include "debug/GIC.hh" 43 #include "debug/ITS.hh" 49 #define COMMAND(x, method) { x, DispatchEntry(#x, method) } 56 : its(_its), coroutine(nullptr)
147 const Addr address = base + (device_id *
sizeof(dte));
149 DPRINTF(ITS,
"Writing DTE at address %#x: %#x\n", address, dte);
151 doWrite(yield, address, &dte,
sizeof(dte));
156 Yield &yield,
const Addr itt_base, uint32_t event_id,
ITTE itte)
158 const Addr address = itt_base + (event_id *
sizeof(itte));
160 doWrite(yield, address, &itte,
sizeof(itte));
162 DPRINTF(ITS,
"Writing ITTE at address %#x: %#x\n", address, itte);
167 Yield &yield, uint32_t collection_id,
CTE cte)
170 const Addr address = base + (collection_id *
sizeof(cte));
172 doWrite(yield, address, &cte,
sizeof(cte));
174 DPRINTF(ITS,
"Writing CTE at address %#x: %#x\n", address, cte);
182 const Addr address = base + (device_id *
sizeof(dte));
184 doRead(yield, address, &dte,
sizeof(dte));
186 DPRINTF(ITS,
"Reading DTE at address %#x: %#x\n", address, dte);
192 Yield &yield,
const Addr itt_base, uint32_t event_id)
195 const Addr address = itt_base + (event_id *
sizeof(itte));
197 doRead(yield, address, &itte,
sizeof(itte));
199 DPRINTF(ITS,
"Reading ITTE at address %#x: %#x\n", address, itte);
208 const Addr address = base + (collection_id *
sizeof(cte));
210 doRead(yield, address, &cte,
sizeof(cte));
212 DPRINTF(ITS,
"Reading CTE at address %#x: %#x\n", address, cte);
221 its.gitsControl.quiescent = 0;
229 its.gitsControl.quiescent = 1;
237 const uint32_t device_id = pkt->
req->streamId();
238 const uint32_t event_id = pkt->
getLE<uint32_t>();
242 uint32_t intid = result.first;
271 const auto collection_id = itte.icid;
316 its.gitsControl.quiescent = 0;
324 its.gitsControl.quiescent = 1;
331 return entry !=
cmdDispatcher.end() ? entry->second.name :
"INVALID";
361 const Addr cmd_addr =
364 doRead(yield, cmd_addr, &command,
sizeof(command));
366 DPRINTF(ITS,
"Command %s read from queue at address: %#x\n",
368 DPRINTF(ITS,
"dw0: %#x dw1: %#x dw2: %#x dw3: %#x\n",
369 command.
raw[0], command.
raw[1], command.
raw[2], command.
raw[3]);
379 entry->second.exec(
this, yield, command);
381 panic(
"Unrecognized command type: %u", command.
type);
401 yield, dte.ittAddress, command.
eventId);
408 const auto collection_id = itte.icid;
436 yield, dte.ittAddress, command.
eventId);
443 const auto collection_id = itte.icid;
456 yield, dte.ittAddress, command.
eventId, itte);
475 yield, dte.ittAddress, command.
eventId);
482 const auto collection_id = itte.icid;
510 yield, dte.ittAddress, command.
eventId);
517 const auto collection_id = itte.icid;
557 cte.valid =
bits(command.
raw[2], 63);
558 cte.rdBase =
bits(command.
raw[2], 50, 16);
574 dte.valid =
bits(command.
raw[2], 63);
575 dte.ittAddress =
mbits(command.
raw[2], 51, 8);
576 dte.ittRange =
bits(command.
raw[1], 4, 0);
604 yield, dte.ittAddress, command.
eventId);
607 itte.intType = Gicv3Its::PHYSICAL_INTERRUPT;
609 itte.icid =
bits(command.
raw[2], 15, 0);
612 yield, dte.ittAddress, command.
eventId, itte);
630 const auto pintid =
bits(command.
raw[1], 63, 32);
640 yield, dte.ittAddress, command.
eventId);
643 itte.intType = Gicv3Its::PHYSICAL_INTERRUPT;
644 itte.intNum = pintid;
645 itte.icid =
bits(command.
raw[2], 15, 0);
648 yield, dte.ittAddress, command.
eventId, itte);
654 const uint64_t rd1 =
bits(command.
raw[2], 50, 16);
655 const uint64_t rd2 =
bits(command.
raw[3], 50, 16);
686 yield, dte.ittAddress, command.
eventId);
688 if (!itte.valid || itte.intType == Gicv3Its::VIRTUAL_INTERRUPT) {
693 const auto collection_id1 = itte.icid;
701 const auto collection_id2 =
bits(command.
raw[2], 15, 0);
712 if (second_redist != first_redist) {
716 first_redist->
setClrLPI(itte.intNum,
false);
717 second_redist->
setClrLPI(itte.intNum,
true);
721 itte.icid = collection_id2;
723 yield, dte.ittAddress, command.
eventId, itte);
729 warn(
"ITS %s command unimplemented", __func__);
735 panic(
"ITS %s command unimplemented", __func__);
741 panic(
"ITS %s command unimplemented", __func__);
747 panic(
"ITS %s command unimplemented", __func__);
753 panic(
"ITS %s command unimplemented", __func__);
759 panic(
"ITS %s command unimplemented", __func__);
765 panic(
"ITS %s command unimplemented", __func__);
771 panic(
"ITS %s command unimplemented", __func__);
788 BASER device_baser = 0;
790 device_baser.entrySize =
sizeof(uint64_t) - 1;
793 BASER icollect_baser = 0;
795 icollect_baser.entrySize =
sizeof(uint64_t) - 1;
822 DPRINTF(GIC,
"%s register at addr: %#x\n", __func__, addr);
876 auto baser_index = relative_addr /
sizeof(uint64_t);
881 panic(
"Unrecognized register access\n");
895 DPRINTF(GIC,
"%s register at addr: %#x\n", __func__, addr);
899 assert(pkt->
getSize() ==
sizeof(uint32_t));
908 panic(
"GITS_IIDR is Read Only\n");
911 panic(
"GITS_TYPER is Read Only\n");
914 if (pkt->
getSize() ==
sizeof(uint32_t)) {
917 assert(pkt->
getSize() ==
sizeof(uint64_t));
927 assert(pkt->
getSize() ==
sizeof(uint32_t));
936 if (pkt->
getSize() ==
sizeof(uint32_t)) {
939 assert(pkt->
getSize() ==
sizeof(uint64_t));
947 assert(pkt->
getSize() ==
sizeof(uint32_t));
954 panic(
"GITS_READR is Read Only\n");
957 if (gitsControl.enabled) {
965 auto baser_index = relative_addr /
sizeof(uint64_t);
967 const uint64_t table_base =
tableBases[baser_index];
968 const uint64_t w_mask =
tableBases[baser_index].type ?
970 const uint64_t
val = pkt->
getLE<uint64_t>() & w_mask;
975 panic(
"Unrecognized register access\n");
986 const uint32_t id_bits =
gitsTyper.idBits;
987 return event_id >= (1
ULL << (id_bits + 1)) ||
988 event_id >= ((1
ULL << itt_range) + 1);
1008 const auto cid_bits =
gitsTyper.cil == 0 ?
1011 return collection_id >= (1
ULL << cid_bits);
1028 DPRINTF(Drain,
"GICv3 ITS not drained\n");
1080 if (!gitsControl.enabled || !
gitsCbaser.valid)
1093 DPRINTF(ITS,
"Reading command from queue\n");
1100 DPRINTF(ITS,
"Waiting for pending command to finish\n");
1108 if (if_name ==
"dma") {
1153 panic(
"Not in timing or atomic mode\n");
1162 switch (action.
type) {
1182 panic(
"Unknown action\n");
1193 bool terminate =
false;
1196 action = proc->
run(pkt);
1198 switch (action.
type) {
1210 panic(
"Unknown action\n");
1213 }
while (!terminate);
1215 action.
delay = delay;
1223 DPRINTF(ITS,
"Starting Translation Request\n");
1244 auto base_it = std::find_if(
1246 [table] (
const BASER &
b) {
return b.type == table; }
1250 "ITS Table not recognised\n");
1252 const BASER
base = *base_it;
1255 switch (base.pageSize) {
1258 return mbits(base, 47, 12);
1260 return mbits(base, 47, 16) | (
bits(base, 15, 12) << 48);
1262 panic(
"Unsupported page size\n");
1270 const uint64_t largest_lpi_id = 1
ULL << (rd1->
lpiIDBits + 1);
1271 uint8_t lpi_pending_table[largest_lpi_id / 8];
1276 sizeof(lpi_pending_table));
1280 sizeof(lpi_pending_table));
1285 0,
sizeof(lpi_pending_table));
1291 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
#define UNSERIALIZE_CONTAINER(member)
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)
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
DrainState
Object drain/handover states.
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...
Draining buffers pending serialization/handover.
bool isAtomicMode() const
Is the system in atomic mode?
static std::string commandName(uint32_t cmd)
static const uint64_t BASER_WMASK_UNIMPL
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 schedule(Event &event, Tick when)
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
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)
#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...
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()
bool scheduled() const
Determine if the current event is scheduled.
void inv(Yield &yield, CommandEntry &command)
static const uint32_t SMALLEST_LPI_ID
virtual const std::string name() const
std::queue< ItsAction > packetsToRetry
void vmapti(Yield &yield, CommandEntry &command)
#define SERIALIZE_CONTAINER(member)
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)
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