dev-arm: drain implementation for SMMUv3
authorAdrian Herrera <adrian.herrera@arm.com>
Tue, 18 Jun 2019 15:56:18 +0000 (16:56 +0100)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Wed, 26 Jun 2019 11:58:55 +0000 (11:58 +0000)
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 <giacomo.travaglini@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/19309
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/dev/arm/smmu_v3.cc
src/dev/arm/smmu_v3_cmdexec.cc
src/dev/arm/smmu_v3_slaveifc.cc
src/dev/arm/smmu_v3_slaveifc.hh
src/dev/arm/smmu_v3_transl.cc

index 25176491edecf9409cb7f0cd0640220991841b51..d913d55a0a43fefe56e13262952eb4681743d9b1 100644 (file)
@@ -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
index 8660846fd797651cfa10b3d5e8bc227244805451..494c86798b7f93e4e929c411d01ab0f9d658b627 100644 (file)
@@ -75,6 +75,8 @@ SMMUCommandExecProcess::main(Yield &yield)
         }
 
         busy = false;
+        // No more commands to process, signal the SMMU as drained
+        smmu.signalDrainDone();
 
         doSleep(yield);
     }
index 48b11411590b7f6a6f93e8a3b7e7a0a913397d81..0a53ed0ba4f9c4775daddce9ccb760e6d8ae9929 100644 (file)
@@ -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()
 {
index a782ff9b7416650a8fd3dc724467454316b38ea2..3302d829bc44a7526af7802c054f02678323649f 100644 (file)
@@ -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();
 };
index 6e0dacb88a712e672816b9b47379302d2ad78aeb..f1e1fb11fba940aaef0c2d90bb746626d1997b7f 100644 (file)
@@ -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