Skip to content

Commit

Permalink
Merge tag '2025-02-07' into push-2025-02-07
Browse files Browse the repository at this point in the history
Change-Id: If0174c385944b316c4fdea92bf52b90a9a8f8454
  • Loading branch information
rdementi committed Feb 7, 2025
2 parents 2d0ca76 + 73f0cab commit 3d8a718
Show file tree
Hide file tree
Showing 8 changed files with 257 additions and 2 deletions.
4 changes: 3 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ FROM fedora:41@sha256:3ec60eb34fa1a095c0c34dd37cead9fd38afb62612d43892fcf1d3425c
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2020-2024 Intel Corporation

RUN dnf -y install gcc-c++ git findutils make cmake openssl openssl-devel libasan libasan-static
RUN dnf -y install gcc-c++ git findutils make cmake openssl openssl-devel libasan libasan-static hwdata
COPY . /tmp/pcm
RUN cd /tmp/pcm && mkdir build && cd build && cmake -DPCM_NO_STATIC_LIBASAN=OFF .. && make -j

FROM fedora:41@sha256:3ec60eb34fa1a095c0c34dd37cead9fd38afb62612d43892fcf1d3425c32bc1e
COPY --from=builder /tmp/pcm/build/bin/* /usr/local/bin/
COPY --from=builder /tmp/pcm/build/bin/opCode*.txt /usr/local/share/pcm/
COPY --from=builder /usr/share/hwdata/pci.ids /usr/share/hwdata/pci.ids
ENV PCM_NO_PERF=1

ENTRYPOINT [ "/usr/local/bin/pcm-sensor-server", "-p", "9738", "-r" ]
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ Clone PCM repository with submodules:

```
git clone --recursive https://github.com/intel/pcm
cd pcm
```

or clone the repository first, and then update submodules with:
Expand Down
20 changes: 20 additions & 0 deletions doc/PCM_RAW_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,26 @@ Example (Icelake server iMC PMON MMIO register read):
mmio/config=0x3451,config1=0x22808,config2=1,config3=0x171D0000D0,config4=0x0c0b0000d8,width=64
```

TPMI Registers:

TPMI ([Topology Aware Register and PM Capsule Interface](https://github.com/intel/tpmi_power_management)) can be read with pcm-raw as follows:

```
tpmi/config=<tpmi_id>,config1=<offset>,config2=<static_or_freerun>[,name=<name>]
```

* tpmi_id: TPMI id
* offset: offset of the register
* static_or_freerun: same syntax as for MSR registers

Example:

```
tpmi/config=0x2,config1=0x18,name=BHS_UFS_CONTROL
```

From: https://github.com/intel/tpmi_power_management/blob/main/UFS_TPMI_public_disclosure_FINAL_rev4.pdf

--------------------------------------------------------------------------------
Collecting Events By Names From Event Lists (https://github.com/intel/perfmon/)
--------------------------------------------------------------------------------
Expand Down
125 changes: 125 additions & 0 deletions scripts/pcm-win-power-tray.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import pystray
from PIL import Image, ImageDraw, ImageFont
import threading
import time
import subprocess
import csv
import io

def create_image(text, background_color):
width = 12
height = 12
image = Image.new('RGB', (width, height), background_color)
draw = ImageDraw.Draw(image)

# Use the default font and scale it
font = ImageFont.load_default()

# Calculate text size and position
text_bbox = draw.textbbox((0, 0), text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
text_x = (width - text_width) // 2
text_y = -2 + (height - text_height) // 2

# Draw the text on the image
draw.text((text_x, text_y), text, fill="white", font=font)

# Scale the image down to fit the system tray icon size
image = image.resize((64, 64), Image.LANCZOS)

return image

# global process variable to kill the pcm.exe process when the icon is clicked
process = None

def update_icon(icon):
# Start the pcm.exe process with -csv 3 parameters
# store process into the global process variable
global process
process = subprocess.Popen(
# change the path to pcm.exe as needed
["..\\windows_build22\\bin\\Release\\pcm.exe", "-r", "-csv", "3"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)

count = 0

while True:
# find the header line to find the index of "SYSTEM Energy (Joules)"
if (count > 1000):
print (f"Can't find SYSTEM Energy (Joules) metric")
process.kill()
exit(0)
count = count + 1
line = process.stdout.readline()
csv_reader = csv.reader(io.StringIO(line))
header = next(csv_reader)
try:
system_energy_index = header.index("SYSTEM Energy (Joules)")
print (f"SYSTEM Energy (Joules) found at index {system_energy_index}")
break
except ValueError:
#print("SYSTEM Energy (Joules) not found in the header")
continue

# Skip the second header line
process.stdout.readline()

while True:
# Read the output line by line
line = process.stdout.readline()
# print (line)
if not line:
break

system_energy_joules = -1

# Parse the CSV output
csv_reader = csv.reader(io.StringIO(line))
for row in csv_reader:
# Extract the system power consumption in Watts
try:
system_energy_joules = float(row[system_energy_index])
print (f"SYSTEM Energy (Joules): {system_energy_joules}")
# Convert Joules to Watts
power_consumption_watts = system_energy_joules / 3.0
if (power_consumption_watts > 30) :
background_color = "red"
elif (power_consumption_watts > 20) :
background_color = "darkblue"
else:
background_color = "darkgreen"
# Update the icon with the current power consumption in Watts
icon.icon = create_image(f"{power_consumption_watts:.0f}", background_color)
except (IndexError, ValueError):
continue

if (system_energy_joules == -1):
continue

print (f"pcm.exe exited with code {process.returncode}")

def on_quit(icon, item):
icon.stop()
process.kill()

def main():
# Create the system tray icon
icon = pystray.Icon("Intel PCM: System Watts")
icon.icon = create_image("P", "darkblue")
icon.title = "Intel PCM: System Watts"
icon.menu = pystray.Menu(
pystray.MenuItem("Quit", on_quit)
)

# Start a thread to update the icon
threading.Thread(target=update_icon, args=(icon,), daemon=True).start()

# Run the icon
icon.run()

if __name__ == "__main__":
main()
52 changes: 52 additions & 0 deletions src/cpucounters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6171,6 +6171,31 @@ PCM::ErrorCode PCM::program(const RawPMUConfigs& curPMUConfigs_, const bool sile
addLocations(pcicfgConfig.programmable);
addLocations(pcicfgConfig.fixed);
}
else if (type == "tpmi")
{
tpmiConfig = pmuConfig.second;
auto addLocations = [this](const std::vector<RawEventConfig>& configs) {
for (const auto& c : configs)
{
if (TPMIRegisterLocations.find(c.first) == TPMIRegisterLocations.end())
{
// add locations
std::vector<TPMIRegisterEncoding> locations;
const auto tpmiID = c.first[TPMIEventPosition::ID];
const uint32 offset = (uint32)c.first[TPMIEventPosition::offset];
const auto numInstances = TPMIHandle::getNumInstances();
for (auto instance = 0ULL; instance < numInstances; ++instance)
{
std::shared_ptr<TPMIHandle> tpmiHandle = std::make_shared<TPMIHandle>(instance, tpmiID, offset);
locations.push_back(TPMIRegisterEncoding{ tpmiHandle });
}
TPMIRegisterLocations[c.first] = locations;
}
}
};
addLocations(tpmiConfig.programmable);
addLocations(tpmiConfig.fixed);
}
else if (type == "mmio")
{
mmioConfig = pmuConfig.second;
Expand Down Expand Up @@ -6686,6 +6711,32 @@ void PCM::readPCICFGRegisters(SystemCounterState& systemState)
}
}

void PCM::readTPMIRegisters(SystemCounterState& systemState)
{
auto read = [this, &systemState](const RawEventConfig& cfg) {
const RawEventEncoding& reEnc = cfg.first;
systemState.TPMIValues[reEnc].clear();
for (auto& h : TPMIRegisterLocations[reEnc])
{
if (h.get())
{
for (auto e = 0ULL; e < h->getNumEntries(); ++e)
{
systemState.TPMIValues[reEnc].push_back(h->read64(e));
}
}
}
};
for (const auto& cfg : tpmiConfig.programmable)
{
read(cfg);
}
for (const auto& cfg : tpmiConfig.fixed)
{
read(cfg);
}
}

void PCM::readMMIORegisters(SystemCounterState& systemState)
{
auto read = [this, &systemState](const RawEventConfig& cfg) {
Expand Down Expand Up @@ -6974,6 +7025,7 @@ void PCM::getAllCounterStates(SystemCounterState & systemState, std::vector<Sock
readPCICFGRegisters(systemState);
readMMIORegisters(systemState);
readPMTRegisters(systemState);
readTPMIRegisters(systemState);
}

for (auto & ar : asyncCoreResults)
Expand Down
39 changes: 38 additions & 1 deletion src/cpucounters.h
Original file line number Diff line number Diff line change
Expand Up @@ -1219,6 +1219,7 @@ class PCM_API PCM
void readQPICounters(SystemCounterState & counterState);
void readSystemEnergyStatus(SystemCounterState & systemState);
void readPCICFGRegisters(SystemCounterState& result);
void readTPMIRegisters(SystemCounterState& result);
void readMMIORegisters(SystemCounterState& result);
void readPMTRegisters(SystemCounterState& result);
void reportQPISpeed() const;
Expand Down Expand Up @@ -1521,6 +1522,34 @@ class PCM_API PCM
typedef std::map<std::string, RawPMUConfig> RawPMUConfigs;
ErrorCode program(const RawPMUConfigs& curPMUConfigs, const bool silent = false, const int pid = -1);

struct TPMIEventPosition
{
enum constants
{
ID = 0,
offset = 1,
type = 2
};
};
typedef std::shared_ptr<TPMIHandle> TPMIRegisterEncoding; // = TPMIHandle shared ptr
struct TPMIRegisterEncodingHash
{
std::size_t operator()(const RawEventEncoding & e) const
{
std::size_t h1 = std::hash<uint64>{}(e[TPMIEventPosition::ID]);
std::size_t h2 = std::hash<uint64>{}(e[TPMIEventPosition::offset]);
return h1 ^ (h2 << 1ULL);
}
};
struct TPMIRegisterEncodingCmp
{
bool operator ()(const RawEventEncoding& a, const RawEventEncoding& b) const
{
return a[TPMIEventPosition::ID] == b[TPMIEventPosition::ID]
&& a[TPMIEventPosition::offset] == b[TPMIEventPosition::offset];
}
};

struct PCICFGEventPosition
{
enum constants
Expand Down Expand Up @@ -1619,6 +1648,7 @@ class PCM_API PCM
};
typedef std::shared_ptr<TelemetryArray> PMTRegisterEncoding; // TelemetryArray shared ptr
private:
std::unordered_map<RawEventEncoding, std::vector<TPMIRegisterEncoding>, TPMIRegisterEncodingHash, TPMIRegisterEncodingCmp> TPMIRegisterLocations{};
std::unordered_map<RawEventEncoding, std::vector<PCICFGRegisterEncoding>, PCICFGRegisterEncodingHash, PCICFGRegisterEncodingCmp> PCICFGRegisterLocations{};
std::unordered_map<RawEventEncoding, std::vector<MMIORegisterEncoding>, MMIORegisterEncodingHash, MMIORegisterEncodingCmp> MMIORegisterLocations{};
std::unordered_map<RawEventEncoding, std::vector<PMTRegisterEncoding>, PMTRegisterEncodingHash, PMTRegisterEncodingCmp> PMTRegisterLocations{};
Expand Down Expand Up @@ -1933,7 +1963,7 @@ class PCM_API PCM
}
return false;
}
RawPMUConfig threadMSRConfig{}, packageMSRConfig{}, pcicfgConfig{}, mmioConfig{}, pmtConfig{};
RawPMUConfig threadMSRConfig{}, packageMSRConfig{}, tpmiConfig{}, pcicfgConfig{}, mmioConfig{}, pmtConfig{};
public:

//! \brief Reads CPU family
Expand Down Expand Up @@ -3922,6 +3952,7 @@ class SocketCounterState : public BasicCounterState, public UncoreCounterState
class SystemCounterState : public SocketCounterState
{
friend class PCM;
friend std::vector<uint64> getTPMIEvent(const PCM::RawEventEncoding& eventEnc, const SystemCounterState& before, const SystemCounterState& after);
friend std::vector<uint64> getPCICFGEvent(const PCM::RawEventEncoding& eventEnc, const SystemCounterState& before, const SystemCounterState& after);
friend std::vector<uint64> getMMIOEvent(const PCM::RawEventEncoding& eventEnc, const SystemCounterState& before, const SystemCounterState& after);
friend std::vector<uint64> getPMTEvent(const PCM::RawEventEncoding& eventEnc, const SystemCounterState& before, const SystemCounterState& after);
Expand All @@ -3933,6 +3964,7 @@ class SystemCounterState : public SocketCounterState
std::vector<std::vector<uint64> > TxL0Cycles;
uint64 uncoreTSC;
uint64 systemEnergyStatus;
std::unordered_map<PCM::RawEventEncoding, std::vector<uint64> , PCM::TPMIRegisterEncodingHash, PCM::TPMIRegisterEncodingCmp> TPMIValues{};
std::unordered_map<PCM::RawEventEncoding, std::vector<uint64> , PCM::PCICFGRegisterEncodingHash, PCM::PCICFGRegisterEncodingCmp> PCICFGValues{};
std::unordered_map<PCM::RawEventEncoding, std::vector<uint64>, PCM::MMIORegisterEncodingHash, PCM::MMIORegisterEncodingCmp> MMIOValues{};
std::unordered_map<PCM::RawEventEncoding, std::vector<uint64>, PCM::PMTRegisterEncodingHash2> PMTValues{};
Expand Down Expand Up @@ -5307,6 +5339,11 @@ inline std::vector<uint64> getRegisterEvent(const PCM::RawEventEncoding& eventEn
return result;
}

inline std::vector<uint64> getTPMIEvent(const PCM::RawEventEncoding & eventEnc, const SystemCounterState& before, const SystemCounterState& after)
{
return getRegisterEvent(eventEnc, before.TPMIValues, after.TPMIValues);
}

inline std::vector<uint64> getPCICFGEvent(const PCM::RawEventEncoding & eventEnc, const SystemCounterState& before, const SystemCounterState& after)
{
return getRegisterEvent(eventEnc, before.PCICFGValues, after.PCICFGValues);
Expand Down
17 changes: 17 additions & 0 deletions src/pcm-raw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1274,6 +1274,15 @@ std::string getMSREventString(const uint64 & index, const std::string & type, co
return c.str();
}

std::string getTPMIEventString(const PCM::RawEventEncoding & eventEnc, const std::string& type)
{
std::stringstream c;
c << type << "/TPMI_ID 0x" << std::hex << eventEnc[PCM::TPMIEventPosition::ID]
<< "/offset 0x" << eventEnc[PCM::TPMIEventPosition::offset] << "/"
<< getTypeString(eventEnc[PCM::TPMIEventPosition::type]);
return c.str();
}

std::string getPCICFGEventString(const PCM::RawEventEncoding & eventEnc, const std::string& type)
{
std::stringstream c;
Expand Down Expand Up @@ -1690,6 +1699,10 @@ void printTransposed(const PCM::RawPMUConfigs& curPMUConfigs,
{
printMSRRows(MSRScope::Package);
}
else if (type == "tpmi")
{
printRegisterRows(getTPMIEventString, getTPMIEvent);
}
else if (type == "pcicfg")
{
printRegisterRows(getPCICFGEventString, getPCICFGEvent);
Expand Down Expand Up @@ -2114,6 +2127,10 @@ void print(const PCM::RawPMUConfigs& curPMUConfigs,
{
printRegisters(getPCICFGEventString, getPCICFGEvent);
}
else if (type == "tpmi")
{
printRegisters(getTPMIEventString, getTPMIEvent);
}
else if (type == "mmio")
{
printRegisters(getMMIOEventString, getMMIOEvent);
Expand Down
1 change: 1 addition & 0 deletions src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,7 @@ bool isRegisterEvent(const std::string & pmu)
if (pmu == "mmio"
|| pmu == "pcicfg"
|| pmu == "pmt"
|| pmu == "tpmi"
|| pmu == "package_msr"
|| pmu == "thread_msr")
{
Expand Down

0 comments on commit 3d8a718

Please sign in to comment.