-
Notifications
You must be signed in to change notification settings - Fork 524
Expand file tree
/
Copy pathpcm-tpmi.cpp
More file actions
200 lines (179 loc) · 6.67 KB
/
pcm-tpmi.cpp
File metadata and controls
200 lines (179 loc) · 6.67 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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2023 Intel Corporation
// written by Roman Dementiev
#include "cpucounters.h"
#ifdef _MSC_VER
#include <windows.h>
#include "windows/windriver.h"
#else
#include <unistd.h>
#endif
#include <iostream>
#include <stdlib.h>
#include <iomanip>
#include <string.h>
#ifdef _MSC_VER
#include "freegetopt/getopt.h"
#endif
using namespace pcm;
void print_usage(const char * progname)
{
std::cout << "Usage " << progname << " [-w value] [-d] [-b low:high] [-e entries] ID offset\n\n";
std::cout << " Reads/writes TPMI (Topology Aware Register and PM Capsule Interface) register \n";
std::cout << " ID : TPMI ID\n";
std::cout << " offset : register offset\n";
std::cout << " -w value : write the value before reading \n";
std::cout << " -b low:high : read or write only low..high bits of the register\n";
std::cout << " -e entries : perform read/write on specified entries (default is all entries)\n";
std::cout << " (examples: -e 10 -e 10-11 -e 4,6,12-20,6)\n";
std::cout << " -i instances: perform read/write on specified instances (default is all instances)\n";
std::cout << " (examples: -i 1 -i 0,1 -i 0,2-3)\n";
std::cout << " -d : output all numbers in dec (default is hex)\n";
std::cout << " -v : verbose ouput\n";
std::cout << " --version : print application version\n";
std::cout << "\n";
}
PCM_MAIN_NOTHROW;
int mainThrows(int argc, char * argv[])
{
if(print_version(argc, argv))
return 0;
std::cout << "\n Intel(r) Performance Counter Monitor " << PCM_VERSION << "\n";
std::cout << "\n TPMI (Topology Aware Register and PM Capsule Interface) read/write utility\n\n";
// register documentation: https://github.com/intel/tpmi_power_management
uint64 value = 0;
bool write = false;
bool dec = false;
std::pair<int64,int64> bits{-1, -1};
std::list<int> entries, instances;
int my_opt = -1;
while ((my_opt = getopt(argc, argv, "w:dvb:e:i:")) != -1)
{
switch (my_opt)
{
case 'w':
write = true;
value = read_number(optarg);
break;
case 'd':
dec = true;
break;
case 'v':
TPMIHandle::setVerbose(true);
break;
case 'b':
bits = parseBitsParameter(optarg);
break;
case 'e':
entries = extract_integer_list(optarg);
break;
case 'i':
instances = extract_integer_list(optarg);
break;
default:
print_usage(argv[0]);
return -1;
}
}
if (optind + 1 >= argc)
{
print_usage(argv[0]);
return -1;
}
uint64 requestedID = (uint64)read_number(argv[optind]);
uint64 requestedRelativeOffset = (uint64)read_number(argv[optind + 1]);
#ifdef _MSC_VER
// Increase the priority a bit to improve context switching delays on Windows
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
// WARNING: This driver code (msr.sys) is only for testing purposes, not for production use
Driver drv = Driver(Driver::msrSystemPath());
// drv.stop(); // restart driver (usually not needed)
if (!drv.start())
{
tcerr << "Can not load MSR driver.\n";
tcerr << "You must have a signed driver at " << drv.driverPath() << " and have administrator rights to run this program\n";
return -1;
}
#endif
try
{
PCM::setQuietMode(true);
auto pcmInstance = PCM::getInstance();
if (instances.empty())
{
for (size_t i = 0; i < TPMIHandle::getNumInstances(); ++i)
{
instances.push_back(i);
}
}
for (const size_t i : instances)
{
if (i >= TPMIHandle::getNumInstances())
{
std::cerr << "Instance " << i << " does not exist\n";
continue;
}
TPMIHandle h(i, requestedID, requestedRelativeOffset, !write);
// Get NUMA node and socket ID
int32 numaNode = h.getNUMANode();
int32 socketId = -1;
if (numaNode >= 0)
{
socketId = pcmInstance->mapNUMANodeToSocket(static_cast<uint32>(numaNode));
}
// Helper lambda to print socket ID and NUMA node information
auto printTopologyInfo = [&socketId, &numaNode]() {
if (socketId >= 0 || numaNode >= 0)
{
// Save stream format state
auto flags = std::cout.flags();
if (socketId >= 0)
std::cout << " (socket " << std::dec << socketId << ")";
if (numaNode >= 0)
std::cout << " (NUMA node " << std::dec << numaNode << ")";
// Restore stream format state
std::cout.flags(flags);
}
};
auto one = [&](const size_t p, uint64 value)
{
if (!dec)
std::cout << std::hex << std::showbase;
readOldValueHelper(bits, value, write, [&h, &p](uint64& old_value)
{ old_value = h.read64(p); return true; });
if (write)
{
std::cout << " Writing " << value << " to TPMI ID " << requestedID << "@" << requestedRelativeOffset << " for entry " << p << " in instance " << i;
printTopologyInfo();
std::cout << "\n";
h.write64(p, value);
}
value = h.read64(p);
extractBitsPrintHelper(bits, value, dec);
std::cout << " from TPMI ID " << requestedID << "@" << requestedRelativeOffset << " for entry " << p << " in instance " << i;
printTopologyInfo();
std::cout << "\n\n";
};
if (entries.empty())
{
for (size_t p = 0; p < h.getNumEntries(); ++p)
{
entries.push_back(p);
}
}
for (const size_t p : entries)
{
if (p < h.getNumEntries())
{
one(p, value);
}
}
}
}
catch (std::exception &e)
{
std::cerr << "Error accessing registers: " << e.what() << "\n";
std::cerr << "Please check if the program can access MSR/PCICFG drivers.\n";
}
return 0;
}