Skip to content

Commit a61bd86

Browse files
committed
implement Intel PMT TelemetryArray on Linux
1 parent 426c0f7 commit a61bd86

File tree

7 files changed

+221
-17
lines changed

7 files changed

+221
-17
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# All pcm-* executables
66
set(PROJECT_NAMES pcm pcm-numa pcm-latency pcm-power pcm-msr pcm-memory pcm-tsx pcm-pcie pcm-core pcm-iio pcm-lspci pcm-pcicfg pcm-mmio pcm-tpmi pcm-raw pcm-accel)
77

8-
file(GLOB COMMON_SOURCES pcm-accel-common.cpp msr.cpp cpucounters.cpp pci.cpp mmio.cpp tpmi.cpp bw.cpp utils.cpp topology.cpp debug.cpp threadpool.cpp uncore_pmu_discovery.cpp)
8+
file(GLOB COMMON_SOURCES pcm-accel-common.cpp msr.cpp cpucounters.cpp pci.cpp mmio.cpp tpmi.cpp pmt.cpp bw.cpp utils.cpp topology.cpp debug.cpp threadpool.cpp uncore_pmu_discovery.cpp)
99

1010
if (APPLE)
1111
file(GLOB UNUX_SOURCES dashboard.cpp)

src/cpucounters.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "msr.h"
2929
#include "pci.h"
3030
#include "tpmi.h"
31+
#include "pmt.h"
3132
#include "bw.h"
3233
#include "width_extender.h"
3334
#include "exceptions/unsupported_processor_exception.hpp"

src/pmt.cpp

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
// Copyright (c) 2024, Intel Corporation
3+
4+
#include "pmt.h"
5+
#include "utils.h"
6+
#include <assert.h>
7+
#include <vector>
8+
#include <unordered_map>
9+
#include <iostream>
10+
11+
namespace pcm {
12+
13+
#ifdef __linux__
14+
class TelemetryArrayLinux : public TelemetryArrayInterface
15+
{
16+
TelemetryArrayLinux() = delete;
17+
typedef std::vector<std::FILE *> FileVector;
18+
typedef std::unordered_map<uint64, FileVector> FileMap;
19+
static std::shared_ptr<FileMap> TelemetryFiles;
20+
static FileMap & getTelemetryFiles()
21+
{
22+
if (!TelemetryFiles.get())
23+
{
24+
std::shared_ptr<FileMap> TelemetryFilesTemp = std::make_shared<FileMap>();
25+
auto paths = findPathsFromPattern("/sys/class/intel_pmt/telem*");
26+
for (auto & path : paths)
27+
{
28+
const auto guid = read_number(readSysFS((path + "/guid").c_str()).c_str());
29+
#if 0
30+
auto size = read_number(readSysFS((path + "/size").c_str()).c_str());
31+
std::cout << "path: " << path << " guid: 0x" << std::hex << guid << " size: "<< std::dec << size << std::endl;
32+
#endif
33+
auto file = std::fopen((path + "/telem").c_str(), "rb");
34+
if (!file)
35+
{
36+
std::cerr << "Error: failed to open " << path << "/telem" << std::endl;
37+
continue;
38+
}
39+
TelemetryFilesTemp->operator[](guid).push_back(file);
40+
}
41+
42+
// print the telemetry files
43+
for (auto & guid : *TelemetryFilesTemp)
44+
{
45+
auto & files = guid.second;
46+
for (auto & file : files)
47+
{
48+
if (!file)
49+
{
50+
std::cerr << "Error: file is null" << std::endl;
51+
continue;
52+
}
53+
// std::cout << "guid: 0x" << std::hex << guid.first << " file: " << file << std::endl;
54+
}
55+
}
56+
57+
TelemetryFiles = TelemetryFilesTemp;
58+
}
59+
return *TelemetryFiles;
60+
}
61+
std::vector<unsigned char> data;
62+
size_t uid, instance;
63+
public:
64+
TelemetryArrayLinux(const size_t uid_, const size_t instance_): uid(uid_), instance(instance_)
65+
{
66+
assert(instance < numInstances(uid));
67+
load();
68+
}
69+
static size_t numInstances(const size_t uid)
70+
{
71+
return getTelemetryFiles().at(uid).size();
72+
}
73+
virtual ~TelemetryArrayLinux() override
74+
{
75+
}
76+
size_t size() override
77+
{
78+
return data.size();
79+
}
80+
void load() override
81+
{
82+
FILE * file = getTelemetryFiles().at(uid).at(instance);
83+
assert(file);
84+
// get the file size
85+
fseek(file, 0, SEEK_END);
86+
size_t fileSize = ftell(file);
87+
fseek(file, 0, SEEK_SET);
88+
data.resize(fileSize);
89+
const size_t bytesRead = fread(data.data(), 1, fileSize, file);
90+
if (bytesRead != fileSize)
91+
{
92+
std::cerr << "Error: failed to read " << fileSize << " bytes from telemetry file" << std::endl;
93+
}
94+
}
95+
uint64 get(size_t qWordOffset, size_t lsb, size_t msb) override
96+
{
97+
assert(qWordOffset * sizeof(uint64) + sizeof(uint64) <= data.size());
98+
return extract_bits(*reinterpret_cast<uint64 *>(&data[qWordOffset * sizeof(uint64)]), lsb, msb);
99+
}
100+
};
101+
102+
std::shared_ptr<TelemetryArrayLinux::FileMap> TelemetryArrayLinux::TelemetryFiles;
103+
104+
#else
105+
106+
class TelemetryArrayDummy : public TelemetryArrayInterface
107+
{
108+
TelemetryArrayDummy() = delete;
109+
public:
110+
TelemetryArrayDummy(const size_t /* uid */, const size_t /* instance */) {};
111+
static size_t numInstances(const size_t /* uid */) { return 0; };
112+
virtual ~TelemetryArrayDummy() override {};
113+
size_t size() override { return 0;}; // in bytes
114+
void load() override {};
115+
uint64 get(size_t , size_t , size_t ) override { return 0;} ;
116+
};
117+
118+
#endif
119+
120+
TelemetryArray::TelemetryArray(const size_t uid, const size_t instance)
121+
{
122+
#ifdef __linux__
123+
impl = std::make_shared<TelemetryArrayLinux>(uid, instance);
124+
#else
125+
impl = std::make_shared<TelemetryArrayDummy>(uid, instance);
126+
#endif
127+
}
128+
129+
size_t TelemetryArray::numInstances(const size_t uid)
130+
{
131+
#ifdef __linux__
132+
return TelemetryArrayLinux::numInstances(uid);
133+
#else
134+
return TelemetryArrayDummy::numInstances(uid);
135+
#endif
136+
}
137+
138+
TelemetryArray::~TelemetryArray() {}
139+
140+
size_t TelemetryArray::size()
141+
{
142+
assert(impl.get());
143+
return impl->size();
144+
}
145+
146+
void TelemetryArray::load()
147+
{
148+
assert(impl.get());
149+
impl->load();
150+
}
151+
152+
uint64 TelemetryArray::get(size_t qWordOffset, size_t lsb, size_t msb)
153+
{
154+
assert(impl.get());
155+
return impl->get(qWordOffset, lsb, msb);
156+
}
157+
158+
}; // namespace pcm

src/pmt.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
// Copyright (c) 2024, Intel Corporation
3+
4+
#pragma once
5+
6+
#include "types.h"
7+
#include <memory>
8+
9+
namespace pcm {
10+
11+
class TelemetryArrayInterface
12+
{
13+
public:
14+
virtual size_t size() = 0; // in bytes
15+
virtual size_t numQWords()
16+
{
17+
return size() / sizeof(uint64);
18+
}
19+
virtual void load() = 0;
20+
virtual uint64 get(size_t qWordOffset, size_t lsb, size_t msb) = 0;
21+
virtual ~TelemetryArrayInterface() {};
22+
};
23+
24+
class TelemetryArray : public TelemetryArrayInterface
25+
{
26+
TelemetryArray() = delete;
27+
std::shared_ptr<TelemetryArrayInterface> impl;
28+
public:
29+
TelemetryArray(const size_t /* uid */, const size_t /* instance */);
30+
static size_t numInstances(const size_t /* uid */);
31+
virtual ~TelemetryArray() override;
32+
size_t size() override; // in bytes
33+
void load() override;
34+
uint64 get(size_t qWordOffset, size_t lsb, size_t msb) override;
35+
};
36+
37+
} // namespace pcm

src/tpmi.cpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include <unordered_map>
1111
#include <assert.h>
1212
#ifdef __linux__
13-
#include <glob.h>
1413
#include <algorithm>
1514
#endif
1615

@@ -331,21 +330,6 @@ bool TPMIHandleDriver::isAvailable()
331330
{
332331
if (available < 0) // not initialized yet
333332
{
334-
auto findPathsFromPattern = [](const char* pattern)
335-
{
336-
std::vector<std::string> result;
337-
glob_t glob_result;
338-
memset(&glob_result, 0, sizeof(glob_result));
339-
if (glob(pattern, GLOB_TILDE, nullptr, &glob_result) == 0)
340-
{
341-
for (size_t i = 0; i < glob_result.gl_pathc; ++i)
342-
{
343-
result.push_back(glob_result.gl_pathv[i]);
344-
}
345-
}
346-
globfree(&glob_result);
347-
return result;
348-
};
349333
instancePaths = findPathsFromPattern("/sys/kernel/debug/tpmi-*");
350334
std::sort(instancePaths.begin(), instancePaths.end());
351335
for (size_t i = 0; i < instancePaths.size(); ++i)

src/utils.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
#ifndef _MSC_VER
2424
#include <execinfo.h>
2525
#endif
26+
#ifdef __linux__
27+
#include <glob.h>
28+
#endif
2629

2730
namespace pcm {
2831

@@ -101,6 +104,24 @@ void print_cpu_details()
101104
std::cerr << "\n";
102105
}
103106

107+
#ifdef __linux__
108+
std::vector<std::string> findPathsFromPattern(const char* pattern)
109+
{
110+
std::vector<std::string> result;
111+
glob_t glob_result;
112+
memset(&glob_result, 0, sizeof(glob_result));
113+
if (glob(pattern, GLOB_TILDE, nullptr, &glob_result) == 0)
114+
{
115+
for (size_t i = 0; i < glob_result.gl_pathc; ++i)
116+
{
117+
result.push_back(glob_result.gl_pathv[i]);
118+
}
119+
}
120+
globfree(&glob_result);
121+
return result;
122+
};
123+
#endif
124+
104125
#ifdef _MSC_VER
105126

106127
ThreadGroupTempAffinity::ThreadGroupTempAffinity(uint32 core_id, bool checkStatus, const bool restore_)

src/utils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,9 @@ inline void extractBitsPrintHelper(const std::pair<int64,int64> & bits, T & valu
612612
void restrictDriverAccessNative(LPCTSTR path);
613613
#endif
614614

615+
#ifdef __linux__
616+
std::vector<std::string> findPathsFromPattern(const char* pattern);
617+
#endif
615618

616619
class TemporalThreadAffinity // speedup trick for Linux, FreeBSD, DragonFlyBSD, Windows
617620
{

0 commit comments

Comments
 (0)