Go to the documentation of this file.
48 #include "debug/Checkpoint.hh"
49 #include "debug/SMMUv3.hh"
57 requestorId(params->
system->getRequestorId(this)),
58 requestPort(
name() +
".request", *this),
59 tableWalkPort(
name() +
".walker", *this),
60 controlPort(
name() +
".control", *this, params->reg_map),
61 tlb(params->tlb_entries, params->tlb_assoc, params->tlb_policy),
62 configCache(params->cfg_entries, params->cfg_assoc, params->cfg_policy),
63 ipaCache(params->ipa_entries, params->ipa_assoc, params->ipa_policy),
68 params->walk_assoc, params->walk_policy),
69 tlbEnable(params->tlb_enable),
70 configCacheEnable(params->cfg_enable),
71 ipaCacheEnable(params->ipa_enable),
72 walkCacheEnable(params->walk_enable),
73 tableWalkPortEnable(
false),
74 walkCacheNonfinalEnable(params->wc_nonfinal_enable),
75 walkCacheS1Levels(params->wc_s1_levels),
76 walkCacheS2Levels(params->wc_s2_levels),
77 requestPortWidth(params->request_port_width),
78 tlbSem(params->tlb_slots),
81 configSem(params->cfg_slots),
82 ipaSem(params->ipa_slots),
83 walkSem(params->walk_slots),
85 transSem(params->xlate_slots),
86 ptwSem(params->ptw_slots),
88 tlbLat(params->tlb_lat),
89 ifcSmmuLat(params->ifc_smmu_lat),
90 smmuIfcLat(params->smmu_ifc_lat),
91 configLat(params->cfg_lat),
92 ipaLat(params->ipa_lat),
93 walkLat(params->walk_lat),
94 deviceInterfaces(params->device_interfaces),
95 commandExecutor(
name() +
".cmd_exec", *
this),
96 regsMap(params->reg_map),
97 processCommandsEvent(
this)
100 "Invalid register map size: %#x different than SMMU_REG_SIZE = %#x\n",
104 memset(®s, 0,
sizeof(regs));
107 regs.idr0 = params->smmu_idr0;
108 regs.idr1 = params->smmu_idr1;
109 regs.idr2 = params->smmu_idr2;
110 regs.idr3 = params->smmu_idr3;
111 regs.idr4 = params->smmu_idr4;
112 regs.idr5 = params->smmu_idr5;
113 regs.iidr = params->smmu_iidr;
114 regs.aidr = params->smmu_aidr;
120 warn(
"SMMUv3 IDx register values unchecked\n");
122 for (
auto ifc : deviceInterfaces)
154 a.pkt->getAddr(),
a.pkt->getSize());
175 DPRINTF(
SMMUv3,
"[t] requestor HWTW resp addr=%#x size=%#x\n",
200 DPRINTF(
SMMUv3,
"[t] requestor HWTW retr addr=%#x size=%#x\n",
201 a.pkt->getAddr(),
a.pkt->getSize());
214 ifc->scheduleDeviceRetry();
226 panic(
"Not in timing or atomic mode!");
235 bool finished =
false;
238 action = proc->
run(pkt);
240 switch (action.
type) {
263 delay += action.
delay;
267 panic(
"ACTION_TERMINATE in atomic mode\n");
270 panic(
"Unknown action\n");
274 action.
delay = delay;
284 switch (action.
type) {
292 DPRINTF(
SMMUv3,
"[t] requestor HWTW req addr=%#x size=%#x\n",
342 DPRINTF(
SMMUv3,
"[t] ATS responder resp addr=%#x size=%#x\n",
360 panic(
"Unknown action\n");
378 panic(
"Not in timing or atomic mode!");
385 switch (cmd.dw0.
type) {
399 dev_interface->microTLB->invalidateSID(cmd.dw0.
sid);
400 dev_interface->mainTLB->invalidateSID(cmd.dw0.
sid);
406 const auto range = cmd.dw1.
range;
414 dev_interface->microTLB->invalidateAll();
415 dev_interface->mainTLB->invalidateAll();
419 const auto start_sid = cmd.dw0.
sid & ~((1 << (range + 1)) - 1);
420 const auto end_sid = start_sid + (1 << (range + 1)) - 1;
421 for (
auto sid = start_sid; sid <= end_sid; sid++) {
425 dev_interface->microTLB->invalidateSID(sid);
426 dev_interface->mainTLB->invalidateSID(sid);
439 dev_interface->microTLB->invalidateSSID(
441 dev_interface->mainTLB->invalidateSSID(
452 dev_interface->microTLB->invalidateSID(cmd.dw0.
sid);
453 dev_interface->mainTLB->invalidateSID(cmd.dw0.
sid);
461 dev_interface->microTLB->invalidateVMID(cmd.dw0.
vmid);
462 dev_interface->mainTLB->invalidateVMID(cmd.dw0.
vmid);
473 dev_interface->microTLB->invalidateASID(
475 dev_interface->mainTLB->invalidateASID(
488 dev_interface->microTLB->invalidateVAA(
490 dev_interface->mainTLB->invalidateVAA(
494 const bool leaf_only = cmd.dw1.leaf ? true :
false;
501 DPRINTF(
SMMUv3,
"CMD_TLBI_NH_VA va=%#08x asid=%#x vmid=%#x\n",
504 dev_interface->microTLB->invalidateVA(
506 dev_interface->mainTLB->invalidateVA(
510 const bool leaf_only = cmd.dw1.leaf ? true :
false;
532 dev_interface->microTLB->invalidateVMID(cmd.dw0.
vmid);
533 dev_interface->mainTLB->invalidateVMID(cmd.dw0.
vmid);
544 dev_interface->microTLB->invalidateAll();
545 dev_interface->mainTLB->invalidateAll();
555 panic(
"resume unimplemented");
559 warn(
"Unimplemented command %#x\n", cmd.dw0.
type);
571 switch (trans_granule) {
576 panic(
"Unknown translation granule size %d", trans_granule);
590 warn(
"smmu: secure registers (0x%x) are not implemented\n",
597 case sizeof(uint32_t):
598 pkt->
setLE<uint32_t>(*
reinterpret_cast<uint32_t *
>(reg_ptr));
600 case sizeof(uint64_t):
601 pkt->
setLE<uint64_t>(*
reinterpret_cast<uint64_t *
>(reg_ptr));
604 panic(
"smmu: unallowed access size: %d bytes\n", pkt->
getSize());
619 DPRINTF(
SMMUv3,
"writeControl: addr=%08x size=%d data=%16x\n",
621 pkt->
getSize() ==
sizeof(uint64_t) ?
622 pkt->
getLE<uint64_t>() : pkt->
getLE<uint32_t>());
626 assert(pkt->
getSize() ==
sizeof(uint32_t));
632 case offsetof(
SMMURegs, strtab_base_cfg):
633 case offsetof(
SMMURegs, eventq_cons):
634 case offsetof(
SMMURegs, eventq_irq_cfg1):
636 assert(pkt->
getSize() ==
sizeof(uint32_t));
638 pkt->
getLE<uint32_t>();
642 assert(pkt->
getSize() ==
sizeof(uint32_t));
644 warn(
"CMDQ is enabled: ignoring write to CMDQ_CONS\n");
647 pkt->
getLE<uint32_t>();
652 assert(pkt->
getSize() ==
sizeof(uint32_t));
654 pkt->
getLE<uint32_t>();
658 case offsetof(
SMMURegs, strtab_base):
659 case offsetof(
SMMURegs, eventq_irq_cfg0):
660 assert(pkt->
getSize() ==
sizeof(uint64_t));
662 pkt->
getLE<uint64_t>();
666 assert(pkt->
getSize() ==
sizeof(uint64_t));
668 warn(
"CMDQ is enabled: ignoring write to CMDQ_BASE\n");
671 pkt->
getLE<uint64_t>();
677 case offsetof(
SMMURegs, eventq_base):
678 assert(pkt->
getSize() ==
sizeof(uint64_t));
680 pkt->
getLE<uint64_t>();
686 assert(pkt->
getSize() ==
sizeof(uint64_t));
688 pkt->
getLE<uint64_t>();
695 warn(
"smmu: secure registers (0x%x) are not implemented\n",
698 warn(
"smmu: write to read-only/undefined register at 0x%x\n",
722 fatal(
"Request port is not connected.\n");
743 using namespace Stats;
759 .
desc(
"STE L1 fetches")
769 .
desc(
"CD L1 fetches")
778 .
init(0, 2000000, 2000)
779 .
name(
name() +
".translationTimeDist")
780 .
desc(
"Time to translate address")
784 .
init(0, 2000000, 2000)
786 .
desc(
"Time to walk page tables")
803 DPRINTF(Checkpoint,
"Serializing SMMUv3\n");
811 DPRINTF(Checkpoint,
"Unserializing SMMUv3\n");
819 if (
name ==
"request") {
821 }
else if (
name ==
"walker") {
823 }
else if (
name ==
"control") {
831 SMMUv3Params::create()
#define fatal(...)
This implements a cprintf based fatal() function.
virtual void regStats()
Callback to set stat parameters.
void makeAtomicResponse()
void schedTimingResp(PacketPtr pkt)
void invalidateSSID(uint32_t sid, uint32_t ssid)
EventWrapper< SMMUv3, &SMMUv3::processCommands > processCommandsEvent
bool isTimingMode() const
Is the system in timing mode?
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
void invalidateIPA(Addr ipa, uint16_t vmid)
bool recvTimingResp(PacketPtr pkt)
const PageTableOps * getPageTableOps(uint8_t trans_granule)
uint64_t Tick
Tick count type.
SMMUv3DeviceInterface * ifc
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
SMMUAction runProcess(SMMUProcess *proc, PacketPtr pkt)
void scheduleDeviceRetries()
SMMUAction run(PacketPtr pkt)
SMMUAction runProcessTiming(SMMUProcess *proc, PacketPtr pkt)
std::queue< SMMUAction > packetsTableWalkToRetry
const Params * params() const
SMMURequestPort requestPort
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
@ Drained
Buffers drained, ready for serialization/handover.
void invalidateVAA(Addr va, uint16_t vmid, const bool leaf_only)
DrainState
Object drain/handover states.
SMMUAction runProcessAtomic(SMMUProcess *proc, PacketPtr pkt)
void invalidateVA(Addr va, uint16_t asid, uint16_t vmid, const bool leaf_only)
void schedule(Event &event, Tick when)
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
bool inSecureBlock(uint32_t offs) const
Ports are used to interface objects to each other.
Stats::Distribution translationTimeDist
SMMUCommandExecProcess commandExecutor
SMMUTableWalkPort tableWalkPort
#define SERIALIZE_ARRAY(member, size)
Tick readControl(PacketPtr pkt)
std::vector< SMMUv3DeviceInterface * > deviceInterfaces
std::queue< SMMUAction > packetsToRetry
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
SMMUControlPort controlPort
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
const std::string & name()
void regStats(const std::string &name) override
void serialize(CheckpointOut &cp) const override
Serialize an object.
void invalidateVMID(uint16_t vmid)
void invalidateASID(uint16_t asid, uint16_t vmid)
uint8_t data[SMMU_REG_SIZE]
virtual const std::string name() const
void invalidateSID(uint32_t sid)
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
void invalidateASID(uint16_t asid, uint16_t vmid)
void schedAtsTimingResp(PacketPtr pkt)
void tableWalkRecvReqRetry()
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
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...
Stats::Scalar steL1Fetches
Addr start() const
Get the start address of the range.
#define UNSERIALIZE_ARRAY(member, size)
virtual void regStats() override
Callback to set stat parameters.
Distribution & init(Counter min, Counter max, Counter bkt)
Set the parameters of this distribution.
const FlagsType pdf
Print the percent of the total that this entry represents.
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
void invalidateVAA(Addr va, uint16_t vmid)
Tick writeControl(PacketPtr pkt)
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
bool isConnected() const
Is this port currently connected to a peer?
Tick nextCycle() const
Based on the clock of the object, determine the start tick of the first cycle that is at least one cy...
virtual Port & getPort(const std::string &name, PortID id=InvalidPortID) override
Get a port with a given name and index.
void setLE(T v)
Set the value in the data pointer to v as little endian.
std::ostream CheckpointOut
void invalidateVMID(uint16_t vmid)
virtual void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
bool tableWalkRecvTimingResp(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 invalidateVA(Addr va, uint16_t asid, uint16_t vmid)
virtual void regStats(const std::string &name)
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void sendRangeChange() const
Called by the owner to send a range change.
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
void processCommand(const SMMUCommand &cmd)
bool isAtomicMode() const
Is the system in atomic mode?
std::string csprintf(const char *format, const Args &...args)
Stats::Distribution ptwTimeDist
Stats::Scalar cdL1Fetches
@ Draining
Draining buffers pending serialization/handover.
void invalidateVMID(uint16_t vmid)
#define panic(...)
This implements a cprintf based panic() function.
Generated on Wed Sep 30 2020 14:02:10 for gem5 by doxygen 1.8.17