From 82a8230aa761e193a91ade0fa3c109a5c0f08aed Mon Sep 17 00:00:00 2001 From: Sudhanshu Jha Date: Mon, 27 Feb 2017 10:29:56 +0000 Subject: [PATCH] dev, kvm: Add a fast KVM-aware mode in DmaReadFifo Use a fast, functional, read operations keep the DMA FIFO full when running in KVM mode. Change-Id: I5b378c2fb6a1d3e687cef15e807e63a0a53a60e2 Signed-off-by: Andreas Sandberg Reviewed-on: https://gem5-review.googlesource.com/2226 Reviewed-by: Rahul Thakur Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power --- src/dev/dma_device.cc | 44 +++++++++++++++++++++++++++++++++++-------- src/dev/dma_device.hh | 10 ++++++++-- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/dev/dma_device.cc b/src/dev/dma_device.cc index 3515e7021..f84b4c311 100644 --- a/src/dev/dma_device.cc +++ b/src/dev/dma_device.cc @@ -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 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() { diff --git a/src/dev/dma_device.hh b/src/dev/dma_device.hh index 4e66b3456..4a1946af5 100644 --- a/src/dev/dma_device.hh +++ b/src/dev/dma_device.hh @@ -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 buffer; -- 2.30.2