From f82f1dd81b9e2342e1c43fe5c413626c1cde996f Mon Sep 17 00:00:00 2001 From: Adrian Herrera Date: Tue, 18 Jun 2019 16:56:18 +0100 Subject: [PATCH] dev-arm: drain implementation for SMMUv3 SMMUv3 is drained when (1) no SMMU translations are pending on any of its slave interfaces and (2) no commands are stored in the Command Queue waiting to be processed. Change-Id: I81cef5fd821fa5e509e130af02aece5239493df5 Reviewed-by: Giacomo Travaglini Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/19309 Reviewed-by: Andreas Sandberg Maintainer: Andreas Sandberg Tested-by: kokoro --- src/dev/arm/smmu_v3.cc | 6 +++++- src/dev/arm/smmu_v3_cmdexec.cc | 2 ++ src/dev/arm/smmu_v3_slaveifc.cc | 10 ++++++++++ src/dev/arm/smmu_v3_slaveifc.hh | 11 +++++++++++ src/dev/arm/smmu_v3_transl.cc | 5 +++++ 5 files changed, 33 insertions(+), 1 deletion(-) 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(_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 -- 2.30.2