Go to the documentation of this file.
49 #include "debug/Checkpoint.hh"
50 #include "debug/SMMUv3.hh"
61 requestorId(params.
system->getRequestorId(this)),
62 requestPort(
name() +
".request", *this),
63 tableWalkPort(
name() +
".walker", *this),
64 controlPort(
name() +
".control", *this, params.reg_map),
65 irqInterfaceEnable(params.irq_interface_enable),
66 tlb(params.tlb_entries, params.tlb_assoc, params.tlb_policy, this),
67 configCache(params.cfg_entries, params.cfg_assoc, params.cfg_policy, this),
68 ipaCache(params.ipa_entries, params.ipa_assoc, params.ipa_policy, this),
73 params.walk_assoc, params.walk_policy,
this),
74 tlbEnable(params.tlb_enable),
75 configCacheEnable(params.cfg_enable),
76 ipaCacheEnable(params.ipa_enable),
77 walkCacheEnable(params.walk_enable),
78 tableWalkPortEnable(
false),
79 walkCacheNonfinalEnable(params.wc_nonfinal_enable),
80 walkCacheS1Levels(params.wc_s1_levels),
81 walkCacheS2Levels(params.wc_s2_levels),
82 requestPortWidth(params.request_port_width),
83 tlbSem(params.tlb_slots),
86 configSem(params.cfg_slots),
87 ipaSem(params.ipa_slots),
88 walkSem(params.walk_slots),
90 transSem(params.xlate_slots),
91 ptwSem(params.ptw_slots),
93 tlbLat(params.tlb_lat),
94 ifcSmmuLat(params.ifc_smmu_lat),
95 smmuIfcLat(params.smmu_ifc_lat),
96 configLat(params.cfg_lat),
97 ipaLat(params.ipa_lat),
98 walkLat(params.walk_lat),
100 deviceInterfaces(params.device_interfaces),
101 commandExecutor(
name() +
".cmd_exec", *
this),
102 regsMap(params.reg_map),
103 processCommandsEvent(
this)
106 "Invalid register map size: %#x different than SMMU_REG_SIZE = %#x\n",
110 memset(®s, 0,
sizeof(regs));
113 regs.idr0 = params.smmu_idr0;
114 regs.idr1 = params.smmu_idr1;
115 regs.idr2 = params.smmu_idr2;
116 regs.idr3 = params.smmu_idr3;
117 regs.idr4 = params.smmu_idr4;
118 regs.idr5 = params.smmu_idr5;
119 regs.iidr = params.smmu_iidr;
120 regs.aidr = params.smmu_aidr;
126 warn(
"SMMUv3 IDx register values unchecked\n");
128 for (
auto ifc : deviceInterfaces)
160 a.pkt->getAddr(),
a.pkt->getSize());
181 DPRINTF(
SMMUv3,
"[t] requestor HWTW resp addr=%#x size=%#x\n",
206 DPRINTF(
SMMUv3,
"[t] requestor HWTW retr addr=%#x size=%#x\n",
207 a.pkt->getAddr(),
a.pkt->getSize());
220 ifc->scheduleDeviceRetry();
232 panic(
"Not in timing or atomic mode!");
241 bool finished =
false;
244 action = proc->
run(pkt);
246 switch (action.
type) {
269 delay += action.
delay;
273 panic(
"ACTION_TERMINATE in atomic mode\n");
276 panic(
"Unknown action\n");
280 action.
delay = delay;
290 switch (action.
type) {
298 DPRINTF(
SMMUv3,
"[t] requestor HWTW req addr=%#x size=%#x\n",
348 DPRINTF(
SMMUv3,
"[t] ATS responder resp addr=%#x size=%#x\n",
366 panic(
"Unknown action\n");
384 panic(
"Not in timing or atomic mode!");
391 switch (cmd.dw0.
type) {
405 dev_interface->microTLB->invalidateSID(cmd.dw0.
sid);
406 dev_interface->mainTLB->invalidateSID(cmd.dw0.
sid);
412 const auto range = cmd.dw1.
range;
420 dev_interface->microTLB->invalidateAll();
421 dev_interface->mainTLB->invalidateAll();
425 const auto start_sid = cmd.dw0.
sid & ~((1 << (range + 1)) - 1);
426 const auto end_sid = start_sid + (1 << (range + 1)) - 1;
427 for (
auto sid = start_sid; sid <= end_sid; sid++) {
431 dev_interface->microTLB->invalidateSID(sid);
432 dev_interface->mainTLB->invalidateSID(sid);
445 dev_interface->microTLB->invalidateSSID(
447 dev_interface->mainTLB->invalidateSSID(
458 dev_interface->microTLB->invalidateSID(cmd.dw0.
sid);
459 dev_interface->mainTLB->invalidateSID(cmd.dw0.
sid);
467 dev_interface->microTLB->invalidateVMID(cmd.dw0.
vmid);
468 dev_interface->mainTLB->invalidateVMID(cmd.dw0.
vmid);
479 dev_interface->microTLB->invalidateASID(
481 dev_interface->mainTLB->invalidateASID(
494 dev_interface->microTLB->invalidateVAA(
496 dev_interface->mainTLB->invalidateVAA(
500 const bool leaf_only = cmd.dw1.leaf ? true :
false;
507 DPRINTF(
SMMUv3,
"CMD_TLBI_NH_VA va=%#08x asid=%#x vmid=%#x\n",
510 dev_interface->microTLB->invalidateVA(
512 dev_interface->mainTLB->invalidateVA(
516 const bool leaf_only = cmd.dw1.leaf ? true :
false;
538 dev_interface->microTLB->invalidateVMID(cmd.dw0.
vmid);
539 dev_interface->mainTLB->invalidateVMID(cmd.dw0.
vmid);
550 dev_interface->microTLB->invalidateAll();
551 dev_interface->mainTLB->invalidateAll();
561 panic(
"resume unimplemented");
565 warn(
"Unimplemented command %#x\n", cmd.dw0.
type);
577 switch (trans_granule) {
582 panic(
"Unknown translation granule size %d", trans_granule);
596 warn(
"smmu: secure registers (0x%x) are not implemented\n",
603 case sizeof(uint32_t):
604 pkt->
setLE<uint32_t>(*
reinterpret_cast<uint32_t *
>(reg_ptr));
606 case sizeof(uint64_t):
607 pkt->
setLE<uint64_t>(*
reinterpret_cast<uint64_t *
>(reg_ptr));
610 panic(
"smmu: unallowed access size: %d bytes\n", pkt->
getSize());
625 DPRINTF(
SMMUv3,
"writeControl: addr=%08x size=%d data=%16x\n",
627 pkt->
getSize() ==
sizeof(uint64_t) ?
628 pkt->
getLE<uint64_t>() : pkt->
getLE<uint32_t>());
632 assert(pkt->
getSize() ==
sizeof(uint32_t));
636 assert(pkt->
getSize() ==
sizeof(uint32_t));
638 warn(
"SMMUv3::%s No support for interrupt sources", __func__);
645 case offsetof(
SMMURegs, strtab_base_cfg):
646 case offsetof(
SMMURegs, eventq_cons):
647 case offsetof(
SMMURegs, eventq_irq_cfg1):
649 assert(pkt->
getSize() ==
sizeof(uint32_t));
651 pkt->
getLE<uint32_t>();
655 assert(pkt->
getSize() ==
sizeof(uint32_t));
657 warn(
"CMDQ is enabled: ignoring write to CMDQ_CONS\n");
660 pkt->
getLE<uint32_t>();
665 assert(pkt->
getSize() ==
sizeof(uint32_t));
667 pkt->
getLE<uint32_t>();
671 case offsetof(
SMMURegs, strtab_base):
672 case offsetof(
SMMURegs, eventq_irq_cfg0):
673 assert(pkt->
getSize() ==
sizeof(uint64_t));
675 pkt->
getLE<uint64_t>();
679 assert(pkt->
getSize() ==
sizeof(uint64_t));
681 warn(
"CMDQ is enabled: ignoring write to CMDQ_BASE\n");
684 pkt->
getLE<uint64_t>();
690 case offsetof(
SMMURegs, eventq_base):
691 assert(pkt->
getSize() ==
sizeof(uint64_t));
693 pkt->
getLE<uint64_t>();
699 assert(pkt->
getSize() ==
sizeof(uint64_t));
701 pkt->
getLE<uint64_t>();
708 warn(
"smmu: secure registers (0x%x) are not implemented\n",
711 warn(
"smmu: write to read-only/undefined register at 0x%x\n",
735 fatal(
"Request port is not connected.\n");
752 : statistics::
Group(parent),
753 ADD_STAT(steL1Fetches, statistics::units::Count::get(),
"STE L1 fetches"),
754 ADD_STAT(steFetches, statistics::units::Count::get(),
"STE fetches"),
755 ADD_STAT(cdL1Fetches, statistics::units::Count::get(),
"CD L1 fetches"),
756 ADD_STAT(cdFetches, statistics::units::Count::get(),
"CD fetches"),
757 ADD_STAT(translationTimeDist, statistics::units::
Tick::get(),
758 "Time to translate address"),
760 "Time to walk page tables")
762 using namespace statistics;
777 .
init(0, 2000000, 2000)
781 .
init(0, 2000000, 2000)
798 DPRINTF(Checkpoint,
"Serializing SMMUv3\n");
806 DPRINTF(Checkpoint,
"Unserializing SMMUv3\n");
814 if (
name ==
"request") {
816 }
else if (
name ==
"walker") {
818 }
else if (
name ==
"control") {
std::queue< SMMUAction > packetsToRetry
#define fatal(...)
This implements a cprintf based fatal() function.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Addr start() const
Get the start address of the range.
const PageTableOps * getPageTableOps(uint8_t trans_granule)
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
SMMUAction runProcessTiming(SMMUProcess *proc, PacketPtr pkt)
SMMUControlPort controlPort
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...
void schedTimingResp(PacketPtr pkt)
void invalidateIPA(Addr ipa, uint16_t vmid)
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time,...
statistics::Distribution ptwTimeDist
bool isAtomicMode() const
Is the system in atomic mode?
void invalidateVMID(uint16_t vmid)
statistics::Scalar cdFetches
void schedule(Event &event, Tick when)
statistics::Scalar steFetches
Tick writeControl(PacketPtr pkt)
void makeAtomicResponse()
statistics::Scalar steL1Fetches
SMMURequestPort requestPort
void unserialize(CheckpointIn &cp) override
Unserialize an object.
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
bool recvTimingResp(PacketPtr pkt)
SMMUAction runProcessAtomic(SMMUProcess *proc, PacketPtr pkt)
SMMUv3(const SMMUv3Params &p)
statistics::Distribution translationTimeDist
const FlagsType pdf
Print the percent of the total that this entry represents.
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
void schedAtsTimingResp(PacketPtr pkt)
DrainState
Object drain/handover states.
Distribution & init(Counter min, Counter max, Counter bkt)
Set the parameters of this distribution.
virtual std::string name() const
const Params & params() const
const bool irqInterfaceEnable
void tableWalkRecvReqRetry()
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
uint64_t Tick
Tick count type.
Tick readControl(PacketPtr pkt)
virtual Port & getPort(const std::string &name, PortID id=InvalidPortID) override
Get a port with a given name and index.
bool inSecureBlock(uint32_t offs) const
void processCommand(const SMMUCommand &cmd)
virtual void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
void invalidateVMID(uint16_t vmid)
bool isConnected() const
Is this port currently connected to a peer?
#define SERIALIZE_ARRAY(member, size)
void invalidateVA(Addr va, uint16_t asid, uint16_t vmid, const bool leaf_only)
@ Drained
Buffers drained, ready for serialization/handover.
bool isTimingMode() const
Is the system in timing mode?
void invalidateASID(uint16_t asid, uint16_t vmid)
SMMUv3Stats(statistics::Group *parent)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
void invalidateASID(uint16_t asid, uint16_t vmid)
bool tableWalkRecvTimingResp(PacketPtr pkt)
const std::string & name()
void invalidateVMID(uint16_t vmid)
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
void sendRangeChange() const
Called by the owner to send a range change.
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
EventWrapper< SMMUv3, &SMMUv3::processCommands > processCommandsEvent
void invalidateVAA(Addr va, uint16_t vmid, const bool leaf_only)
Tick nextCycle() const
Based on the clock of the object, determine the start tick of the first cycle that is at least one cy...
std::queue< SMMUAction > packetsTableWalkToRetry
uint8_t data[SMMU_REG_SIZE]
SMMUTableWalkPort tableWalkPort
void invalidateVA(Addr va, uint16_t asid, uint16_t vmid)
Ports are used to interface objects to each other.
#define UNSERIALIZE_ARRAY(member, size)
SMMUAction run(PacketPtr pkt)
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
void invalidateSID(uint32_t sid)
SMMUv3DeviceInterface * ifc
void serialize(CheckpointOut &cp) const override
Serialize an object.
std::ostream CheckpointOut
void setLE(T v)
Set the value in the data pointer to v as little endian.
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
std::vector< SMMUv3DeviceInterface * > deviceInterfaces
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
void scheduleDeviceRetries()
SMMUAction runProcess(SMMUProcess *proc, PacketPtr pkt)
statistics::Scalar cdL1Fetches
SMMUCommandExecProcess commandExecutor
void invalidateSSID(uint32_t sid, uint32_t ssid)
@ Draining
Draining buffers pending serialization/handover.
#define panic(...)
This implements a cprintf based panic() function.
void invalidateVAA(Addr va, uint16_t vmid)
Generated on Wed Jul 28 2021 12:10:25 for gem5 by doxygen 1.8.17