Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions common/include/villas/kernel/devices/pci_device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

#include <villas/log.hpp>

#include <villas/kernel/devices/device.hpp>

namespace villas {
namespace kernel {
namespace devices {
Expand Down Expand Up @@ -58,7 +60,11 @@ struct Region {
unsigned long long flags;
};

class PciDevice {
class PciDevice : public Device {
private:
static constexpr char PROBE_DEFAULT[] = "/sys/bus/pci/drivers_probe";
static constexpr char OVERRIDE_DEFAULT[] = "driver_override";

public:
PciDevice(Id i, Slot s) : id(i), slot(s), log(Log::get("kernel:pci")) {}

Expand All @@ -68,15 +74,17 @@ class PciDevice {

bool operator==(const PciDevice &other);

// Get currently loaded driver for device
std::string getDriver() const;
// Implement device interface
std::optional<std::unique_ptr<Driver>> driver() const override;
std::optional<int> iommu_group() const override;
std::string name() const override;
std::filesystem::path override_path() const override;
std::filesystem::path path() const override;
void probe() const override;

// Bind a new LKM to the PCI device
bool attachDriver(const std::string &driver) const;

// Return the IOMMU group of this PCI device or -1 if the device is not in a group
int getIommuGroup() const;

std::list<Region> getRegions() const;

// Write 32-bit BAR value from to the PCI configuration space
Expand Down
47 changes: 40 additions & 7 deletions common/lib/kernel/devices/pci_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@

#include <villas/config.hpp>
#include <villas/exceptions.hpp>
#include <villas/kernel/devices/linux_driver.hpp>
#include <villas/kernel/devices/pci_device.hpp>
#include <villas/utils.hpp>

using namespace villas::kernel::devices;
using villas::utils::write_to_file;

#define PCI_BASE_ADDRESS_N(n) (PCI_BASE_ADDRESS_0 + sizeof(uint32_t) * (n))

Expand Down Expand Up @@ -311,8 +313,7 @@ std::list<Region> PciDevice::getRegions() const {

return regions;
}

std::string PciDevice::getDriver() const {
std::optional<std::unique_ptr<Driver>> PciDevice::driver() const {
int ret;
char sysfs[1024], syml[1024];
memset(syml, 0, sizeof(syml));
Expand All @@ -323,13 +324,15 @@ std::string PciDevice::getDriver() const {
struct stat st;
ret = stat(sysfs, &st);
if (ret)
return "";
return std::nullopt;

ret = readlink(sysfs, syml, sizeof(syml));
if (ret < 0)
throw SystemError("Failed to follow link: {}", sysfs);

return basename(syml);
auto driver = std::make_optional(std::make_unique<LinuxDriver>(
"/sys/bus/pci/drivers/" + std::string(basename(syml))));
return driver;
}

bool PciDevice::attachDriver(const std::string &driver) const {
Expand Down Expand Up @@ -423,7 +426,7 @@ void PciDevice::writeBar(uint32_t addr, unsigned barNum) {
file.write(reinterpret_cast<char *>(&addr), sizeof(addr));
}

int PciDevice::getIommuGroup() const {
std::optional<int> PciDevice::iommu_group() const {
int ret;
char *group;

Expand All @@ -437,11 +440,11 @@ int PciDevice::getIommuGroup() const {

ret = readlink(sysfs, link, sizeof(link));
if (ret < 0)
return -1;
return std::nullopt;

group = basename(link);

return atoi(group);
return std::make_optional(atoi(group));
}

std::fstream PciDevice::openSysFs(const std::string &subPath,
Expand All @@ -457,3 +460,33 @@ std::fstream PciDevice::openSysFs(const std::string &subPath,

return file;
}

// TODO: test
std::string PciDevice::name() const {
char sysfs[1024];

snprintf(sysfs, sizeof(sysfs), "%04x:%02x:%02x.%x", slot.domain, slot.bus,
slot.device, slot.function);

return std::string(sysfs);
}

// TODO: test
std::filesystem::path PciDevice::path() const {
char sysfs[1024];

snprintf(sysfs, sizeof(sysfs), "%04x:%02x:%02x.%x", slot.domain, slot.bus,
slot.device, slot.function);

return sysfs;
}

// TODO: test
std::filesystem::path PciDevice::override_path() const {

return this->path() / OVERRIDE_DEFAULT;
}

void PciDevice::probe() const {
write_to_file(this->name(), this->PROBE_DEFAULT);
}
4 changes: 2 additions & 2 deletions common/lib/kernel/vfio_container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ std::shared_ptr<Device> Container::attachDevice(devices::PciDevice &pdev) {
throw RuntimeError("Failed to load kernel driver: vfio_pci");

// Bind PCI card to vfio-pci driver if not already bound
if (pdev.getDriver() != kernelDriver) {
if ( !(pdev.driver().has_value()) || pdev.driver().value()->name() != kernelDriver) {
log->debug("Bind PCI card to kernel driver '{}'", kernelDriver);
pdev.attachDriver(kernelDriver);
}
Expand All @@ -215,7 +215,7 @@ std::shared_ptr<Device> Container::attachDevice(devices::PciDevice &pdev) {
}

// Get IOMMU group of device
int index = isIommuEnabled() ? pdev.getIommuGroup() : 0;
int index = isIommuEnabled() ? pdev.iommu_group().value() : 0;
if (index < 0) {
ret = kernel::getCmdlineParam("intel_iommu", iommu_state,
sizeof(iommu_state));
Expand Down
62 changes: 62 additions & 0 deletions etc/examples/nodes/miob.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# SPDX-FileCopyrightText: 2025 Institute for Automation of Complex Power Systems, RWTH Aachen University
# SPDX-License-Identifier: Apache-2.0

logging = {
level = "info"
}

fpgas = {
zcu106 = {
interface = "platform",
ips = "../../fpga/zcu106-dino/zcu106-dino.json",
#ignore_ips = ["dino_dinoif_dac_0", "dino_dinoif_fast_nologic_0"], # Optionally ignore IPs
polling = true,
}
}

nodes = {
fpga_0 = {
type = "fpga",
card = "zcu106"
# connect = ["dino<->dma"] # Alternate HW Loopback
connect = ["0<->dma"] # Loopback
lowLatencyMode = false,
},

signal_gen_0 = {
type = "signal.v2",
realtime = true,
rate = 2,
in = {
signals = (
{
name = "sine.v2",
signal = "sine",
frequency = 0.1,
amplitude = 10,
}
)
},
}
}

paths = (
{
in = "signal_gen_0"
out = "fpga_0"
hooks = (
{
type = "print"
})

},
{
in = "fpga_0"
hooks = (
{
type = "print"
}
)
}
)