From 94ba899b21efd06ba15141881a5ea7cbc6229da3 Mon Sep 17 00:00:00 2001 From: Daniel Krebs Date: Tue, 15 May 2018 11:22:29 +0200 Subject: [PATCH] vfio: track if IOMMU is enabled to prepare for non-IOMMU mode --- fpga/include/villas/kernel/vfio.hpp | 4 ++++ fpga/lib/kernel/vfio.cpp | 37 ++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/fpga/include/villas/kernel/vfio.hpp b/fpga/include/villas/kernel/vfio.hpp index 9f794baf5..0e3fc453f 100644 --- a/fpga/include/villas/kernel/vfio.hpp +++ b/fpga/include/villas/kernel/vfio.hpp @@ -135,6 +135,9 @@ public: /** munmap() a region which has been mapped by vfio_map_region() */ bool memoryUnmap(uintptr_t phys, size_t length); + bool isIommuEnabled() const + { return this->hasIommu; } + private: VfioGroup& getOrAttachGroup(int index); @@ -143,6 +146,7 @@ private: int version; int extensions; uint64_t iova_next; /**< Next free IOVA address */ + bool hasIommu; /// All groups bound to this container std::list> groups; diff --git a/fpga/lib/kernel/vfio.cpp b/fpga/lib/kernel/vfio.cpp index dcc29c2e8..7d29c9ee8 100644 --- a/fpga/lib/kernel/vfio.cpp +++ b/fpga/lib/kernel/vfio.cpp @@ -108,12 +108,25 @@ VfioContainer::VfioContainer() logger->error("Failed to get VFIO extensions"); throw std::exception(); } - else if (ret > 0) + else if (ret > 0) { extensions |= (1 << i); + } } - logger->debug("Version: {:#x}", version); + hasIommu = false; + + if(not (extensions & (1 << VFIO_NOIOMMU_IOMMU))) { + if(not (extensions & (1 << VFIO_TYPE1_IOMMU))) { + logger->error("No supported IOMMU extension found"); + throw std::exception(); + } else { + hasIommu = true; + } + } + + logger->debug("Version: {:#x}", version); logger->debug("Extensions: {:#x}", extensions); + logger->debug("IOMMU: {}", hasIommu ? "yes" : "no"); } @@ -319,6 +332,11 @@ VfioContainer::memoryMap(uintptr_t virt, uintptr_t phys, size_t length) { int ret; + if(not hasIommu) { + logger->error("DMA mapping not supported without IOMMU"); + return UINTPTR_MAX; + } + if (length & 0xFFF) { length += 0x1000; length &= ~0xFFF; @@ -363,6 +381,10 @@ VfioContainer::memoryUnmap(uintptr_t phys, size_t length) { int ret; + if(not hasIommu) { + return true; + } + struct vfio_iommu_type1_dma_unmap dmaUnmap; dmaUnmap.argsz = sizeof(struct vfio_iommu_type1_dma_unmap); dmaUnmap.flags = 0; @@ -554,6 +576,11 @@ VfioDevice::pciHotReset() free(reset); free(reset_info); + if(not success and not group.container->isIommuEnabled()) { + logger->info("PCI hot reset failed, but this is expected without IOMMU"); + return true; + } + return success; } @@ -740,7 +767,11 @@ VfioGroup::attach(int containerFd, int groupIndex) } /* Set IOMMU type */ - ret = ioctl(containerFd, VFIO_SET_IOMMU, VFIO_TYPE1_IOMMU); + int iommu_type = container.isIommuEnabled() ? + VFIO_TYPE1_IOMMU : + VFIO_NOIOMMU_IOMMU; + + ret = ioctl(containerFd, VFIO_SET_IOMMU, iommu_type); if (ret < 0) { logger->error("Failed to set IOMMU type of container: {}", ret); return nullptr;