/** FPGA card * * This class represents a FPGA device. * * Author: Steffen Vogel * Author: Daniel Krebs * SPDX-FileCopyrightText: 2017 Institute for Automation of Complex Power * Systems, EONERC SPDX-License-Identifier: Apache-2.0 *********************************************************************************/ #include using namespace villas; using namespace villas::fpga; Card::~Card() { } std::shared_ptr Card::lookupIp(const std::string &name) const { for(auto &ip : ips) { if(*ip == name) { return ip; } } return nullptr; } std::shared_ptr Card::lookupIp(const Vlnv &vlnv) const { for(auto &ip : ips) { if(*ip == vlnv) { return ip; } } return nullptr; } std::shared_ptr Card::lookupIp(const ip::IpIdentifier &id) const { for(auto &ip : ips) { if(*ip == id) { return ip; } } return nullptr; } bool Card::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(); 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 Card::mapMemoryBlock(const MemoryBlock &block) { if(not vfioContainer->isIommuEnabled()) { logger->warn("VFIO mapping not supported without IOMMU"); return false; } auto &mm = MemoryManager::get(); const auto &addrSpaceId = block.getAddrSpaceId(); if(memoryBlocksMapped.find(addrSpaceId) != memoryBlocksMapped.end()) // Block already mapped return true; else logger->debug("Create VFIO mapping for {}", addrSpaceId); auto translationFromProcess = mm.getTranslationFromProcess(addrSpaceId); uintptr_t processBaseAddr = translationFromProcess.getLocalAddr(0); uintptr_t iovaAddr = vfioContainer->memoryMap(processBaseAddr, UINTPTR_MAX, block.getSize()); if(iovaAddr == UINTPTR_MAX) { logger->error("Cannot map memory at {:#x} of size {:#x}", processBaseAddr, block.getSize()); return false; } mm.createMapping(iovaAddr, 0, block.getSize(), "VFIO-D2H", this->addrSpaceIdDeviceToHost, addrSpaceId); // Remember that this block has already been mapped for later memoryBlocksMapped.insert(addrSpaceId); return true; }