-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathvfio_group.cpp
More file actions
125 lines (99 loc) · 3.27 KB
/
vfio_group.cpp
File metadata and controls
125 lines (99 loc) · 3.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/* Virtual Function IO wrapper around kernel API.
*
* Author: Steffen Vogel <post@steffenvogel.de>
* Author: Daniel Krebs <github@daniel-krebs.net>
* Author: Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
* SPDX-FileCopyrightText: 2014-2021 Steffen Vogel <post@steffenvogel.de>
* SPDX-FileCopyrightText: 2018 Daniel Krebs <github@daniel-krebs.net>
* SPDX-FileCopyrightText: 2022-2023 Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
* SPDX-License-Identifier: Apache-2.0
*/
#define _DEFAULT_SOURCE
#if defined(__arm__) || defined(__aarch64__)
#define _LARGEFILE64_SOURCE 1
#define _FILE_OFFSET_BITS 64
#endif
#include <algorithm>
#include <limits>
#include <sstream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <fcntl.h>
#include <linux/pci_regs.h>
#include <sys/eventfd.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <villas/exceptions.hpp>
#include <villas/kernel/vfio_group.hpp>
using namespace villas::kernel::vfio;
Group::Group(int index, bool iommuEnabled)
: fd(-1), index(index), attachedToContainer(false), status(), devices(),
log(Log::get("kernel:vfio:group")) {
// Open group fd
std::stringstream groupPath;
groupPath << VFIO_PATH << (iommuEnabled ? "" : "noiommu-") << index;
log->debug("path: {}", groupPath.str().c_str());
fd = open(groupPath.str().c_str(), O_RDWR);
if (fd < 0) {
log->error("Failed to open VFIO group {}", index);
throw RuntimeError("Failed to open VFIO group");
}
log->debug("VFIO group {} (fd {}) has path {}", index, fd, groupPath.str());
checkStatus();
}
std::shared_ptr<Device> Group::attachDevice(std::shared_ptr<Device> device) {
if (device->isAttachedToGroup())
throw RuntimeError("Device is already attached to a group");
devices.push_back(device);
device->setAttachedToGroup();
return device;
}
std::shared_ptr<Device>
Group::attachDevice(const std::string &name,
const kernel::devices::PciDevice *pci_device) {
auto device = std::make_shared<Device>(name, fd, pci_device);
return attachDevice(device);
}
bool Group::checkStatus() {
int ret;
// Check group viability and features
status.argsz = sizeof(status);
ret = ioctl(fd, VFIO_GROUP_GET_STATUS, &status);
if (ret < 0) {
log->error("Failed to get VFIO group status");
return false;
}
if (!(status.flags & VFIO_GROUP_FLAGS_VIABLE)) {
log->error(
"VFIO group is not available: bind all devices to the VFIO driver!");
return false;
}
log->debug("VFIO group is {} viable", index);
return true;
}
void Group::dump() {
log->info("VFIO Group {}, viable={}, container={}", index,
(status.flags & VFIO_GROUP_FLAGS_VIABLE) > 0,
(status.flags & VFIO_GROUP_FLAGS_CONTAINER_SET) > 0);
for (auto &device : devices) {
device->dump();
}
}
Group::~Group() {
// Release memory and close fds
devices.clear();
log->debug("Cleaning up group {} with fd {}", index, fd);
if (fd < 0)
log->debug("Destructing group that has not been attached");
else {
log->debug("unsetting group container");
int ret = ioctl(fd, VFIO_GROUP_UNSET_CONTAINER);
if (ret != 0)
log->error("Cannot unset container for group fd {}", fd);
ret = close(fd);
if (ret != 0)
log->error("Cannot close group fd {}", fd);
}
}