summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dev/arm/smmu_v3.cc6
-rw-r--r--src/dev/arm/smmu_v3_cmdexec.cc2
-rw-r--r--src/dev/arm/smmu_v3_slaveifc.cc10
-rw-r--r--src/dev/arm/smmu_v3_slaveifc.hh11
-rw-r--r--src/dev/arm/smmu_v3_transl.cc5
5 files changed, 33 insertions, 1 deletions
diff --git a/src/dev/arm/smmu_v3.cc b/src/dev/arm/smmu_v3.cc
index 25176491e..d913d55a0 100644
--- a/src/dev/arm/smmu_v3.cc
+++ b/src/dev/arm/smmu_v3.cc
@@ -741,7 +741,11 @@ SMMUv3::regStats()
DrainState
SMMUv3::drain()
{
- panic("SMMUv3 doesn't support draining\n");
+ // Wait until the Command Executor is not busy
+ if (commandExecutor.isBusy()) {
+ return DrainState::Draining;
+ }
+ return DrainState::Drained;
}
void
diff --git a/src/dev/arm/smmu_v3_cmdexec.cc b/src/dev/arm/smmu_v3_cmdexec.cc
index 8660846fd..494c86798 100644
--- a/src/dev/arm/smmu_v3_cmdexec.cc
+++ b/src/dev/arm/smmu_v3_cmdexec.cc
@@ -75,6 +75,8 @@ SMMUCommandExecProcess::main(Yield &yield)
}
busy = false;
+ // No more commands to process, signal the SMMU as drained
+ smmu.signalDrainDone();
doSleep(yield);
}
diff --git a/src/dev/arm/smmu_v3_slaveifc.cc b/src/dev/arm/smmu_v3_slaveifc.cc
index 48b114115..0a53ed0ba 100644
--- a/src/dev/arm/smmu_v3_slaveifc.cc
+++ b/src/dev/arm/smmu_v3_slaveifc.cc
@@ -253,6 +253,16 @@ SMMUv3SlaveInterface::scheduleDeviceRetry()
}
}
+DrainState
+SMMUv3SlaveInterface::drain()
+{
+ // Wait until all SMMU translations are completed
+ if (xlateSlotsRemaining < params()->xlate_slots) {
+ return DrainState::Draining;
+ }
+ return DrainState::Drained;
+}
+
SMMUv3SlaveInterface*
SMMUv3SlaveInterfaceParams::create()
{
diff --git a/src/dev/arm/smmu_v3_slaveifc.hh b/src/dev/arm/smmu_v3_slaveifc.hh
index a782ff9b7..3302d829b 100644
--- a/src/dev/arm/smmu_v3_slaveifc.hh
+++ b/src/dev/arm/smmu_v3_slaveifc.hh
@@ -56,6 +56,9 @@ class SMMUSlavePort;
class SMMUv3SlaveInterface : public MemObject
{
+ protected:
+ friend class SMMUTranslationProcess;
+
public:
SMMUv3 *smmu;
SMMUTLB* microTLB;
@@ -124,6 +127,14 @@ class SMMUv3SlaveInterface : public MemObject
delete mainTLB;
}
+ const SMMUv3SlaveInterfaceParams *
+ params() const
+ {
+ return static_cast<const SMMUv3SlaveInterfaceParams *>(_params);
+ }
+
+ DrainState drain() override;
+
void setSMMU(SMMUv3 *_smmu) { smmu = _smmu; }
void sendRange();
};
diff --git a/src/dev/arm/smmu_v3_transl.cc b/src/dev/arm/smmu_v3_transl.cc
index 6e0dacb88..f1e1fb11f 100644
--- a/src/dev/arm/smmu_v3_transl.cc
+++ b/src/dev/arm/smmu_v3_transl.cc
@@ -94,6 +94,11 @@ SMMUTranslationProcess::~SMMUTranslationProcess()
{
// Increase number of pending translation slots on the slave interface
ifc.xlateSlotsRemaining++;
+ // If no more SMMU translations are pending (all slots available),
+ // signal SMMU Slave Interface as drained
+ if (ifc.xlateSlotsRemaining == ifc.params()->xlate_slots) {
+ ifc.signalDrainDone();
+ }
}
void