Skip to content

Commit 1fe2509

Browse files
authored
Merge pull request #940 from intel/push-2025-04-22
Push 2025 04 22
2 parents 9899e74 + d93cd52 commit 1fe2509

15 files changed

+2545
-2355
lines changed

doc/PCM_RAW_README.md

+6
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,12 @@ Sample csv output (date,time,event_name,milliseconds_between_samples,TSC_cycles_
214214
```
215215
The unit can be logical core, memory channel, CHA, etc, depending on the event type.
216216

217+
218+
Show events available for the processor on the system:
219+
```
220+
pcm-raw -?
221+
```
222+
217223
--------------------------------------------------------------------------------
218224
Low-level access to Intel PMT telemetry data
219225
--------------------------------------------------------------------------------

doc/WINDOWS_HOWTO.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ _For support of systems with more than _**_64_**_ logical cores you need to comp
44

55
## Command-line utility
66

7-
1. Follow [Compile the windows MSR driver](#compile-the-windows-msr-driver) to compile the windows MSR driver (msr.sys). For Windows 7 and later versions you have to sign the msr.sys driver additionally ([http://msdn.microsoft.com/en-us/library/ms537361(VS.85).aspx](http://msdn.microsoft.com/en-us/library/ms537361(VS.85).aspx)). To enable loading test signed drivers on the system: in administrator cmd console run `bcdedit /set testsigning on` and reboot.
7+
1. Follow [Compile the Windows MSR driver](#compile-the-windows-msr-driver) to compile the Windows MSR driver (msr.sys). For Windows 7 and later versions you have to sign the msr.sys driver additionally ([http://msdn.microsoft.com/en-us/library/ms537361(VS.85).aspx](http://msdn.microsoft.com/en-us/library/ms537361(VS.85).aspx)). To enable loading test-signed drivers on the system: in administrator cmd console run `bcdedit /set testsigning on` and reboot.
88

99
2. Build the *pcm.exe* utility:
1010
```
@@ -17,7 +17,7 @@ _For support of systems with more than _**_64_**_ logical cores you need to comp
1717
4. As Administrator copy the msr.sys driver and pcm.exe into the PCM directory
1818
5. Run pcm.exe utility from the PCM directory as Administrator
1919

20-
For Windows 7+ and Windows Server 2008+ R2 the PCM utilities need to be run as administrator:
20+
For Windows 7+ and Windows Server 2008+ R2 the PCM utilities need to be run as Administrator:
2121

2222
Alternatively you can achieve the same using the “Properties” Windows menu of the executable (“Privilege level” setting in the “Compatibility” tab): Right mouse click -> Properties -> Compatibility -> Privilege level -> Set “Run this program as an administrator”.
2323

@@ -47,13 +47,14 @@ Unhandled Exception: System.NotSupportedException: This method implicitly uses C
4747

4848
8. Start perfmon and find new PCM\* counters
4949

50-
If you do not want or cannot compile the msr.sys driver you might use a third-party open source WinRing0 driver instead. Instructions:
50+
If you do not want or cannot compile the msr.sys driver you might use a third-party open source WinRing0 driver instead (experimental only, for testing environments only).
51+
Instructions:
5152

5253
1. Download the free RealTemp utility package from [http://www.techpowerup.com/realtemp/](http://www.techpowerup.com/realtemp/) or any other free utility that uses the open-source WinRing0 driver (like OpenHardwareMonitor [http://code.google.com/p/open-hardware-monitor/downloads/list](http://code.google.com/p/open-hardware-monitor/downloads/list)).
5354
2. Copy WinRing0.dll, WinRing0.sys, WinRing0x64.dll, WinRing0x64.sys files from there into the PCM.exe binary location, into the PCM-Service.exe location and into c:\windows\system32
5455
3. Run the PCM.exe tool and/or go to step 6 (perfmon utility).
5556

56-
## Compile the windows MSR driver
57+
## Compile the Windows MSR driver
5758

5859
1. Download Visual Studio ([Visual Studio download](https://visualstudio.microsoft.com/downloads/)).
5960
When you install Visual Studio, also install related packages:

src/CMakeLists.txt

+5-5
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ set(PROJECT_NAMES pcm pcm-numa pcm-latency pcm-power pcm-msr pcm-memory pcm-tsx
88

99
set(MINIMUM_OPENSSL_VERSION 1.1.1)
1010

11-
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 ${PCM_PUGIXML_CPP})
11+
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 pcm-iio-pmu.cpp lspci.cpp ${PCM_PUGIXML_CPP})
1212

1313
if (APPLE)
14-
file(GLOB UNUX_SOURCES dashboard.cpp)
14+
file(GLOB UNIX_SOURCES dashboard.cpp)
1515
else()
16-
file(GLOB UNUX_SOURCES dashboard.cpp resctrl.cpp)
16+
file(GLOB UNIX_SOURCES dashboard.cpp resctrl.cpp)
1717
endif()
1818

1919
if (LINUX)
@@ -49,11 +49,11 @@ if(UNIX) # LINUX, FREE_BSD, APPLE
4949
list(APPEND PROJECT_NAMES pcm-sensor)
5050

5151
# libpcm.a
52-
add_library(PCM_STATIC STATIC ${COMMON_SOURCES} ${UNUX_SOURCES})
52+
add_library(PCM_STATIC STATIC ${COMMON_SOURCES} ${UNIX_SOURCES})
5353
set_target_properties(PCM_STATIC PROPERTIES OUTPUT_NAME pcm)
5454

5555
# libpcm.a with -DPCM_SILENT for Release*
56-
add_library(PCM_STATIC_SILENT STATIC ${COMMON_SOURCES} ${UNUX_SOURCES})
56+
add_library(PCM_STATIC_SILENT STATIC ${COMMON_SOURCES} ${UNIX_SOURCES})
5757
target_compile_definitions(PCM_STATIC_SILENT PRIVATE
5858
$<$<CONFIG:Release>:PCM_SILENT>
5959
$<$<CONFIG:MinSizeRel>:PCM_SILENT>

src/cpucounters.cpp

+20-2
Original file line numberDiff line numberDiff line change
@@ -2652,7 +2652,7 @@ void PCM::initUncorePMUsDirect()
26522652
std::vector<std::pair<uint32, uint32> > socket2QATbus;
26532653
std::map<int, int> rootbusMap;
26542654

2655-
//Enumurate IDX devices by PCIe bus scan
2655+
//Enumerate IDX devices by PCIe bus scan
26562656
initSocket2Bus(socket2IAAbus, SPR_IDX_IAA_REGISTER_DEV_ADDR, SPR_IDX_IAA_REGISTER_FUNC_ADDR, IAA_DEV_IDS, (uint32)sizeof(IAA_DEV_IDS) / sizeof(IAA_DEV_IDS[0]));
26572657
initSocket2Bus(socket2DSAbus, SPR_IDX_DSA_REGISTER_DEV_ADDR, SPR_IDX_DSA_REGISTER_FUNC_ADDR, DSA_DEV_IDS, (uint32)sizeof(DSA_DEV_IDS) / sizeof(DSA_DEV_IDS[0]));
26582658
initSocket2Bus(socket2QATbus, SPR_IDX_QAT_REGISTER_DEV_ADDR, SPR_IDX_QAT_REGISTER_FUNC_ADDR, QAT_DEV_IDS, (uint32)sizeof(QAT_DEV_IDS) / sizeof(QAT_DEV_IDS[0]));
@@ -4192,10 +4192,18 @@ PCM::ErrorCode PCM::programCoreCounters(const int i /* core */,
41924192

41934193
if (EXT_CUSTOM_CORE_EVENTS == mode_ && pExtDesc)
41944194
{
4195-
if (pExtDesc->OffcoreResponseMsrValue[0]) // still need to do also if perf API is used due to a bug in perf
4195+
if (pExtDesc->OffcoreResponseMsrValue[0]) // still need to do also if perf API is used due to a bug in perf in some kernels
4196+
{
4197+
DBG(3, "programming offcore response 0x", std::hex , pExtDesc->OffcoreResponseMsrValue[0] ,
4198+
" into MSR 0x" , MSR_OFFCORE_RSP0 , std::dec , " for core ", i);
41964199
MSR[i]->write(MSR_OFFCORE_RSP0, pExtDesc->OffcoreResponseMsrValue[0]);
4200+
}
41974201
if (pExtDesc->OffcoreResponseMsrValue[1])
4202+
{
4203+
DBG(3, "programming offcore response 0x", std::hex , pExtDesc->OffcoreResponseMsrValue[1] ,
4204+
" into MSR 0x" , MSR_OFFCORE_RSP1 , std::dec , " for core ", i);
41984205
MSR[i]->write(MSR_OFFCORE_RSP1, pExtDesc->OffcoreResponseMsrValue[1]);
4206+
}
41994207

42004208
if (pExtDesc->LoadLatencyMsrValue != ExtendedCustomCoreEventDescription::invalidMsrValue())
42014209
{
@@ -4268,9 +4276,19 @@ PCM::ErrorCode PCM::programCoreCounters(const int i /* core */,
42684276
if (pExtDesc != nullptr)
42694277
{
42704278
if (event_select_reg.fields.event_select == getOCREventNr(0, i).first && event_select_reg.fields.umask == getOCREventNr(0, i).second)
4279+
{
4280+
DBG(3, "writing offcore response 0x", std::hex , pExtDesc->OffcoreResponseMsrValue[0] ,
4281+
" into perf config1 for core ", std::dec , i, std::hex ," event 0x", event_select_reg.fields.event_select, " umask 0x", event_select_reg.fields.umask ,
4282+
" on counter ", std::dec , j);
42714283
e.config1 = pExtDesc->OffcoreResponseMsrValue[0];
4284+
}
42724285
if (event_select_reg.fields.event_select == getOCREventNr(1, i).first && event_select_reg.fields.umask == getOCREventNr(1, i).second)
4286+
{
4287+
DBG(3, "writing offcore response 0x", std::hex , pExtDesc->OffcoreResponseMsrValue[1] ,
4288+
" into perf config1 for core ", std::dec , i, std::hex , " event 0x", event_select_reg.fields.event_select, " umask 0x", event_select_reg.fields.umask ,
4289+
" on counter ", std::dec , j);
42734290
e.config1 = pExtDesc->OffcoreResponseMsrValue[1];
4291+
}
42744292

42754293
if (event_select_reg.fields.event_select == LOAD_LATENCY_EVTNR && event_select_reg.fields.umask == LOAD_LATENCY_UMASK)
42764294
{

src/cpucounters.h

+19-1
Original file line numberDiff line numberDiff line change
@@ -1666,6 +1666,7 @@ class PCM_API PCM
16661666
std::pair<unsigned, unsigned> getOCREventNr(const int event, const unsigned coreID) const
16671667
{
16681668
assert (coreID < topology.size());
1669+
const auto eCoreOCREvent = std::make_pair(OFFCORE_RESPONSE_0_EVTNR, event + 1);
16691670
if (hybrid)
16701671
{
16711672
switch (cpu_family_model)
@@ -1677,7 +1678,7 @@ class PCM_API PCM
16771678
case ARL:
16781679
if (topology[coreID].core_type == TopologyEntry::Atom)
16791680
{
1680-
return std::make_pair(OFFCORE_RESPONSE_0_EVTNR, event + 1);
1681+
return eCoreOCREvent;
16811682
}
16821683
break;
16831684
}
@@ -1688,13 +1689,30 @@ class PCM_API PCM
16881689
case SPR:
16891690
case EMR:
16901691
case GNR:
1692+
case GNR_D:
16911693
case ADL: // ADL big core (GLC)
16921694
case RPL:
16931695
case MTL:
16941696
case LNL:
16951697
case ARL:
16961698
useGLCOCREvent = true;
16971699
break;
1700+
1701+
case ATOM:
1702+
case ATOM_2:
1703+
case CENTERTON:
1704+
case BAYTRAIL:
1705+
case AVOTON:
1706+
case CHERRYTRAIL:
1707+
case APOLLO_LAKE:
1708+
case GEMINI_LAKE:
1709+
case DENVERTON:
1710+
case SNOWRIDGE:
1711+
case ELKHART_LAKE:
1712+
case JASPER_LAKE:
1713+
case SRF:
1714+
case GRR:
1715+
return eCoreOCREvent;
16981716
}
16991717
switch (event)
17001718
{

src/lspci.cpp

+167
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
#include "lspci.h"
2+
3+
namespace pcm {
4+
5+
const ccr_config ccr::skx_ccrs(44, 0xFFULL);
6+
const ccr_config ccr::icx_ccrs(48, 0xFFFULL);
7+
8+
bool operator<(const iio_stack& lh, const iio_stack& rh)
9+
{
10+
return lh.iio_unit_id < rh.iio_unit_id;
11+
}
12+
13+
bool operator<(const bdf &l, const bdf &r) {
14+
if (l.domainno < r.domainno)
15+
return true;
16+
if (l.domainno > r.domainno)
17+
return false;
18+
if (l.busno < r.busno)
19+
return true;
20+
if (l.busno > r.busno)
21+
return false;
22+
if (l.devno < r.devno)
23+
return true;
24+
if (l.devno > r.devno)
25+
return false;
26+
if (l.funcno < r.funcno)
27+
return true;
28+
if (l.funcno > r.funcno)
29+
return false;
30+
31+
return false; // bdf == bdf
32+
}
33+
34+
void probe_capability_pci_express(struct pci *p, uint32_t cap_ptr)
35+
{
36+
struct cap {
37+
union {
38+
struct {
39+
uint8_t id;
40+
union {
41+
uint8_t next;
42+
uint8_t cap_ptr;
43+
};
44+
uint16_t junk;
45+
};
46+
uint32 dw0;
47+
};
48+
} cap;
49+
uint32 value;
50+
PciHandleType h(0, p->bdf.busno, p->bdf.devno, p->bdf.funcno);
51+
h.read32(cap_ptr, &value); //Capability pointer
52+
cap.dw0 = value;
53+
if (cap.id != 0x10 && cap.next != 0x00) {
54+
probe_capability_pci_express(p, cap.cap_ptr);
55+
} else {
56+
if (cap.id == 0x10) { // We're in PCI express capability structure
57+
h.read32(cap_ptr+0x10, &value);
58+
p->link_info = value;
59+
} else { /*Finish recursive searching but cannot find PCI express capability structure*/ }
60+
}
61+
}
62+
63+
bool probe_pci(struct pci *p)
64+
{
65+
uint32 value;
66+
p->exist = false;
67+
struct bdf *bdf = &p->bdf;
68+
if (PciHandleType::exists(bdf->domainno, bdf->busno, bdf->devno, bdf->funcno)) {
69+
PciHandleType h(bdf->domainno, bdf->busno, bdf->devno, bdf->funcno);
70+
// VID:DID
71+
h.read32(0x0, &value);
72+
// Invalid VID::DID
73+
if (value != (std::numeric_limits<unsigned int>::max)()) {
74+
p->offset_0 = value;
75+
h.read32(0xc, &value);
76+
p->header_type = (value >> 16) & 0x7f;
77+
if (p->header_type == 0) {
78+
// Status register
79+
h.read32(0x4, &value);
80+
// Capability list == true
81+
if (value & 0x100000) {
82+
// Capability pointer
83+
h.read32(0x34, &value);
84+
probe_capability_pci_express(p, value);
85+
}
86+
} else if (p->header_type == 1) {
87+
h.read32(0x18, &value);
88+
p->offset_18 = value;
89+
}
90+
p->exist = true;
91+
}
92+
}
93+
94+
return p->exist;
95+
}
96+
97+
void print_pci(struct pci p, const PCIDB & pciDB)
98+
{
99+
printf("Parent bridge info:");
100+
printf("%x:%x.%d [%04x:%04x] %s %s %d P:%x S:%x S:%x ",
101+
p.bdf.busno, p.bdf.devno, p.bdf.funcno,
102+
p.vendor_id, p.device_id,
103+
(pciDB.first.count(p.vendor_id) > 0)?pciDB.first.at(p.vendor_id).c_str():"unknown vendor",
104+
(pciDB.second.count(p.vendor_id) > 0 && pciDB.second.at(p.vendor_id).count(p.device_id) > 0)?pciDB.second.at(p.vendor_id).at(p.device_id).c_str():"unknown device",
105+
p.header_type,
106+
p.primary_bus_number, p.secondary_bus_number, p.subordinate_bus_number);
107+
printf("Device info:");
108+
printf("%x:%x.%d [%04x:%04x] %s %s %d Gen%d x%d\n",
109+
p.bdf.busno, p.bdf.devno, p.bdf.funcno,
110+
p.vendor_id, p.device_id,
111+
(pciDB.first.count(p.vendor_id) > 0)?pciDB.first.at(p.vendor_id).c_str():"unknown vendor",
112+
(pciDB.second.count(p.vendor_id) > 0 && pciDB.second.at(p.vendor_id).count(p.device_id) > 0)?pciDB.second.at(p.vendor_id).at(p.device_id).c_str():"unknown device",
113+
p.header_type,
114+
p.link_speed, p.link_width);
115+
}
116+
117+
void load_PCIDB(PCIDB & pciDB)
118+
{
119+
std::ifstream in(PCI_IDS_PATH);
120+
std::string line, item;
121+
122+
if (!in.is_open())
123+
{
124+
#ifndef _MSC_VER
125+
// On Unix, try PCI_IDS_PATH2
126+
in.open(PCI_IDS_PATH2);
127+
}
128+
129+
if (!in.is_open())
130+
{
131+
// On Unix, try the current directory if the default path failed
132+
in.open("pci.ids");
133+
}
134+
135+
if (!in.is_open())
136+
{
137+
#endif
138+
std::cerr << PCI_IDS_NOT_FOUND << "\n";
139+
return;
140+
}
141+
142+
int vendorID = -1;
143+
144+
while (std::getline(in, line)) {
145+
// Ignore any line starting with #
146+
if (line.size() == 0 || line[0] == '#')
147+
continue;
148+
149+
if (line[0] == '\t' && line[1] == '\t')
150+
{
151+
// subvendor subdevice subsystem_name
152+
continue;
153+
}
154+
if (line[0] == '\t')
155+
{
156+
int deviceID = stoi(line.substr(1,4),0,16);
157+
//std::cout << vendorID << ";" << vendorName << ";" << deviceID << ";" << line.substr(7) << "\n";
158+
pciDB.second[vendorID][deviceID] = line.substr(7);
159+
continue;
160+
}
161+
// vendor
162+
vendorID = stoi(line.substr(0,4),0,16);
163+
pciDB.first[vendorID] = line.substr(6);
164+
}
165+
}
166+
167+
} // Namespace pcm

0 commit comments

Comments
 (0)