From c0cfb425afc39b736a7ac28f6608b00338f708df Mon Sep 17 00:00:00 2001 From: IgnoreWarnings Date: Thu, 8 Aug 2024 15:50:53 +0000 Subject: [PATCH] add device and driver classes Signed-off-by: IgnoreWarnings --- fpga/include/villas/fpga/device/device.hpp | 59 +++++++++++++++++ fpga/include/villas/fpga/device/driver.hpp | 42 ++++++++++++ fpga/include/villas/fpga/device/ip_device.hpp | 26 ++++++++ fpga/include/villas/fpga/device/utils.hpp | 16 +++++ fpga/lib/device/driver.cpp | 24 +++++++ fpga/lib/device/ip_device.cpp | 66 +++++++++++++++++++ fpga/lib/device/utils.cpp | 45 +++++++++++++ 7 files changed, 278 insertions(+) create mode 100644 fpga/include/villas/fpga/device/device.hpp create mode 100644 fpga/include/villas/fpga/device/driver.hpp create mode 100644 fpga/include/villas/fpga/device/ip_device.hpp create mode 100644 fpga/include/villas/fpga/device/utils.hpp create mode 100644 fpga/lib/device/driver.cpp create mode 100644 fpga/lib/device/ip_device.cpp create mode 100644 fpga/lib/device/utils.cpp diff --git a/fpga/include/villas/fpga/device/device.hpp b/fpga/include/villas/fpga/device/device.hpp new file mode 100644 index 000000000..451648d4f --- /dev/null +++ b/fpga/include/villas/fpga/device/device.hpp @@ -0,0 +1,59 @@ +/* Device + * + * Author: Pascal Bauer + * + * SPDX-FileCopyrightText: 2023-2024 Pascal Bauer + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include + +class Device { +private: + static constexpr char PROBE_DEFAULT[] = "/sys/bus/platform/drivers_probe"; + +public: + const std::filesystem::path path; + +private: + const std::filesystem::path probe_path; + +public: + Device(const std::filesystem::path path) + : Device(path, std::filesystem::path(PROBE_DEFAULT)){}; + Device(const std::filesystem::path path, + const std::filesystem::path probe_path) + : path(path), probe_path(probe_path){}; + + std::string name() const { + size_t pos = path.u8string().rfind('/'); + return path.u8string().substr(pos + 1); + } + + std::optional driver() const { + std::filesystem::path driver_symlink = + this->path / std::filesystem::path("driver"); + + try { + std::filesystem::read_symlink(driver_symlink); + } catch (std::filesystem::filesystem_error &e) { + return std::nullopt; + } + + std::filesystem::path driver_path = + std::filesystem::canonical(driver_symlink); + return Driver(driver_path); + }; + + void driver_override(const Driver &driver) const { + write_to_file(driver.name(), + this->path / std::filesystem::path("driver_override")); + }; + + void probe() const { write_to_file(this->name(), this->probe_path); }; +}; diff --git a/fpga/include/villas/fpga/device/driver.hpp b/fpga/include/villas/fpga/device/driver.hpp new file mode 100644 index 000000000..4733f3096 --- /dev/null +++ b/fpga/include/villas/fpga/device/driver.hpp @@ -0,0 +1,42 @@ +/* Driver + * + * Author: Pascal Bauer + * + * SPDX-FileCopyrightText: 2023-2024 Pascal Bauer + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +class Device; + +class Driver { +private: + static constexpr char BIND_DEFAULT[] = "bind"; + static constexpr char UNBIND_DEFAULT[] = "unbind"; + +public: + const std::filesystem::path path; + +private: + const std::filesystem::path bind_path; + const std::filesystem::path unbind_path; + const std::filesystem::path probe_path; + +public: + Driver(const std::filesystem::path path) + : Driver(path, path / std::filesystem::path(BIND_DEFAULT), + path / std::filesystem::path(UNBIND_DEFAULT)){}; + + Driver(const std::filesystem::path path, + const std::filesystem::path bind_path, + const std::filesystem::path unbind_path) + : path(path), bind_path(bind_path), unbind_path(unbind_path){}; + + std::string name() const; + void bind(const Device &device) const; + void unbind(const Device &device) const; +}; diff --git a/fpga/include/villas/fpga/device/ip_device.hpp b/fpga/include/villas/fpga/device/ip_device.hpp new file mode 100644 index 000000000..e94b0b69d --- /dev/null +++ b/fpga/include/villas/fpga/device/ip_device.hpp @@ -0,0 +1,26 @@ +/* IpDevice + * + * Author: Pascal Bauer + * + * SPDX-FileCopyrightText: 2023-2024 Pascal Bauer + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +class IpDevice : public Device { +public: + static IpDevice from(const std::filesystem::path unsafe_path); + static bool is_path_valid(const std::filesystem::path unsafe_path); + +private: + IpDevice(const std::filesystem::path valid_path) : Device(valid_path){}; + +public: + std::string ip_name() const; + size_t addr() const; + int iommu_group() const; +}; diff --git a/fpga/include/villas/fpga/device/utils.hpp b/fpga/include/villas/fpga/device/utils.hpp new file mode 100644 index 000000000..9567fa86a --- /dev/null +++ b/fpga/include/villas/fpga/device/utils.hpp @@ -0,0 +1,16 @@ +/* Utils + * + * Author: Pascal Bauer + * + * SPDX-FileCopyrightText: 2023-2024 Pascal Bauer + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include + +void write_to_file(std::string data, const std::filesystem::path file); +std::vector read_names_in_directory(const std::string &name); diff --git a/fpga/lib/device/driver.cpp b/fpga/lib/device/driver.cpp new file mode 100644 index 000000000..8065e2497 --- /dev/null +++ b/fpga/lib/device/driver.cpp @@ -0,0 +1,24 @@ +/* Driver + * + * Author: Pascal Bauer + * + * SPDX-FileCopyrightText: 2023-2024 Pascal Bauer + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +std::string Driver::name() const { + size_t pos = path.u8string().rfind('/'); + return path.u8string().substr(pos + 1); +} + +void Driver::bind(const Device &device) const { + write_to_file(device.name(), this->bind_path); +}; + +void Driver::unbind(const Device &device) const { + write_to_file(device.name(), this->unbind_path); +}; + diff --git a/fpga/lib/device/ip_device.cpp b/fpga/lib/device/ip_device.cpp new file mode 100644 index 000000000..b9b2d3caf --- /dev/null +++ b/fpga/lib/device/ip_device.cpp @@ -0,0 +1,66 @@ +/* IpDevice + * + * Author: Pascal Bauer + * + * SPDX-FileCopyrightText: 2023-2024 Pascal Bauer + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +IpDevice IpDevice::from(const std::filesystem::path unsafe_path) { + if (!is_path_valid(unsafe_path)) + throw std::runtime_error( + "Path \"" + unsafe_path.u8string() + + "\" failed validation as IpDevicePath \"[adress in hex].[name]\". "); + return IpDevice(unsafe_path); +} + +bool IpDevice::is_path_valid(const std::filesystem::path unsafe_path) { + // Split the string at last slash + int pos = unsafe_path.u8string().rfind('/'); + std::string assumed_device_name = unsafe_path.u8string().substr(pos + 1); + + // Match format of hexaddr.devicename + if (!std::regex_match(assumed_device_name, + std::regex(R"([0-9A-Fa-f]+\..*)"))) { + return false; + } + + return true; +} + +std::string IpDevice::ip_name() const { + int pos = name().find('.'); + return name().substr(pos + 1); +} + +size_t IpDevice::addr() const { + size_t pos = name().find('.'); + std::string addr_hex = name().substr(0, pos); + + // convert from hex string to number + std::stringstream ss; + ss << std::hex << addr_hex; + size_t addr = 0; + ss >> addr; + + return addr; +} + +int IpDevice::iommu_group() const { + std::filesystem::path symlink = + std::filesystem::path(this->path.u8string() + "/iommu_group"); + + std::filesystem::path link; + link = std::filesystem::read_symlink(symlink); + + std::string delimiter = "iommu_groups/"; + int pos = link.u8string().find(delimiter); + int iommu_group = std::stoi(link.u8string().substr(pos + delimiter.length())); + return iommu_group; +} diff --git a/fpga/lib/device/utils.cpp b/fpga/lib/device/utils.cpp new file mode 100644 index 000000000..206a0c51e --- /dev/null +++ b/fpga/lib/device/utils.cpp @@ -0,0 +1,45 @@ +/* Utils + * + * Author: Pascal Bauer + * + * SPDX-FileCopyrightText: 2023-2024 Pascal Bauer + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +void write_to_file(std::string data, const std::filesystem::path file) { + villas::logging.get("Filewriter")->debug("{} > {}", data, file.u8string()); + std::ofstream outputFile(file.u8string()); + + if (outputFile.is_open()) { + // Write to file + outputFile << data; + outputFile.close(); + } else { + throw std::filesystem::filesystem_error("Cannot open outputfile", + std::error_code()); + } +} + +std::vector read_names_in_directory(const std::string &name) { + DIR *directory = opendir(name.c_str()); + + struct dirent *dp; + std::vector names; + dp = readdir(directory); + while (dp != NULL) { + auto name = std::string(dp->d_name); + if (name != "." && name != "..") { + names.push_back(name); + } + dp = readdir(directory); + } + closedir(directory); + return names; +} \ No newline at end of file