dev, kvm: Add a fast KVM-aware mode in DmaReadFifo
authorSudhanshu Jha <sudhanshu.jha@arm.com>
Mon, 27 Feb 2017 10:29:56 +0000 (10:29 +0000)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Tue, 7 Mar 2017 11:14:28 +0000 (11:14 +0000)
Use a fast, functional, read operations keep the DMA FIFO full when
running in KVM mode.

Change-Id: I5b378c2fb6a1d3e687cef15e807e63a0a53a60e2
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/2226
Reviewed-by: Rahul Thakur <rjthakur@google.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>

src/dev/dma_device.cc
src/dev/dma_device.hh

index 3515e70215f2c1e923cda355a2649d31acfd2e6c..f84b4c311762d9317e68edfdf5763284d8d84efa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015 ARM Limited
+ * Copyright (c) 2012, 2015, 2017 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -50,6 +50,7 @@
 #include "base/chunk_generator.hh"
 #include "debug/DMA.hh"
 #include "debug/Drain.hh"
+#include "mem/port_proxy.hh"
 #include "sim/system.hh"
 
 DmaPort::DmaPort(MemObject *dev, System *s)
@@ -371,6 +372,40 @@ DmaReadFifo::resumeFill()
         return;
 
     const bool old_eob(atEndOfBlock());
+
+    if (port.sys->bypassCaches())
+        resumeFillFunctional();
+    else
+        resumeFillTiming();
+
+    if (!old_eob && atEndOfBlock())
+        onEndOfBlock();
+}
+
+void
+DmaReadFifo::resumeFillFunctional()
+{
+    const size_t fifo_space = buffer.capacity() - buffer.size();
+    const size_t kvm_watermark = port.sys->cacheLineSize();
+    if (fifo_space >= kvm_watermark || buffer.capacity() < kvm_watermark) {
+        const size_t block_remaining = endAddr - nextAddr;
+        const size_t xfer_size = std::min(fifo_space, block_remaining);
+        std::vector<uint8_t> tmp_buffer(xfer_size);
+
+        assert(pendingRequests.empty());
+        DPRINTF(DMA, "KVM Bypassing startAddr=%#x xfer_size=%#x " \
+                "fifo_space=%#x block_remaining=%#x\n",
+                nextAddr, xfer_size, fifo_space, block_remaining);
+
+        port.sys->physProxy.readBlob(nextAddr, tmp_buffer.data(), xfer_size);
+        buffer.write(tmp_buffer.begin(), xfer_size);
+        nextAddr += xfer_size;
+    }
+}
+
+void
+DmaReadFifo::resumeFillTiming()
+{
     size_t size_pending(0);
     for (auto &e : pendingRequests)
         size_pending += e->requestSize();
@@ -392,11 +427,6 @@ DmaReadFifo::resumeFill()
 
         pendingRequests.emplace_back(std::move(event));
     }
-
-    // EOB can be set before a call to dmaDone() if in-flight accesses
-    // have been canceled.
-    if (!old_eob && atEndOfBlock())
-        onEndOfBlock();
 }
 
 void
@@ -430,8 +460,6 @@ DmaReadFifo::handlePending()
         signalDrainDone();
 }
 
-
-
 DrainState
 DmaReadFifo::drain()
 {
index 4e66b34565a6a08f456dec7480e79b9725e38eec..4a1946af5679216857b15462e33c708529ec1753 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013, 2015 ARM Limited
+ * Copyright (c) 2012-2013, 2015, 2017 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -494,9 +494,15 @@ class DmaReadFifo : public Drainable, public Serializable
     /** Handle pending requests that have been flagged as done. */
     void handlePending();
 
-    /** Try to issue new DMA requests */
+    /** Try to issue new DMA requests or bypass DMA requests*/
     void resumeFill();
 
+    /** Try to issue new DMA requests during normal execution*/
+    void resumeFillTiming();
+
+    /** Try to bypass DMA requests in KVM execution mode */
+    void resumeFillFunctional();
+
   private: // Internal state
     Fifo<uint8_t> buffer;