diff options
-rw-r--r-- | src/dev/arm/smmu_v3.cc | 6 | ||||
-rw-r--r-- | src/dev/arm/smmu_v3_cmdexec.cc | 2 | ||||
-rw-r--r-- | src/dev/arm/smmu_v3_slaveifc.cc | 10 | ||||
-rw-r--r-- | src/dev/arm/smmu_v3_slaveifc.hh | 11 | ||||
-rw-r--r-- | src/dev/arm/smmu_v3_transl.cc | 5 |
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 |