diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dev/dma_device.cc | 44 | ||||
-rw-r--r-- | 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<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() { 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<uint8_t> buffer; |