Skip to content

Commit ef8145c

Browse files
RoC: Add checks for hugepage backing of DMA buffer
1 parent 1edbf39 commit ef8145c

File tree

4 files changed

+155
-25
lines changed

4 files changed

+155
-25
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ set(SRCS
8484
src/ParameterTypes/ResetLevel.cxx
8585
src/ParameterTypes/ReadoutMode.cxx
8686
src/RorcStatusCode.cxx
87+
src/Utilities/MemoryMaps.cxx
8788
src/CommandLineUtilities/AliceLowlevelFrontend/Sca.cxx
8889
src/CommandLineUtilities/AliceLowlevelFrontend/ServiceNames.cxx
8990
src/CommandLineUtilities/Common.cxx

src/DmaChannelPdaBase.cxx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
#include "DmaChannelPdaBase.h"
77
#include <boost/filesystem/path.hpp>
8+
#include "Common/Iommu.h"
9+
#include "Utilities/MemoryMaps.h"
810
#include "Utilities/SmartPointer.h"
911
#include "Utilities/Util.h"
1012
#include "Visitor.h"
@@ -47,6 +49,34 @@ DmaChannelPdaBase::DmaChannelPdaBase(const Parameters& parameters,
4749
BOOST_THROW_EXCEPTION(Exception() << ErrorInfo::Message(message));
4850
}
4951
}
52+
53+
// Check memory mappings if it's hugepage
54+
{
55+
bool checked = false;
56+
const auto maps = Utilities::getMemoryMaps();
57+
for (const auto& map : maps) {
58+
const auto bufferAddress = reinterpret_cast<uintptr_t>(getBufferProvider().getAddress());
59+
if (map.addressStart == bufferAddress) {
60+
if (map.pageSizeKiB > 4) {
61+
log("Buffer is hugepage-backed", InfoLogger::InfoLogger::Info);
62+
} else {
63+
if (Common::Iommu::isEnabled()) {
64+
log("Buffer is NOT hugepage-backed, but IOMMU is enabled", InfoLogger::InfoLogger::Warning);
65+
} else {
66+
std::string message = "Buffer is NOT hugepage-backed and IOMMU is disabled - unsupported buffer "
67+
"configuration";
68+
log(message, InfoLogger::InfoLogger::Error);
69+
BOOST_THROW_EXCEPTION(Exception() << ErrorInfo::Message(message));
70+
}
71+
}
72+
checked = true;
73+
break;
74+
}
75+
}
76+
if (!checked) {
77+
log("Failed to check if buffer is hugepage-backed", InfoLogger::InfoLogger::Warning);
78+
}
79+
}
5080
}
5181

5282
DmaChannelPdaBase::~DmaChannelPdaBase()

src/Utilities/MemoryMaps.cxx

Lines changed: 115 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,137 @@
33
///
44
/// \author Pascal Boeschoten ([email protected])
55

6-
#pragma once
6+
#include "MemoryMaps.h"
77

8+
#include <fstream>
89
#include <map>
10+
#include <sstream>
11+
#include <string>
12+
#include <iostream>
913
#include <boost/throw_exception.hpp>
10-
#include <boost/algorithm/string/split.hpp>
14+
#include <boost/algorithm/string.hpp>
15+
#include <boost/lexical_cast.hpp>
16+
#include "Common/System.h"
1117

1218
namespace AliceO2 {
1319
namespace roc {
1420
namespace Utilities {
1521

16-
std::vector<MemoryMap> getMemoryMaps()
22+
namespace {
23+
std::string slurp(std::string file)
1724
{
18-
std::vector<MemoryMap> memoryMaps;
25+
std::ifstream ifstream(file);
26+
std::stringstream buffer;
27+
buffer << ifstream.rdbuf();
28+
return buffer.str();
29+
}
30+
31+
/// Splits string into rows and "columns"
32+
std::vector<std::vector<std::string>> tablify(std::string string) {
33+
std::vector<std::string> lines;
34+
boost::split(lines, string, boost::is_any_of("\n"), boost::token_compress_on);
35+
std::vector<std::vector<std::string>> splitLines(lines.size());
36+
for (size_t i = 0; i < lines.size(); ++i) {
37+
boost::split(splitLines.at(i), lines.at(i), boost::is_any_of(" "), boost::token_compress_on);
38+
}
39+
return splitLines;
40+
}
41+
42+
struct Mapping
43+
{
44+
uintptr_t addressStart;
45+
uintptr_t addressEnd;
46+
std::string permissions;
47+
uintptr_t offset;
48+
std::string dev;
49+
size_t inode;
50+
std::string path;
51+
};
52+
53+
struct NumaMapping
54+
{
55+
std::string path;
56+
size_t pageSizeKiB;
57+
};
58+
59+
std::vector<Mapping> getMaps()
60+
{
61+
std::vector<Mapping> maps;
62+
auto procMaps = slurp("/proc/self/maps");
63+
auto table = tablify(procMaps);
64+
65+
for (const auto& row : table) {
66+
if (row.size() != 6) {
67+
continue;
68+
}
69+
70+
Mapping mapping;
71+
std::vector<std::string> addressSplit;
72+
boost::split(addressSplit, row.at(0), boost::is_any_of("-"), boost::token_compress_on);
73+
mapping.addressStart = std::strtoul(addressSplit.at(0).c_str(), nullptr, 16);
74+
mapping.addressEnd = std::strtoul(addressSplit.at(1).c_str(), nullptr, 16);
75+
mapping.permissions = boost::trim_copy(row.at(1));
76+
mapping.offset = std::strtoul(row.at(2).c_str(), nullptr, 16);
77+
mapping.dev = boost::trim_copy(row.at(3));
78+
mapping.inode = boost::lexical_cast<size_t>(row.at(4));
79+
mapping.path = boost::trim_copy(row.at(5));
80+
maps.push_back(mapping);
81+
}
1982

20-
auto procMaps = executeCommand("cat /proc/self/maps");
21-
auto procNumaMaps = executeCommand("cat /proc/self/numa_maps");
83+
return maps;
84+
}
85+
86+
std::map<uintptr_t, NumaMapping> getNumaMaps()
87+
{
88+
std::map<uintptr_t, NumaMapping> maps;
89+
auto numaMaps = slurp("/proc/self/numa_maps");
90+
auto table = tablify(numaMaps);
91+
92+
for (const auto& row : table) {
93+
auto address = std::strtoul(row.at(0).c_str(), nullptr, 16);
2294

23-
auto splitLines = [](std::string string) {
24-
std::vector<std::string> lines;
25-
boost::split(lines, string, boost::is_any_of("\n"));
95+
NumaMapping mapping;
2696

27-
std::vector<std::vector<std::string>> splitLines(lines.size());
28-
for (int i = 0; i < lines.size(); ++i) {
29-
boost::split(splitLines.at(i), lines, boost::is_any_of(" "));
97+
for (const auto& item : row) {
98+
auto setKeyValue = [&](std::string key, auto setFunction) {
99+
if (item.find(key) == 0) {
100+
setFunction(item.substr(key.size() + 1)); // Add 1 for the =
101+
}
102+
};
103+
104+
setKeyValue("file", [&](auto value){mapping.path = value;});
105+
setKeyValue("kernelpagesize_kB", [&](auto value){mapping.pageSizeKiB = boost::lexical_cast<size_t>(value);});
106+
107+
if (item.find("huge") == 0) {
108+
mapping.pageSizeKiB = 2*1024;
109+
}
30110
}
31111

32-
return splitLines;
33-
};
112+
maps[address] = mapping;
113+
}
114+
115+
return maps;
116+
}
117+
118+
119+
} // Anonymous namespace
120+
121+
std::vector<MemoryMap> getMemoryMaps()
122+
{
123+
std::vector<MemoryMap> memoryMaps;
34124

35-
auto mapsTable = splitLines(procMaps);
36-
auto numaMapsTable = splitLines(procNumaMaps);
125+
const auto maps = getMaps();
126+
const auto numaMaps = getNumaMaps();
37127

38-
for (int i = 0; i < mapsTable.size(); ++i) {
39-
std::vector<std::string> memoryRange;
40-
const auto& memoryRangeString = mapsTable.at(i).at(0);
41-
boost::split(memoryRange, memoryRangeString, boost::is_any_of(" "));
128+
for (const auto& map : maps) {
129+
MemoryMap memMap;
130+
memMap.addressStart = map.addressStart;
131+
memMap.addressEnd = map.addressEnd;
132+
memMap.path = map.path;
133+
if (numaMaps.count(map.addressStart)) {
134+
memMap.pageSizeKiB = numaMaps.at(map.addressStart).pageSizeKiB;
135+
}
136+
memoryMaps.push_back(memMap);
42137
}
43138

44139
return memoryMaps;

src/Utilities/MemoryMaps.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,21 @@
55

66
#pragma once
77

8+
#include <cstddef>
9+
#include <cstdint>
10+
#include <vector>
11+
#include <string>
12+
813
namespace AliceO2 {
914
namespace roc {
1015
namespace Utilities {
1116

1217
struct MemoryMap
1318
{
14-
uintptr_t startAddress;
15-
uintptr_t endAddress;
16-
size_t size;
17-
bool isHuge; ///< Is hugepage memory
18-
size_t kernelPageSize; ///< Size of the
19+
uintptr_t addressStart; ///< Starting address of the mapping
20+
uintptr_t addressEnd; ///< End address of the mapping
21+
size_t pageSizeKiB; ///< Size of the pages. 0 if unknown.
22+
std::string path; ///< Pathname of the mapping.
1923
};
2024

2125
/// TODO Work in progress

0 commit comments

Comments
 (0)