50 #include "debug/Checkpoint.hh" 51 #include "debug/SMMUv3.hh" 59 masterId(params->
system->getMasterId(this)),
60 masterPort(
name() +
".master", *this),
61 masterTableWalkPort(
name() +
".master_walker", *this),
62 controlPort(
name() +
".control", *this, params->reg_map),
63 tlb(params->tlb_entries, params->tlb_assoc, params->tlb_policy),
64 configCache(params->cfg_entries, params->cfg_assoc, params->cfg_policy),
65 ipaCache(params->ipa_entries, params->ipa_assoc, params->ipa_policy),
66 walkCache({ { params->walk_S1L0, params->walk_S1L1,
67 params->walk_S1L2, params->walk_S1L3,
68 params->walk_S2L0, params->walk_S2L1,
69 params->walk_S2L2, params->walk_S2L3 } },
102 "Invalid register map size: %#x different than SMMU_REG_SIZE = %#x\n",
122 warn(
"SMMUv3 IDx register values unchecked\n");
216 ifc->scheduleDeviceRetry();
228 panic(
"Not in timing or atomic mode!");
237 bool finished =
false;
240 action = proc->
run(pkt);
242 switch (action.
type) {
265 delay += action.
delay;
269 panic(
"ACTION_TERMINATE in atomic mode\n");
272 panic(
"Unknown action\n");
276 action.
delay = delay;
286 switch (action.
type) {
361 panic(
"Unknown action\n");
379 panic(
"Not in timing or atomic mode!");
386 switch (cmd.dw0.
type) {
400 slave_interface->microTLB->invalidateSID(cmd.dw0.
sid);
401 slave_interface->mainTLB->invalidateSID(cmd.dw0.
sid);
407 const auto range = cmd.dw1.
range;
415 slave_interface->microTLB->invalidateAll();
416 slave_interface->mainTLB->invalidateAll();
420 const auto start_sid = cmd.dw0.
sid & ~((1 << (range + 1)) - 1);
421 const auto end_sid = start_sid + (1 << (range + 1)) - 1;
422 for (
auto sid = start_sid; sid <= end_sid; sid++) {
426 slave_interface->microTLB->invalidateSID(sid);
427 slave_interface->mainTLB->invalidateSID(sid);
440 slave_interface->microTLB->invalidateSSID(
442 slave_interface->mainTLB->invalidateSSID(
453 slave_interface->microTLB->invalidateSID(cmd.dw0.
sid);
454 slave_interface->mainTLB->invalidateSID(cmd.dw0.
sid);
462 slave_interface->microTLB->invalidateVMID(cmd.dw0.
vmid);
463 slave_interface->mainTLB->invalidateVMID(cmd.dw0.
vmid);
474 slave_interface->microTLB->invalidateASID(
476 slave_interface->mainTLB->invalidateASID(
489 slave_interface->microTLB->invalidateVAA(
491 slave_interface->mainTLB->invalidateVAA(
495 const bool leaf_only = cmd.dw1.leaf ? true :
false;
502 DPRINTF(
SMMUv3,
"CMD_TLBI_NH_VA va=%#08x asid=%#x vmid=%#x\n",
505 slave_interface->microTLB->invalidateVA(
507 slave_interface->mainTLB->invalidateVA(
511 const bool leaf_only = cmd.dw1.leaf ? true :
false;
533 slave_interface->microTLB->invalidateVMID(cmd.dw0.
vmid);
534 slave_interface->mainTLB->invalidateVMID(cmd.dw0.
vmid);
545 slave_interface->microTLB->invalidateAll();
546 slave_interface->mainTLB->invalidateAll();
556 panic(
"resume unimplemented");
560 warn(
"Unimplemented command %#x\n", cmd.dw0.
type);
572 switch (trans_granule) {
577 panic(
"Unknown translation granule size %d", trans_granule);
591 warn(
"smmu: secure registers (0x%x) are not implemented\n",
598 case sizeof(uint32_t):
599 pkt->
setLE<uint32_t>(*reinterpret_cast<uint32_t *>(reg_ptr));
601 case sizeof(uint64_t):
602 pkt->
setLE<uint64_t>(*reinterpret_cast<uint64_t *>(reg_ptr));
605 panic(
"smmu: unallowed access size: %d bytes\n", pkt->
getSize());
620 DPRINTF(
SMMUv3,
"writeControl: addr=%08x size=%d data=%16x\n",
622 pkt->
getSize() ==
sizeof(uint64_t) ?
623 pkt->
getLE<uint64_t>() : pkt->
getLE<uint32_t>());
627 assert(pkt->
getSize() ==
sizeof(uint32_t));
633 case offsetof(
SMMURegs, strtab_base_cfg):
634 case offsetof(
SMMURegs, eventq_cons):
635 case offsetof(
SMMURegs, eventq_irq_cfg1):
637 assert(pkt->
getSize() ==
sizeof(uint32_t));
639 pkt->
getLE<uint32_t>();
643 assert(pkt->
getSize() ==
sizeof(uint32_t));
645 warn(
"CMDQ is enabled: ignoring write to CMDQ_CONS\n");
648 pkt->
getLE<uint32_t>();
653 assert(pkt->
getSize() ==
sizeof(uint32_t));
655 pkt->
getLE<uint32_t>();
659 case offsetof(
SMMURegs, strtab_base):
660 case offsetof(
SMMURegs, eventq_irq_cfg0):
661 assert(pkt->
getSize() ==
sizeof(uint64_t));
663 pkt->
getLE<uint64_t>();
667 assert(pkt->
getSize() ==
sizeof(uint64_t));
669 warn(
"CMDQ is enabled: ignoring write to CMDQ_BASE\n");
672 pkt->
getLE<uint64_t>();
678 case offsetof(
SMMURegs, eventq_base):
679 assert(pkt->
getSize() ==
sizeof(uint64_t));
681 pkt->
getLE<uint64_t>();
687 assert(pkt->
getSize() ==
sizeof(uint64_t));
689 pkt->
getLE<uint64_t>();
696 warn(
"smmu: secure registers (0x%x) are not implemented\n",
699 warn(
"smmu: write to read-only/undefined register at 0x%x\n",
723 fatal(
"Master port is not connected.\n");
744 using namespace Stats;
760 .
desc(
"STE L1 fetches")
770 .
desc(
"CD L1 fetches")
779 .
init(0, 2000000, 2000)
780 .
name(
name() +
".translationTimeDist")
781 .
desc(
"Time to translate address")
785 .
init(0, 2000000, 2000)
787 .
desc(
"Time to walk page tables")
804 DPRINTF(Checkpoint,
"Serializing SMMUv3\n");
812 DPRINTF(Checkpoint,
"Unserializing SMMUv3\n");
820 if (name ==
"master") {
822 }
else if (name ==
"master_walker") {
824 }
else if (name ==
"control") {
832 SMMUv3Params::create()
#define panic(...)
This implements a cprintf based panic() function.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
std::queue< SMMUAction > packetsTableWalkToRetry
const FlagsType pdf
Print the percent of the total that this entry represents.
Ports are used to interface objects to each other.
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
void invalidateVAA(Addr va, uint16_t vmid, const bool leaf_only)
bool inSecureBlock(uint32_t offs) const
void sendRangeChange() const
Called by the owner to send a range change.
SMMUAction runProcess(SMMUProcess *proc, PacketPtr pkt)
Stats::Distribution translationTimeDist
#define fatal(...)
This implements a cprintf based fatal() function.
std::queue< SMMUAction > packetsToRetry
const std::string & name()
SMMUAction run(PacketPtr pkt)
void invalidateVMID(uint16_t vmid)
DrainState
Object drain/handover states.
virtual void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
void serialize(CheckpointOut &cp) const override
Serialize an object.
void schedAtsTimingResp(PacketPtr pkt)
Tick readControl(PacketPtr pkt)
Tick writeControl(PacketPtr pkt)
void invalidateVMID(uint16_t vmid)
void scheduleSlaveRetries()
virtual void regStats()
Callback to set stat parameters.
const unsigned walkCacheS1Levels
void invalidateSSID(uint32_t sid, uint32_t ssid)
const unsigned masterPortWidth
EventWrapper< SMMUv3, &SMMUv3::processCommands > processCommandsEvent
SMMUv3SlaveInterface * ifc
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the slave port by calling its corresponding receive function...
bool isConnected() const
Is this port currently connected to a peer?
Stats::Scalar steL1Fetches
void invalidateVA(Addr va, uint16_t asid, uint16_t vmid, const bool leaf_only)
void processCommand(const SMMUCommand &cmd)
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
const Params * params() const
virtual Port & getPort(const std::string &name, PortID id=InvalidPortID) override
Get a port with a given name and index.
std::vector< SMMUv3SlaveInterface * > slaveInterfaces
void setLE(T v)
Set the value in the data pointer to v as little endian.
Stats::Scalar cdL1Fetches
void masterRecvReqRetry()
SMMUControlPort controlPort
bool isAtomicMode() const
Is the system in atomic mode?
std::string csprintf(const char *format, const Args &...args)
void masterTableWalkRecvReqRetry()
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
SMMUCommandExecProcess commandExecutor
void makeAtomicResponse()
uint64_t Tick
Tick count type.
Stats::Distribution ptwTimeDist
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
#define SERIALIZE_ARRAY(member, size)
bool masterRecvTimingResp(PacketPtr pkt)
void invalidateIPA(Addr ipa, uint16_t vmid)
void invalidateSID(uint32_t sid)
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
void invalidateASID(uint16_t asid, uint16_t vmid)
Distribution & init(Counter min, Counter max, Counter bkt)
Set the parameters of this distribution.
void schedTimingResp(PacketPtr pkt)
Tick nextCycle() const
Based on the clock of the object, determine the start tick of the first cycle that is at least one cy...
DrainState drain() override
Notify an object that it needs to drain its state.
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
SMMUSemaphore masterPortSem
Draining buffers pending serialization/handover.
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
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
SMMUMasterPort masterPort
#define UNSERIALIZE_ARRAY(member, size)
This is an implementation of the SMMUv3 architecture.
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
void invalidateVAA(Addr va, uint16_t vmid)
bool masterTableWalkRecvTimingResp(PacketPtr pkt)
SMMUAction runProcessTiming(SMMUProcess *proc, PacketPtr pkt)
std::ostream CheckpointOut
uint8_t data[SMMU_REG_SIZE]
void schedule(Event &event, Tick when)
const PageTableOps * getPageTableOps(uint8_t trans_granule)
const bool walkCacheNonfinalEnable
void invalidateVMID(uint16_t vmid)
const bool walkCacheEnable
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...
Addr start() const
Get the start address of the range.
Addr size() const
Get the size of the address range.
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
const bool ipaCacheEnable
const unsigned walkCacheS2Levels
bool isTimingMode() const
Is the system in timing mode?
void invalidateVA(Addr va, uint16_t asid, 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...
void regStats(const std::string &name) override
const bool configCacheEnable
SMMUAction runProcessAtomic(SMMUProcess *proc, PacketPtr pkt)
virtual void regStats(const std::string &name)
virtual void regStats() override
Callback to set stat parameters.
void invalidateASID(uint16_t asid, uint16_t vmid)
SMMUMasterTableWalkPort masterTableWalkPort