diff --git a/fpga/include/villas/fpga/card.hpp b/fpga/include/villas/fpga/card.hpp index 5b071089c..07028bfa4 100644 --- a/fpga/include/villas/fpga/card.hpp +++ b/fpga/include/villas/fpga/card.hpp @@ -88,8 +88,8 @@ public: std::shared_ptr lookupIp(const ip::IpIdentifier &id) const; - bool - mapMemoryBlock(const MemoryBlock &block); + bool mapMemoryBlock(const MemoryBlock &block); + bool unmapMemoryBlock(const MemoryBlock &block); private: // Cache a set of already mapped memory blocks diff --git a/fpga/lib/card.cpp b/fpga/lib/card.cpp index 45d64b51e..89c243ea8 100644 --- a/fpga/lib/card.cpp +++ b/fpga/lib/card.cpp @@ -218,6 +218,29 @@ std::shared_ptr PCIeCard::lookupIp(const ip::IpIdentifier &id) const return nullptr; } +bool PCIeCard::unmapMemoryBlock(const MemoryBlock &block) +{ + if (memoryBlocksMapped.find(block.getAddrSpaceId()) == memoryBlocksMapped.end()) { + throw std::runtime_error("Block " + std::to_string(block.getAddrSpaceId()) + " is not mapped but was requested to be unmapped."); + } + + auto &mm = MemoryManager::get(); + + // Unmap all memory blocks + auto translation = mm.getTranslation(addrSpaceIdDeviceToHost, block.getAddrSpaceId()); + + const uintptr_t iova = translation.getLocalAddr(0); + const size_t size = translation.getSize(); + + logger->debug("Unmap block {} at IOVA {:#x} of size {:#x}", + block.getAddrSpaceId(), iova, size); + vfioContainer->memoryUnmap(iova, size); + + memoryBlocksMapped.erase(block.getAddrSpaceId()); + + return true; +} + bool PCIeCard::mapMemoryBlock(const MemoryBlock &block) { if (not vfioContainer->isIommuEnabled()) { diff --git a/fpga/lib/ips/dma.cpp b/fpga/lib/ips/dma.cpp index 3904e173c..cc9bb9356 100644 --- a/fpga/lib/ips/dma.cpp +++ b/fpga/lib/ips/dma.cpp @@ -205,6 +205,12 @@ bool Dma::reset() Dma::~Dma() { + // Unmap memory in our ownership, MemoryBlock gets deleted and removed from + // graph by this destructor as well. + if (hasScatterGather()) { + card->unmapMemoryBlock(*sgRingTx); + card->unmapMemoryBlock(*sgRingRx); + } Dma::reset(); }