Skip to content

Commit efdf5f6

Browse files
authored
Merge pull request #115 from powerapi-ng/feat/msr-pmu-events
feat: Add `msr` PMU events encoding
2 parents d916f76 + 5e4d567 commit efdf5f6

File tree

3 files changed

+68
-22
lines changed

3 files changed

+68
-22
lines changed

Dockerfile

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,11 @@
1-
# libpfm dependency builder image
2-
FROM ubuntu:24.04 as libpfm-builder
3-
ENV DEBIAN_FRONTEND=noninteractive
4-
RUN apt update && \
5-
apt install -y build-essential git devscripts debhelper libncurses-dev && \
6-
git clone -b smartwatts https://github.com/gfieni/libpfm4.git /root/libpfm4 && \
7-
cd /root/libpfm4 && \
8-
sed -i 's/CONFIG_PFMLIB_NOPYTHON=n/CONFIG_PFMLIB_NOPYTHON=y/' debian/rules && \
9-
sed -i '/^Package: python-libpfm4$/,/^$/d' debian/control && \
10-
fakeroot debian/rules binary
11-
121
# sensor builder image (build tools + development dependencies):
132
FROM ubuntu:24.04 as sensor-builder
143
ENV DEBIAN_FRONTEND=noninteractive
154
ARG BUILD_TYPE=Debug
165
ARG MONGODB_SUPPORT=ON
176
RUN apt update && \
18-
apt install -y build-essential git clang-tidy cmake pkg-config libczmq-dev libjson-c-dev libsystemd-dev uuid-dev && \
7+
apt install -y build-essential git clang-tidy cmake pkg-config libczmq-dev libpfm4-dev libjson-c-dev libsystemd-dev uuid-dev && \
198
echo "${MONGODB_SUPPORT}" |grep -iq "on" && apt install -y libmongoc-dev || true
20-
COPY --from=libpfm-builder /root/libpfm4*.deb /tmp/
21-
RUN dpkg -i /tmp/libpfm4_*.deb /tmp/libpfm4-dev_*.deb && \
22-
rm /tmp/*.deb
239
COPY . /usr/src/hwpc-sensor
2410
RUN cd /usr/src/hwpc-sensor && \
2511
GIT_TAG=$(git describe --tags --dirty 2>/dev/null || echo "unknown") \
@@ -35,13 +21,10 @@ ARG MONGODB_SUPPORT=ON
3521
ARG FILE_CAPABILITY=CAP_SYS_ADMIN
3622
RUN useradd -d /opt/powerapi -m powerapi && \
3723
apt update && \
38-
apt install -y libczmq4 libjson-c5 libcap2-bin && \
24+
apt install -y libczmq4 libpfm4 libjson-c5 libcap2-bin && \
3925
echo "${MONGODB_SUPPORT}" |grep -iq "on" && apt install -y libmongoc-1.0-0 || true && \
4026
echo "${BUILD_TYPE}" |grep -iq "debug" && apt install -y libasan8 libubsan1 || true && \
4127
rm -rf /var/lib/apt/lists/*
42-
COPY --from=libpfm-builder /root/libpfm4*.deb /tmp/
43-
RUN dpkg -i /tmp/libpfm4_*.deb && \
44-
rm /tmp/*.deb
4528
COPY --from=sensor-builder /usr/src/hwpc-sensor/build/hwpc-sensor /usr/bin/hwpc-sensor
4629
RUN setcap "${FILE_CAPABILITY}+ep" /usr/bin/hwpc-sensor && \
4730
setcap -v "${FILE_CAPABILITY}+ep" /usr/bin/hwpc-sensor

src/events.c

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,66 @@
3636
#include "events.h"
3737
#include "util.h"
3838

39+
40+
static int
41+
setup_msr_perf_event_attr_type(struct perf_event_attr *attr)
42+
{
43+
const char pmu_type_path[PATH_MAX] = "/sys/devices/msr/type";
44+
FILE *f = NULL;
45+
char buffer[16] = {0}; /* uint32 expected */
46+
unsigned int pmu_type = 0;
47+
int ret = -1;
48+
49+
f = fopen(pmu_type_path, "r");
50+
if (f) {
51+
if (fgets(buffer, sizeof(buffer), f)) {
52+
if (!str_to_uint(buffer, &pmu_type)) {
53+
attr->type = pmu_type;
54+
ret = 0;
55+
}
56+
}
57+
58+
fclose(f);
59+
}
60+
61+
return ret;
62+
}
63+
64+
static int
65+
setup_msr_perf_event_attr_config(const char *event_name, struct perf_event_attr *attr)
66+
{
67+
/* events config from: https://github.com/torvalds/linux/blob/master/arch/x86/events/msr.c */
68+
const char *msr_events_name[] = {"tsc", "aperf", "mperf", "pperf", "smi", "ptsc", "irperf", "cpu_thermal_margin"};
69+
const uint64_t msr_events_config[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
70+
const size_t num_msr_events = sizeof(msr_events_name) / sizeof(msr_events_name[0]);
71+
char event_path[PATH_MAX] = {0};
72+
73+
for (size_t i = 0; i < num_msr_events; i++) {
74+
if (!strcasecmp(event_name, msr_events_name[i])) {
75+
snprintf(event_path, PATH_MAX, "/sys/devices/msr/events/%s", msr_events_name[i]);
76+
if (!access(event_path, F_OK)) {
77+
attr->config = msr_events_config[i];
78+
return 0;
79+
}
80+
}
81+
}
82+
83+
return -1;
84+
}
85+
86+
static int
87+
get_msr_pmu_event_encoding(const char *event_name, struct perf_event_attr *attr)
88+
{
89+
attr->size = sizeof(struct perf_event_attr);
90+
attr->disabled = 1;
91+
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_GROUP;
92+
93+
if (setup_msr_perf_event_attr_type(attr)) return -1;
94+
if (setup_msr_perf_event_attr_config(event_name, attr)) return -1;
95+
96+
return 0;
97+
}
98+
3999
static int
40100
setup_perf_event_attr(const char *event_name, struct perf_event_attr *attr)
41101
{
@@ -48,7 +108,10 @@ setup_perf_event_attr(const char *event_name, struct perf_event_attr *attr)
48108
arg.size = sizeof(pfm_perf_encode_arg_t);
49109
arg.attr = attr;
50110
if (pfm_get_os_event_encoding(event_name, PFM_PLM0 | PFM_PLM3, PFM_OS_PERF_EVENT_EXT, &arg) != PFM_SUCCESS) {
51-
return -1;
111+
/* fallback to MSR PMU event encoding if libpfm fails */
112+
if (get_msr_pmu_event_encoding(event_name, attr)) {
113+
return -1;
114+
}
52115
}
53116

54117
return 0;

src/util.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ str_to_uint(const char *str, unsigned int *out)
120120
errno = 0;
121121
value = strtoul(str, &str_endp, 0);
122122

123-
if (errno != 0 || str == str_endp || *str_endp != '\0') {
123+
if (errno != 0 || str == str_endp || (*str_endp != '\0' && *str_endp != '\n')) {
124124
return EINVAL;
125125
}
126126

@@ -141,7 +141,7 @@ str_to_int(const char *str, int *out)
141141
errno = 0;
142142
value = strtol(str, &str_endp, 0);
143143

144-
if (errno != 0 || str == str_endp || *str_endp != '\0') {
144+
if (errno != 0 || str == str_endp || (*str_endp != '\0' && *str_endp != '\n')) {
145145
return EINVAL;
146146
}
147147

0 commit comments

Comments
 (0)