Commit dc484e35 authored by Daniel Krebs's avatar Daniel Krebs
Browse files

common/memory: add host DMA memory allocator using udmabuf

parent 857f2ac1
......@@ -7,3 +7,6 @@
[submodule "lib/gpu/gdrcopy"]
path = lib/gpu/gdrcopy
url = https://github.com/daniel-k/gdrcopy.git
[submodule "thirdparty/udmabuf"]
path = thirdparty/udmabuf
url = https://github.com/ikwzm/udmabuf
......@@ -245,4 +245,41 @@ private:
static HostRamAllocator allocator;
};
class HostDmaRam {
private:
static std::string
getUdmaBufName(int num);
static std::string
getUdmaBufBasePath(int num);
static size_t
getUdmaBufBufSize(int num);
static uintptr_t
getUdmaBufPhysAddr(int num);
public:
class HostDmaRamAllocator : public LinearAllocator {
public:
HostDmaRamAllocator(int num);
virtual ~HostDmaRamAllocator();
std::string getName() const
{ return getUdmaBufName(num); }
private:
int num;
};
static HostDmaRamAllocator&
getAllocator(int num = 0);
private:
static std::map<int, std::unique_ptr<HostDmaRamAllocator>> allocators;
};
} // namespace villas
#include <sys/mman.h>
#include <unistd.h>
#include <sstream>
#include <fstream>
#include "memory.hpp"
namespace villas {
......@@ -140,4 +143,122 @@ HostRam::HostRamAllocator::HostRamAllocator() :
};
}
std::map<int, std::unique_ptr<HostDmaRam::HostDmaRamAllocator>>
HostDmaRam::allocators;
HostDmaRam::HostDmaRamAllocator::HostDmaRamAllocator(int num) :
LinearAllocator(MemoryManager::get().getOrCreateAddressSpace(getUdmaBufName(num)), getUdmaBufBufSize(num)),
num(num)
{
auto& mm = MemoryManager::get();
logger = loggerGetOrCreate(getName());
if(getSize() == 0) {
logger->error("Zero-sized DMA buffer not supported, is the kernel module loaded?");
throw std::bad_alloc();
}
const uintptr_t base = getUdmaBufPhysAddr(num);
mm.createMapping(base, 0, getSize(), getName() + "-PCI",
mm.getPciAddressSpace(), getAddrSpaceId());
const auto bufPath = std::string("/dev/") + getUdmaBufName(num);
const int bufFd = open(bufPath.c_str(), O_RDWR | O_SYNC);
if(bufFd != -1) {
void* buf = mmap(nullptr, getSize(), PROT_READ|PROT_WRITE, MAP_SHARED, bufFd, 0);
close(bufFd);
if(buf != MAP_FAILED) {
mm.createMapping(reinterpret_cast<uintptr_t>(buf), 0, getSize(),
getName() + "-VA",
mm.getProcessAddressSpace(), getAddrSpaceId());
} else {
logger->warn("Cannot map {}", bufPath);
}
} else {
logger->warn("Cannot open {}", bufPath);
}
logger->info("Mapped {} of size {} bytes", bufPath, getSize());
}
HostDmaRam::HostDmaRamAllocator::~HostDmaRamAllocator()
{
auto& mm = MemoryManager::get();
void* baseVirt;
try {
auto translation = mm.getTranslationFromProcess(getAddrSpaceId());
baseVirt = reinterpret_cast<void*>(translation.getLocalAddr(0));
} catch(const std::out_of_range&) {
// not mapped, nothing to do
return;
}
logger->debug("Unmapping {}", getName());
// try to unmap it
if(::munmap(baseVirt, getSize()) != 0) {
logger->warn("munmap() failed for {:p} of size {:#x}",
baseVirt, getSize());
}
}
std::string
HostDmaRam::getUdmaBufName(int num)
{
std::stringstream name;
name << "udmabuf" << num;
return name.str();
}
std::string
HostDmaRam::getUdmaBufBasePath(int num)
{
std::stringstream path;
path << "/sys/class/udmabuf/udmabuf" << num << "/";
return path.str();
}
size_t
HostDmaRam::getUdmaBufBufSize(int num)
{
std::fstream s(getUdmaBufBasePath(num) + "size", s.in);
if(s.is_open()) {
std::string line;
if(std::getline(s, line)) {
return std::strtoul(line.c_str(), nullptr, 10);
}
}
return 0;
}
uintptr_t
HostDmaRam::getUdmaBufPhysAddr(int num)
{
std::fstream s(getUdmaBufBasePath(num) + "phys_addr", s.in);
if(s.is_open()) {
std::string line;
if(std::getline(s, line)) {
return std::strtoul(line.c_str(), nullptr, 16);
}
}
return UINTPTR_MAX;
}
HostDmaRam::HostDmaRamAllocator&HostDmaRam::getAllocator(int num)
{
auto& allocator = allocators[num];
if(not allocator) {
allocator = std::make_unique<HostDmaRamAllocator>(num);
}
return *allocator;
}
} // namespace villas
Subproject commit 65762ca3333cb230e3b80ecf4cb5e605390474f2
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment