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);
580 warn(
"smmu: secure registers (0x%x) are not implemented\n",
587 case sizeof(uint32_t):
588 pkt->
setLE<uint32_t>(*
reinterpret_cast<uint32_t *
>(reg_ptr));
590 case sizeof(uint64_t):
591 pkt->
setLE<uint64_t>(*
reinterpret_cast<uint64_t *
>(reg_ptr));
594 panic(
"smmu: unallowed access size: %d bytes\n", pkt->
getSize());
609 DPRINTF(
SMMUv3,
"writeControl: addr=%08x size=%d data=%16x\n",
611 pkt->
getSize() ==
sizeof(uint64_t) ?
612 pkt->
getLE<uint64_t>() : pkt->
getLE<uint32_t>());
616 assert(pkt->
getSize() ==
sizeof(uint32_t));
620 assert(pkt->
getSize() ==
sizeof(uint32_t));
622 warn(
"SMMUv3::%s No support for interrupt sources", __func__);
629 case offsetof(
SMMURegs, strtab_base_cfg):
630 case offsetof(
SMMURegs, eventq_cons):
631 case offsetof(
SMMURegs, eventq_irq_cfg1):
633 assert(pkt->
getSize() ==
sizeof(uint32_t));
635 pkt->
getLE<uint32_t>();
639 assert(pkt->
getSize() ==
sizeof(uint32_t));
641 warn(
"CMDQ is enabled: ignoring write to CMDQ_CONS\n");
644 pkt->
getLE<uint32_t>();
649 assert(pkt->
getSize() ==
sizeof(uint32_t));
651 pkt->
getLE<uint32_t>();
655 case offsetof(
SMMURegs, strtab_base):
656 case offsetof(
SMMURegs, eventq_irq_cfg0):
657 assert(pkt->
getSize() ==
sizeof(uint64_t));
659 pkt->
getLE<uint64_t>();
663 assert(pkt->
getSize() ==
sizeof(uint64_t));
665 warn(
"CMDQ is enabled: ignoring write to CMDQ_BASE\n");
668 pkt->
getLE<uint64_t>();
674 case offsetof(
SMMURegs, eventq_base):
675 assert(pkt->
getSize() ==
sizeof(uint64_t));
677 pkt->
getLE<uint64_t>();
683 assert(pkt->
getSize() ==
sizeof(uint64_t));
685 pkt->
getLE<uint64_t>();
692 warn(
"smmu: secure registers (0x%x) are not implemented\n",
695 warn(
"smmu: write to read-only/undefined register at 0x%x\n",
719 fatal(
"Request port is not connected.\n");
736 : statistics::
Group(parent),
737 ADD_STAT(steL1Fetches, statistics::units::Count::get(),
"STE L1 fetches"),
738 ADD_STAT(steFetches, statistics::units::Count::get(),
"STE fetches"),
739 ADD_STAT(cdL1Fetches, statistics::units::Count::get(),
"CD L1 fetches"),
740 ADD_STAT(cdFetches, statistics::units::Count::get(),
"CD fetches"),
741 ADD_STAT(translationTimeDist, statistics::units::
Tick::get(),
742 "Time to translate address"),
744 "Time to walk page tables")
746 using namespace statistics;
761 .
init(0, 2000000, 2000)
765 .
init(0, 2000000, 2000)
782 DPRINTF(Checkpoint,
"Serializing SMMUv3\n");
790 DPRINTF(Checkpoint,
"Unserializing SMMUv3\n");
798 if (
name ==
"request") {
800 }
else if (
name ==
"walker") {
802 }
else if (
name ==
"control") {
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
void invalidateVAA(Addr va, uint16_t vmid)
void invalidateVA(Addr va, uint16_t asid, uint16_t vmid)
void invalidateVMID(uint16_t vmid)
void invalidateASID(uint16_t asid, uint16_t vmid)
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Tick nextCycle() const
Based on the clock of the object, determine the start tick of the first cycle that is at least one cy...
void invalidateSID(uint32_t sid)
void invalidateSSID(uint32_t sid, uint32_t ssid)
void invalidateVMID(uint16_t vmid)
void invalidateIPA(Addr ipa, uint16_t vmid)
virtual std::string name() const
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
void setLE(T v)
Set the value in the data pointer to v as little endian.
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.
void makeAtomicResponse()
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Ports are used to interface objects to each other.
bool isConnected() const
Is this port currently connected to a peer?
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.
void sendRangeChange() const
Called by the owner to send a range change.
SMMUAction run(PacketPtr pkt)
void schedAtsTimingResp(PacketPtr pkt)
void schedTimingResp(PacketPtr pkt)
SMMUCommandExecProcess commandExecutor
Tick readControl(PacketPtr pkt)
const bool irqInterfaceEnable
void serialize(CheckpointOut &cp) const override
Serialize an object.
SMMUAction runProcess(SMMUProcess *proc, PacketPtr pkt)
std::vector< SMMUv3DeviceInterface * > deviceInterfaces
void unserialize(CheckpointIn &cp) override
Unserialize an object.
SMMUControlPort controlPort
SMMUTableWalkPort tableWalkPort
virtual void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
SMMUAction runProcessAtomic(SMMUProcess *proc, PacketPtr pkt)
bool recvTimingResp(PacketPtr pkt)
bool inSecureBlock(uint32_t offs) const
virtual Port & getPort(const std::string &name, PortID id=InvalidPortID) override
Get a port with a given name and index.
Tick writeControl(PacketPtr pkt)
SMMURequestPort requestPort
void scheduleDeviceRetries()
std::queue< SMMUAction > packetsTableWalkToRetry
DrainState drain() override
Provide a default implementation of the drain interface for objects that don't need draining.
std::queue< SMMUAction > packetsToRetry
void processCommand(const SMMUCommand &cmd)
void tableWalkRecvReqRetry()
SMMUv3(const SMMUv3Params &p)
MemberEventWrapper<&SMMUv3::processCommands > processCommandsEvent
SMMUAction runProcessTiming(SMMUProcess *proc, PacketPtr pkt)
bool tableWalkRecvTimingResp(PacketPtr pkt)
bool isAtomicMode() const
Is the system in atomic mode?
bool isTimingMode() const
Is the system in timing mode?
void invalidateVAA(Addr va, uint16_t vmid, const bool leaf_only)
void invalidateVMID(uint16_t vmid)
void invalidateASID(uint16_t asid, uint16_t vmid)
void invalidateVA(Addr va, uint16_t asid, uint16_t vmid, const bool leaf_only)
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
Distribution & init(Counter min, Counter max, Counter bkt)
Set the parameters of this distribution.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Addr start() const
Get the start address of the range.
DrainState
Object drain/handover states.
@ Draining
Draining buffers pending serialization/handover.
@ Drained
Buffers drained, ready for serialization/handover.
void schedule(Event &event, Tick when)
#define panic(...)
This implements a cprintf based panic() function.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
#define fatal(...)
This implements a cprintf based fatal() function.
#define UNSERIALIZE_ARRAY(member, size)
#define SERIALIZE_ARRAY(member, size)
const Params & params() const
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
const FlagsType pdf
Print the percent of the total that this entry represents.
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
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.
This is an implementation of the SMMUv3 architecture.
SMMUv3DeviceInterface * ifc
SMMUv3Stats(statistics::Group *parent)
statistics::Distribution ptwTimeDist
statistics::Scalar cdL1Fetches
statistics::Scalar steL1Fetches
statistics::Scalar steFetches
statistics::Distribution translationTimeDist
statistics::Scalar cdFetches
const std::string & name()
uint8_t data[SMMU_REG_SIZE]