diff --git a/common/include/villas/kernel/kernel.hpp b/common/include/villas/kernel/kernel.hpp index 1941214d1..87d7e87e4 100644 --- a/common/include/villas/kernel/kernel.hpp +++ b/common/include/villas/kernel/kernel.hpp @@ -15,25 +15,24 @@ namespace villas { namespace kernel { -/** Get the version of the kernel. */ +// Get the version of the kernel. utils::Version getVersion(); -/** Get number of reserved hugepages. */ +// Get number of reserved hugepages. int getNrHugepages(); -/** Set number of reserved hugepages. */ +// Set number of reserved hugepages. int setNrHugepages(int nr); -/** Get kernel cmdline parameter - * - * See https://www.kernel.org/doc/Documentation/kernel-parameters.txt - * - * @param param The cmdline parameter to look for. - * @param buf The string buffer to which the parameter value will be copied to. - * @param len The length of the buffer \p value - * @retval 0 Parameter \p key was found and value was copied to \p value - * @reval <>0 Kernel was not booted with parameter \p key - */ +// Get kernel cmdline parameter +// +// See https://www.kernel.org/doc/Documentation/kernel-parameters.txt +// +// @param param The cmdline parameter to look for. +// @param buf The string buffer to which the parameter value will be copied to. +// @param len The length of the buffer \p value +// @retval 0 Parameter \p key was found and value was copied to \p value +// @reval <>0 Kernel was not booted with parameter \p key int getCmdlineParam(const char *param, char *buf, size_t len); /** Checks if a kernel module is loaded @@ -44,25 +43,25 @@ int getCmdlineParam(const char *param, char *buf, size_t len); */ int isModuleLoaded(const char *module); -/** Load kernel module via modprobe */ +// Load kernel module via modprobe int loadModule(const char *module); -/** Set parameter of loaded kernel module */ +// Set parameter of loaded kernel module int setModuleParam(const char *module, const char *param, const char *value); -/** Get cacheline size in bytes */ +// Get cacheline size in bytes int getCachelineSize(); -/** Get the size of a standard page in bytes. */ +// Get the size of a standard page in bytes. int getPageSize(); -/** Get the size of a huge page in bytes. */ +// Get the size of a huge page in bytes. int getHugePageSize(); -/** Get CPU base frequency */ +// Get CPU base frequency int get_cpu_frequency(uint64_t *freq); -/** Set SMP affinity of IRQ */ +// Set SMP affinity of IRQ int setIRQAffinity(unsigned irq, uintmax_t aff , uintmax_t *old); } // namespace villas diff --git a/common/include/villas/kernel/pci.hpp b/common/include/villas/kernel/pci.hpp index 757e87219..cc34aab4b 100644 --- a/common/include/villas/kernel/pci.hpp +++ b/common/include/villas/kernel/pci.hpp @@ -31,8 +31,7 @@ public: class_code(cc) { } - bool - operator==(const Id &i); + bool operator==(const Id &i); unsigned int vendor; unsigned int device; @@ -50,8 +49,7 @@ public: function(fcn) { } - bool - operator==(const Slot &s); + bool operator==(const Slot &s); unsigned int domain; unsigned int bus; @@ -87,35 +85,29 @@ public: bool operator==(const Device &other); - /** Get currently loaded driver for device */ - std::string - getDriver() const; + // Get currently loaded driver for device. + std::string getDriver() const; - /** Bind a new LKM to the PCI device */ - bool - attachDriver(const std::string &driver) const; + // 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; + // Return the IOMMU group of this PCI device or -1 if the device is not in a group. + int getIommuGroup() const; - std::list - getRegions() const; + std::list getRegions() const; - /** Write 32-bit BAR value from to the PCI configuration space */ + // Write 32-bit BAR value from to the PCI configuration space bool writeBar(uint32_t new_bar); - /** If BAR values in config space and in the kernel do not match, rewrite - * the BAR value of the kernel to PCIe config space. - */ + // If BAR values in config space and in the kernel do not match, rewrite + // the BAR value of the kernel to PCIe config space. bool rewriteBar(); - /** Read 32-bit BAR value from the PCI configuration space */ + // Read 32-bit BAR value from the PCI configuration space. bool readBar(uint32_t &bar) const; - /** Read 32-bit BAR value from the devices resource file. This is what the kernel - * thinks the BAR should be. - */ + // Read 32-bit BAR value from the devices resource file. This is what the kernel + // thinks the BAR should be. bool readHostBar(uint32_t &bar) const; Id id; @@ -126,20 +118,16 @@ private: class DeviceList : public std::list> { public: - /** Initialize Linux PCI handle. - * - * This search for all available PCI devices under /sys/bus/pci - */ + // Initialize Linux PCI handle. + // + // This search for all available PCI devices under /sys/bus/pci DeviceList(); - DeviceList::value_type - lookupDevice(const Slot &s); + DeviceList::value_type lookupDevice(const Slot &s); - DeviceList::value_type - lookupDevice(const Id &i); + DeviceList::value_type lookupDevice(const Id &i); - DeviceList::value_type - lookupDevice(const Device &f); + DeviceList::value_type lookupDevice(const Device &f); }; } // namespace pci diff --git a/common/include/villas/kernel/rt.hpp b/common/include/villas/kernel/rt.hpp index 37e9647a8..efd1ca9dd 100644 --- a/common/include/villas/kernel/rt.hpp +++ b/common/include/villas/kernel/rt.hpp @@ -22,13 +22,12 @@ void setThreadAffinity(pthread_t thread, int affinity); void setPriority(int priority); -/** Checks for realtime (PREEMPT_RT) patched kernel. - * - * See https://rt.wiki.kernel.org - * - * @retval true Kernel is patched. - * @retval false Kernel is not patched. - */ +// Checks for realtime (PREEMPT_RT) patched kernel. +// +// See https://rt.wiki.kernel.org +// +// @retval true Kernel is patched. +// @retval false Kernel is not patched. bool isPreemptible(); } // namespace villas diff --git a/common/include/villas/kernel/vfio_container.hpp b/common/include/villas/kernel/vfio_container.hpp index 4d40a4d68..f3170d46b 100644 --- a/common/include/villas/kernel/vfio_container.hpp +++ b/common/include/villas/kernel/vfio_container.hpp @@ -51,13 +51,12 @@ public: std::shared_ptr attachDevice(const std::string& name, int groupIndex); std::shared_ptr attachDevice(pci::Device &pdev); - /** - * @brief Map VM to an IOVA, which is accessible by devices in the container - * @param virt virtual address of memory - * @param phys IOVA where to map @p virt, -1 to use VFIO internal allocator - * @param length size of memory region in bytes - * @return IOVA address, UINTPTR_MAX on failure - */ + // Map VM to an IOVA, which is accessible by devices in the container + // + // @param virt virtual address of memory + // @param phys IOVA where to map @p virt, -1 to use VFIO internal allocator + // @param length size of memory region in bytes + // @return IOVA address, UINTPTR_MAX on failure uintptr_t memoryMap(uintptr_t virt, uintptr_t phys, size_t length); /** munmap() a region which has been mapped by vfio_map_region() */ @@ -75,7 +74,7 @@ private: int version; std::array extensions; - uint64_t iova_next; /**< Next free IOVA address */ + uint64_t iova_next; // Next free IOVA address bool hasIommu; // All groups bound to this container diff --git a/common/include/villas/kernel/vfio_device.hpp b/common/include/villas/kernel/vfio_device.hpp index 42a4177a6..be2bf7898 100644 --- a/common/include/villas/kernel/vfio_device.hpp +++ b/common/include/villas/kernel/vfio_device.hpp @@ -22,7 +22,6 @@ #include #include - namespace villas { namespace kernel { namespace vfio { diff --git a/common/lib/kernel/pci.cpp b/common/lib/kernel/pci.cpp index 29a4e21a8..8f3203476 100644 --- a/common/lib/kernel/pci.cpp +++ b/common/lib/kernel/pci.cpp @@ -35,8 +35,7 @@ DeviceList::DeviceList() if (!dp) throw SystemError("Failed to detect PCI devices"); - while ((e = readdir(dp))) - { + while ((e = readdir(dp))) { // Ignore special entries if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) @@ -45,8 +44,7 @@ DeviceList::DeviceList() Id id; Slot slot; - struct - { + struct { const char *s; unsigned int *p; } map[] = { @@ -54,8 +52,7 @@ DeviceList::DeviceList() {"device", &id.device}}; // Read vendor & device id - for (int i = 0; i < 2; i++) - { + for (int i = 0; i < 2; i++) { snprintf(path, sizeof(path), "%s/bus/pci/devices/%s/%s", SYSFS_PATH, e->d_name, map[i].s); f = fopen(path, "r"); @@ -80,22 +77,19 @@ DeviceList::DeviceList() closedir(dp); } -DeviceList::value_type -DeviceList::lookupDevice(const Slot &s) +DeviceList::value_type DeviceList::lookupDevice(const Slot &s) { return *std::find_if(begin(), end(), [s](const DeviceList::value_type &d) { return d->slot == s; }); } -DeviceList::value_type -DeviceList::lookupDevice(const Id &i) +DeviceList::value_type DeviceList::lookupDevice(const Id &i) { return *std::find_if(begin(), end(), [i](const DeviceList::value_type &d) { return d->id == i; }); } -DeviceList::value_type -DeviceList::lookupDevice(const Device &d) +DeviceList::value_type DeviceList::lookupDevice(const Device &d) { auto dev = std::find_if(begin(), end(), [d](const DeviceList::value_type &e) { return *e == d; }); @@ -103,9 +97,10 @@ DeviceList::lookupDevice(const Device &d) return dev == end() ? value_type() : *dev; } -Id::Id(const std::string &str) : vendor(0), - device(0), - class_code(0) +Id::Id(const std::string &str) : + vendor(0), + device(0), + class_code(0) { char *s, *c, *e; char *tmp = strdup(str.c_str()); @@ -114,19 +109,16 @@ Id::Id(const std::string &str) : vendor(0), return; s = strchr(tmp, ':'); - if (!s) - { + if (!s) { free(tmp); throw RuntimeError("Failed to parse PCI id: ':' expected", str); } *s++ = 0; - if (tmp[0] && strcmp(tmp, "*")) - { + if (tmp[0] && strcmp(tmp, "*")) { long int x = strtol(tmp, &e, 16); - if ((e && *e) || (x < 0 || x > 0xffff)) - { + if ((e && *e) || (x < 0 || x > 0xffff)) { free(tmp); throw RuntimeError("Failed to parse PCI id: {}: Invalid vendor id", str); } @@ -138,11 +130,9 @@ Id::Id(const std::string &str) : vendor(0), if (c) *c++ = 0; - if (s[0] && strcmp(s, "*")) - { + if (s[0] && strcmp(s, "*")) { long int x = strtol(s, &e, 16); - if ((e && *e) || (x < 0 || x > 0xffff)) - { + if ((e && *e) || (x < 0 || x > 0xffff)) { free(tmp); throw RuntimeError("Failed to parse PCI id: {}: Invalid device id", str); } @@ -150,12 +140,10 @@ Id::Id(const std::string &str) : vendor(0), device = x; } - if (c && c[0] && strcmp(s, "*")) - { + if (c && c[0] && strcmp(s, "*")) { long int x = strtol(c, &e, 16); - if ((e && *e) || (x < 0 || x > 0xffff)) - { + if ((e && *e) || (x < 0 || x > 0xffff)) { free(tmp); throw RuntimeError("Failed to parse PCI id: {}: Invalid class code", str); } @@ -176,10 +164,11 @@ bool Id::operator==(const Id &i) return true; } -Slot::Slot(const std::string &str) : domain(0), - bus(0), - device(0), - function(0) +Slot::Slot(const std::string &str) : + domain(0), + bus(0), + device(0), + function(0) { char *tmp = strdup(str.c_str()); char *colon = strrchr(tmp, ':'); @@ -187,22 +176,18 @@ Slot::Slot(const std::string &str) : domain(0), char *mid = tmp; char *e, *buss, *colon2; - if (colon) - { + if (colon) { *colon++ = 0; mid = colon; colon2 = strchr(tmp, ':'); - if (colon2) - { + if (colon2) { *colon2++ = 0; buss = colon2; - if (tmp[0] && strcmp(tmp, "*")) - { + if (tmp[0] && strcmp(tmp, "*")) { long int x = strtol(tmp, &e, 16); - if ((e && *e) || (x < 0 || x > 0x7fffffff)) - { + if ((e && *e) || (x < 0 || x > 0x7fffffff)) { free(tmp); throw RuntimeError("Failed to parse PCI slot: {}: invalid domain", str); } @@ -213,11 +198,9 @@ Slot::Slot(const std::string &str) : domain(0), else buss = tmp; - if (buss[0] && strcmp(buss, "*")) - { + if (buss[0] && strcmp(buss, "*")) { long int x = strtol(buss, &e, 16); - if ((e && *e) || (x < 0 || x > 0xff)) - { + if ((e && *e) || (x < 0 || x > 0xff)) { free(tmp); throw RuntimeError("Failed to parse PCI slot: {}: invalid bus", str); } @@ -229,12 +212,10 @@ Slot::Slot(const std::string &str) : domain(0), if (dot) *dot++ = 0; - if (mid[0] && strcmp(mid, "*")) - { + if (mid[0] && strcmp(mid, "*")) { long int x = strtol(mid, &e, 16); - if ((e && *e) || (x < 0 || x > 0x1f)) - { + if ((e && *e) || (x < 0 || x > 0x1f)) { free(tmp); throw RuntimeError("Failed to parse PCI slot: {}: invalid slot", str); } @@ -242,12 +223,10 @@ Slot::Slot(const std::string &str) : domain(0), device = x; } - if (dot && dot[0] && strcmp(dot, "*")) - { + if (dot && dot[0] && strcmp(dot, "*")) { long int x = strtol(dot, &e, 16); - if ((e && *e) || (x < 0 || x > 7)) - { + if ((e && *e) || (x < 0 || x > 7)) { free(tmp); throw RuntimeError("Failed to parse PCI slot: {}: invalid function", str); } @@ -274,8 +253,7 @@ bool Device::operator==(const Device &f) return id == f.id && slot == f.slot; } -std::list -Device::getRegions() const +std::list Device::getRegions() const { FILE *f; char sysfs[1024]; @@ -296,16 +274,13 @@ Device::getRegions() const int reg_num = 0; // Cap to 8 regions, just because we don't know how many may exist. - while (reg_num < 8 && (bytesRead = getline(&line, &len, f)) != -1) - { + while (reg_num < 8 && (bytesRead = getline(&line, &len, f)) != -1) { unsigned long long tokens[3]; char *s = line; - for (int i = 0; i < 3; i++) - { + for (int i = 0; i < 3; i++) { char *end; tokens[i] = strtoull(s, &end, 16); - if (s == end) - { + if (s == end) { log->debug("Error parsing line {} of {}", reg_num + 1, sysfs); tokens[0] = tokens[1] = 0; // Mark invalid break; @@ -319,8 +294,7 @@ Device::getRegions() const line = nullptr; len = 0; - if (tokens[0] != tokens[1]) - { // This is a valid region + if (tokens[0] != tokens[1]) { // This is a valid region Region region; region.num = reg_num; @@ -339,8 +313,7 @@ Device::getRegions() const return regions; } -std::string -Device::getDriver() const +std::string Device::getDriver() const { int ret; char sysfs[1024], syml[1024]; @@ -393,62 +366,61 @@ bool Device::attachDriver(const std::string &driver) const bool Device::readHostBar(uint32_t &bar) const { unsigned long long start, end, size, flags; + char *path = NULL; if (asprintf(&path, "%s/bus/pci/devices/%04x:%02x:%02x.%x/resource", SYSFS_PATH, - slot.domain, slot.bus, slot.device, slot.function) == -1) - { + slot.domain, slot.bus, slot.device, slot.function) == -1) { log->error("could not allocate memory for path"); return false; } + FILE *file = fopen(path, "r"); - if (!file) - { + if (!file) { log->error("error opening resource file"); return false; } - if (fscanf(file, "%llx %llx %llx", &start, &end, &flags) != 3) - { + if (fscanf(file, "%llx %llx %llx", &start, &end, &flags) != 3) { log->error("error reading resource file"); fclose(file); return false; } + if (end > start) - { size = end - start + 1; - } - else - { + else { log->error("error reading bar size"); fclose(file); return false; } - log->debug("start: {:#x}, end: {:#x}, size: {:#x}, flags: {:#x}", start, end, size, flags); + + log->debug("Start: {:#x}, end: {:#x}, size: {:#x}, flags: {:#x}", start, end, size, flags); + fclose(file); bar = start; + return true; } bool Device::rewriteBar() { uint32_t hostbar, configbar; - if (!readHostBar(hostbar)) - { - log->error("error reading host bar"); + if (!readHostBar(hostbar)) { + log->error("Error reading host bar"); return false; } - if (!readBar(configbar)) - { - log->error("error reading config bar"); + + if (!readBar(configbar)) { + log->error("Error reading config bar"); return false; } - log->debug("hostbar: {:#x}, configbar: {:#x}", hostbar, configbar); - if (hostbar == configbar) - { - log->debug("bar is already correct"); + log->debug("Host BAR: {:#x}, configbar: {:#x}", hostbar, configbar); + + if (hostbar == configbar) { + log->debug("BAR is already correct"); return true; } else { - log->debug("bar is incorrect, rewriting"); + log->debug("BAR is incorrect, rewriting"); return writeBar(hostbar); } } @@ -459,26 +431,26 @@ bool Device::readBar(uint32_t &bar) const uint32_t read_buf; char *path = NULL; if (asprintf(&path, "%s/bus/pci/devices/%04x:%02x:%02x.%x/config", SYSFS_PATH, - slot.domain, slot.bus, slot.device, slot.function) == -1) - { + slot.domain, slot.bus, slot.device, slot.function) == -1) { log->error("could not allocate memory for path"); return false; } + int fd = open(path, O_RDWR); - if (fd < 0) - { + if (fd < 0) { log->error("could not open config space"); return false; } - if (pread(fd, &read_buf, sizeof(read_buf), pos) != sizeof(read_buf)) - { + if (pread(fd, &read_buf, sizeof(read_buf), pos) != sizeof(read_buf)) { log->error("error reading from {:#x}", pos); close(fd); return false; } + bar = read_buf; close(fd); + return true; } @@ -487,33 +459,34 @@ bool Device::writeBar(uint32_t new_bar) uint32_t write_buf = new_bar; off_t pos = PCI_BASE_ADDRESS_0; char *path = NULL; + if (asprintf(&path, "%s/bus/pci/devices/%04x:%02x:%02x.%x/config", SYSFS_PATH, - slot.domain, slot.bus, slot.device, slot.function) == -1) - { + slot.domain, slot.bus, slot.device, slot.function) == -1) { log->error("could not allocate memory for path"); return false; } + int fd = open(path, O_RDWR); - if (fd < 0) - { + if (fd < 0) { log->error("could not open config space"); return false; } - if (pwrite(fd, &write_buf, sizeof(write_buf), pos) != sizeof(write_buf)) - { + if (pwrite(fd, &write_buf, sizeof(write_buf), pos) != sizeof(write_buf)) { log->error("error writing to {:#x}", pos); close(fd); return false; } + close(fd); return true; } -int Device::getIOMMUGroup() const +int Device::getIommuGroup() const { int ret; char *group; + // readlink() does not add a null terminator! char link[1024] = {0}; char sysfs[1024]; diff --git a/common/lib/kernel/vfio_container.cpp b/common/lib/kernel/vfio_container.cpp index 4aa32f0a6..c63b3c8b7 100644 --- a/common/lib/kernel/vfio_container.cpp +++ b/common/lib/kernel/vfio_container.cpp @@ -98,11 +98,9 @@ Container::Container() : // Check available VFIO extensions (IOMMU types) for (unsigned int i = VFIO_TYPE1_IOMMU; i < EXTENSION_SIZE; i++) { int ret = ioctl(fd, VFIO_CHECK_EXTENSION, i); - if (ret == 0) - extensions[i] = false; - else { - extensions[i] = true; - } + + extensions[i] = ret != 0; + log->debug("VFIO extension {} is {} ({})", i, extensions[i] ? "available" : "not available", VFIO_EXTENSION_STR[i]); } @@ -112,9 +110,8 @@ Container::Container() : } else if (extensions[VFIO_NOIOMMU_IOMMU]) { log->debug("Using VFIO type {} ({})", VFIO_NOIOMMU_IOMMU, VFIO_EXTENSION_STR[VFIO_NOIOMMU_IOMMU]); hasIommu = false; - } else { + } else throw RuntimeError("No supported IOMMU type available"); - } log->debug("Version: {:#x}", version); log->debug("IOMMU: {}", hasIommu ? "yes" : "no"); @@ -140,20 +137,16 @@ void Container::attachGroup(std::shared_ptr group) // Claim group ownership int ret = ioctl(group->getFileDescriptor(), VFIO_GROUP_SET_CONTAINER, &fd); - if (ret < 0) { - log->error("Failed to attach VFIO group {} to container fd {} (error {})", - group->getIndex(), fd, ret); - throw RuntimeError("Failed to attach VFIO group to container"); - } + if (ret < 0) + throw SystemError("Failed to attach VFIO group {} to container fd {}", + group->getIndex(), fd); // Set IOMMU type int iommu_type = isIommuEnabled() ? VFIO_TYPE1_IOMMU : VFIO_NOIOMMU_IOMMU; ret = ioctl(fd, VFIO_SET_IOMMU, iommu_type); - if (ret < 0) { - log->error("Failed to set IOMMU type of container: {}", ret); - throw RuntimeError("Failed to set IOMMU type of container"); - } + if (ret < 0) + throw SystemError("Failed to set IOMMU type of container"); group->setAttachedToContainer(); @@ -167,16 +160,14 @@ std::shared_ptr Container::getOrAttachGroup(int index) { // Search if group with index already exists for (auto &group : groups) { - if (group->getIndex() == index) { + if (group->getIndex() == index) return group; - } } // Group not yet part of this container, so acquire ownership auto group = std::make_shared(index, isIommuEnabled()); attachGroup(group); - return group; } @@ -186,13 +177,11 @@ void Container::dump() log->info("Version: {}", version); // Check available VFIO extensions (IOMMU types) - for (size_t i = 0; i < extensions.size(); i++) { + for (size_t i = 0; i < extensions.size(); i++) log->debug("VFIO extension {} ({}) is {}", extensions[i], VFIO_EXTENSION_STR[i], extensions[i] ? "available" : "not available"); - } - for (auto &group : groups) { + for (auto &group : groups) group->dump(); - } } std::shared_ptr Container::attachDevice(const std::string& name, int index) @@ -225,14 +214,14 @@ std::shared_ptr Container::attachDevice(pci::Device &pdev) } // Get IOMMU group of device - int index = isIommuEnabled() ? pdev.getIOMMUGroup() : 0; + int index = isIommuEnabled() ? pdev.getIommuGroup() : 0; if (index < 0) { ret = kernel::getCmdlineParam("intel_iommu", iommu_state, sizeof(iommu_state)); if (ret != 0 || strcmp("on", iommu_state) != 0) log->warn("Kernel booted without command line parameter " - "'intel_iommu' set to 'on'. Please check documentation " - "(https://villas.fein-aachen.org/doc/fpga-setup.html) " - "for help with troubleshooting."); + "'intel_iommu' set to 'on'. Please check documentation " + "(https://villas.fein-aachen.org/doc/fpga-setup.html) " + "for help with troubleshooting."); throw RuntimeError("Failed to get IOMMU group of device"); } @@ -245,7 +234,6 @@ std::shared_ptr Container::attachDevice(pci::Device &pdev) auto group = getOrAttachGroup(index); auto device = group->attachDevice(name, &pdev); - // Check if this is really a vfio-pci device if (!device->isVfioPciDevice()) throw RuntimeError("Device is not a vfio-pci device"); @@ -253,7 +241,6 @@ std::shared_ptr Container::attachDevice(pci::Device &pdev) return device; } - uintptr_t Container::memoryMap(uintptr_t virt, uintptr_t phys, size_t length) { int ret; @@ -323,4 +310,3 @@ bool Container::memoryUnmap(uintptr_t phys, size_t length) return true; } -