2023-08-28 12:31:18 +02:00
|
|
|
/* Linux PCI helpers
|
2020-06-14 21:52:29 +02:00
|
|
|
*
|
2023-08-31 11:17:07 +02:00
|
|
|
* Author: Steffen Vogel <post@steffenvogel.de>
|
|
|
|
* SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2023-08-28 12:31:18 +02:00
|
|
|
*/
|
2020-06-14 21:52:29 +02:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2022-12-21 11:50:03 +01:00
|
|
|
#include <list>
|
|
|
|
#include <fstream>
|
|
|
|
|
2020-06-14 21:52:29 +02:00
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
|
|
|
|
2022-12-19 15:25:55 +01:00
|
|
|
#include <villas/log.hpp>
|
2020-06-14 21:52:29 +02:00
|
|
|
|
|
|
|
namespace villas {
|
|
|
|
namespace kernel {
|
|
|
|
namespace pci {
|
|
|
|
|
|
|
|
#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
|
|
|
|
#define PCI_FUNC(devfn) ((devfn) & 0x07)
|
|
|
|
|
|
|
|
class Id {
|
|
|
|
public:
|
|
|
|
Id(const std::string &str);
|
|
|
|
|
|
|
|
Id(int vid = 0, int did = 0, int cc = 0) :
|
|
|
|
vendor(vid),
|
|
|
|
device(did),
|
|
|
|
class_code(cc)
|
|
|
|
{ }
|
|
|
|
|
2022-12-21 09:56:04 +01:00
|
|
|
bool operator==(const Id &i);
|
2020-06-14 21:52:29 +02:00
|
|
|
|
2020-09-11 16:01:16 +02:00
|
|
|
unsigned int vendor;
|
|
|
|
unsigned int device;
|
|
|
|
unsigned int class_code;
|
2020-06-14 21:52:29 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class Slot {
|
|
|
|
public:
|
|
|
|
Slot(const std::string &str);
|
|
|
|
|
|
|
|
Slot(int dom = 0, int b = 0, int dev = 0, int fcn = 0) :
|
|
|
|
domain(dom),
|
|
|
|
bus(b),
|
|
|
|
device(dev),
|
|
|
|
function(fcn)
|
|
|
|
{ }
|
|
|
|
|
2022-12-21 09:56:04 +01:00
|
|
|
bool operator==(const Slot &s);
|
2020-06-14 21:52:29 +02:00
|
|
|
|
2020-09-11 16:01:16 +02:00
|
|
|
unsigned int domain;
|
|
|
|
unsigned int bus;
|
|
|
|
unsigned int device;
|
|
|
|
unsigned int function;
|
2020-06-14 21:52:29 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Region {
|
|
|
|
int num;
|
|
|
|
uintptr_t start;
|
|
|
|
uintptr_t end;
|
|
|
|
unsigned long long flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Device {
|
|
|
|
public:
|
|
|
|
Device(Id i, Slot s) :
|
|
|
|
id(i),
|
2022-12-19 15:25:55 +01:00
|
|
|
slot(s),
|
|
|
|
log(logging.get("kernel:pci"))
|
2020-06-14 21:52:29 +02:00
|
|
|
{ }
|
|
|
|
|
2020-06-15 21:05:51 +02:00
|
|
|
Device(Id i) :
|
2022-12-19 15:25:55 +01:00
|
|
|
id(i),
|
|
|
|
log(logging.get("kernel:pci"))
|
2020-06-15 21:05:51 +02:00
|
|
|
{ }
|
2020-06-14 21:52:29 +02:00
|
|
|
|
2020-06-15 21:05:51 +02:00
|
|
|
Device(Slot s) :
|
2022-12-19 15:25:55 +01:00
|
|
|
slot(s),
|
|
|
|
log(logging.get("kernel:pci"))
|
2020-06-15 21:05:51 +02:00
|
|
|
{ }
|
2020-06-14 21:52:29 +02:00
|
|
|
|
|
|
|
bool
|
2020-06-15 21:05:51 +02:00
|
|
|
operator==(const Device &other);
|
2020-06-14 21:52:29 +02:00
|
|
|
|
2023-08-28 12:31:18 +02:00
|
|
|
// Get currently loaded driver for device
|
2022-12-21 09:56:04 +01:00
|
|
|
std::string getDriver() const;
|
2020-06-14 21:52:29 +02:00
|
|
|
|
2023-08-28 12:31:18 +02:00
|
|
|
// Bind a new LKM to the PCI device
|
2022-12-21 09:56:04 +01:00
|
|
|
bool attachDriver(const std::string &driver) const;
|
2020-06-14 21:52:29 +02:00
|
|
|
|
2023-08-28 12:31:18 +02:00
|
|
|
// Return the IOMMU group of this PCI device or -1 if the device is not in a group
|
2022-12-21 09:56:04 +01:00
|
|
|
int getIommuGroup() const;
|
2020-06-14 21:52:29 +02:00
|
|
|
|
2022-12-21 09:56:04 +01:00
|
|
|
std::list<Region> getRegions() const;
|
2020-06-14 21:52:29 +02:00
|
|
|
|
2022-12-21 09:56:04 +01:00
|
|
|
// Write 32-bit BAR value from to the PCI configuration space
|
2022-12-21 11:50:03 +01:00
|
|
|
void writeBar(uint32_t addr, unsigned bar = 0);
|
2022-12-19 15:25:55 +01:00
|
|
|
|
2022-12-21 09:56:04 +01:00
|
|
|
// If BAR values in config space and in the kernel do not match, rewrite
|
2023-08-28 12:31:18 +02:00
|
|
|
// the BAR value of the kernel to PCIe config space
|
2022-12-21 11:50:03 +01:00
|
|
|
void rewriteBar(unsigned bar = 0);
|
2022-12-19 15:25:55 +01:00
|
|
|
|
2023-08-28 12:31:18 +02:00
|
|
|
// Read 32-bit BAR value from the PCI configuration space
|
2022-12-21 11:50:03 +01:00
|
|
|
uint32_t readBar(unsigned bar = 0) const;
|
2022-12-19 15:25:55 +01:00
|
|
|
|
2023-08-28 12:31:18 +02:00
|
|
|
// Read 32-bit BAR value from the devices resource file.
|
|
|
|
// This is what the kernel thinks the BAR should be.
|
2022-12-21 11:50:03 +01:00
|
|
|
uint32_t readHostBar(unsigned bar = 0) const;
|
2022-12-19 15:25:55 +01:00
|
|
|
|
2020-06-14 21:52:29 +02:00
|
|
|
Id id;
|
|
|
|
Slot slot;
|
2022-12-19 15:25:55 +01:00
|
|
|
private:
|
|
|
|
villas::Logger log;
|
2022-12-21 11:50:03 +01:00
|
|
|
|
|
|
|
protected:
|
2023-01-12 18:18:12 +01:00
|
|
|
std::fstream openSysFs(const std::string &subPath, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) const;
|
2020-06-14 21:52:29 +02:00
|
|
|
};
|
|
|
|
|
2020-06-15 21:05:51 +02:00
|
|
|
class DeviceList : public std::list<std::shared_ptr<Device>> {
|
2020-06-14 21:52:29 +02:00
|
|
|
public:
|
2022-12-21 09:56:04 +01:00
|
|
|
// Initialize Linux PCI handle.
|
|
|
|
//
|
|
|
|
// This search for all available PCI devices under /sys/bus/pci
|
2020-06-14 21:52:29 +02:00
|
|
|
DeviceList();
|
|
|
|
|
2022-12-21 09:56:04 +01:00
|
|
|
DeviceList::value_type lookupDevice(const Slot &s);
|
2020-06-15 21:05:51 +02:00
|
|
|
|
2022-12-21 09:56:04 +01:00
|
|
|
DeviceList::value_type lookupDevice(const Id &i);
|
2020-06-14 21:52:29 +02:00
|
|
|
|
2022-12-21 09:56:04 +01:00
|
|
|
DeviceList::value_type lookupDevice(const Device &f);
|
2020-06-14 21:52:29 +02:00
|
|
|
};
|
|
|
|
|
2022-12-02 17:16:44 +01:00
|
|
|
} // namespace pci
|
|
|
|
} // namespace kernel
|
|
|
|
} // namespace villas
|