Skip to content

Commit 2ed6b4c

Browse files
committed
Merge tag 'linux-cpupower-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux
Pull cpupower utility updates for 6.2-rc1 from Shuah Khan: "This cpupower update for Linux 6.2-rc1 consists of: - enhancement to choose base_cpu to display default cpupower details instead of picking cpu 0 and failing show information when it is offline. This change ensure user will see power information on the cpu the tool runs on. - adds Georgian translation to cpupower documentation. - introduces powercap intel-rapl library, powercap-info command, and rapl monitor. This adds the ability to show the used power consumption in for each rapl domain" * tag 'linux-cpupower-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux: cpupower: rapl monitor - shows the used power consumption in uj for each rapl domain cpupower: Introduce powercap intel-rapl library and powercap-info command cpupower: Add Georgian translation tools/cpupower: Choose base_cpu to display default cpupower details
2 parents 76dcd73 + 8c37df3 commit 2ed6b4c

14 files changed

Lines changed: 1642 additions & 13 deletions

File tree

tools/power/cpupower/Makefile

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,10 @@ UTIL_OBJS = utils/helpers/amd.o utils/helpers/msr.o \
131131
utils/idle_monitor/hsw_ext_idle.o \
132132
utils/idle_monitor/amd_fam14h_idle.o utils/idle_monitor/cpuidle_sysfs.o \
133133
utils/idle_monitor/mperf_monitor.o utils/idle_monitor/cpupower-monitor.o \
134+
utils/idle_monitor/rapl_monitor.o \
134135
utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \
135136
utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o \
136-
utils/cpuidle-set.o
137+
utils/cpuidle-set.o utils/powercap-info.o
137138

138139
UTIL_SRC := $(UTIL_OBJS:.o=.c)
139140

@@ -143,9 +144,12 @@ UTIL_HEADERS = utils/helpers/helpers.h utils/idle_monitor/cpupower-monitor.h \
143144
utils/helpers/bitmask.h \
144145
utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def
145146

146-
LIB_HEADERS = lib/cpufreq.h lib/cpupower.h lib/cpuidle.h lib/acpi_cppc.h
147-
LIB_SRC = lib/cpufreq.c lib/cpupower.c lib/cpuidle.c lib/acpi_cppc.c
148-
LIB_OBJS = lib/cpufreq.o lib/cpupower.o lib/cpuidle.o lib/acpi_cppc.o
147+
LIB_HEADERS = lib/cpufreq.h lib/cpupower.h lib/cpuidle.h lib/acpi_cppc.h \
148+
lib/powercap.h
149+
LIB_SRC = lib/cpufreq.c lib/cpupower.c lib/cpuidle.c lib/acpi_cppc.c \
150+
lib/powercap.c
151+
LIB_OBJS = lib/cpufreq.o lib/cpupower.o lib/cpuidle.o lib/acpi_cppc.o \
152+
lib/powercap.o
149153
LIB_OBJS := $(addprefix $(OUTPUT),$(LIB_OBJS))
150154

151155
override CFLAGS += -pipe
@@ -276,6 +280,7 @@ install-lib: libcpupower
276280
$(INSTALL) -d $(DESTDIR)${includedir}
277281
$(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h
278282
$(INSTALL_DATA) lib/cpuidle.h $(DESTDIR)${includedir}/cpuidle.h
283+
$(INSTALL_DATA) lib/powercap.h $(DESTDIR)${includedir}/powercap.h
279284

280285
install-tools: $(OUTPUT)cpupower
281286
$(INSTALL) -d $(DESTDIR)${bindir}
@@ -292,6 +297,7 @@ install-man:
292297
$(INSTALL_DATA) -D man/cpupower-set.1 $(DESTDIR)${mandir}/man1/cpupower-set.1
293298
$(INSTALL_DATA) -D man/cpupower-info.1 $(DESTDIR)${mandir}/man1/cpupower-info.1
294299
$(INSTALL_DATA) -D man/cpupower-monitor.1 $(DESTDIR)${mandir}/man1/cpupower-monitor.1
300+
$(INSTALL_DATA) -D man/cpupower-powercap-info.1 $(DESTDIR)${mandir}/man1/cpupower-powercap-info.1
295301

296302
install-gmo: create-gmo
297303
$(INSTALL) -d $(DESTDIR)${localedir}
@@ -321,6 +327,7 @@ uninstall:
321327
- rm -f $(DESTDIR)${mandir}/man1/cpupower-set.1
322328
- rm -f $(DESTDIR)${mandir}/man1/cpupower-info.1
323329
- rm -f $(DESTDIR)${mandir}/man1/cpupower-monitor.1
330+
- rm -f $(DESTDIR)${mandir}/man1/cpupower-powercap-info.1
324331
- for HLANG in $(LANGUAGES); do \
325332
rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \
326333
done;
Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* (C) 2016 SUSE Software Solutions GmbH
4+
* Thomas Renninger <trenn@suse.de>
5+
*/
6+
7+
#include <sys/types.h>
8+
#include <sys/stat.h>
9+
#include <unistd.h>
10+
#include <stdlib.h>
11+
#include <string.h>
12+
#include <fcntl.h>
13+
#include <stdio.h>
14+
#include <dirent.h>
15+
16+
#include "powercap.h"
17+
18+
static unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
19+
{
20+
int fd;
21+
ssize_t numread;
22+
23+
fd = open(path, O_RDONLY);
24+
if (fd == -1)
25+
return 0;
26+
27+
numread = read(fd, buf, buflen - 1);
28+
if (numread < 1) {
29+
close(fd);
30+
return 0;
31+
}
32+
33+
buf[numread] = '\0';
34+
close(fd);
35+
36+
return (unsigned int) numread;
37+
}
38+
39+
static int sysfs_get_enabled(char *path, int *mode)
40+
{
41+
int fd;
42+
char yes_no;
43+
44+
*mode = 0;
45+
46+
fd = open(path, O_RDONLY);
47+
if (fd == -1)
48+
return -1;
49+
50+
if (read(fd, &yes_no, 1) != 1) {
51+
close(fd);
52+
return -1;
53+
}
54+
55+
if (yes_no == '1') {
56+
*mode = 1;
57+
return 0;
58+
} else if (yes_no == '0') {
59+
return 0;
60+
}
61+
return -1;
62+
}
63+
64+
int powercap_get_enabled(int *mode)
65+
{
66+
char path[SYSFS_PATH_MAX] = PATH_TO_POWERCAP "/intel-rapl/enabled";
67+
68+
return sysfs_get_enabled(path, mode);
69+
}
70+
71+
/*
72+
* Hardcoded, because rapl is the only powercap implementation
73+
- * this needs to get more generic if more powercap implementations
74+
* should show up
75+
*/
76+
int powercap_get_driver(char *driver, int buflen)
77+
{
78+
char file[SYSFS_PATH_MAX] = PATH_TO_RAPL;
79+
80+
struct stat statbuf;
81+
82+
if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) {
83+
driver = "";
84+
return -1;
85+
} else if (buflen > 10) {
86+
strcpy(driver, "intel-rapl");
87+
return 0;
88+
} else
89+
return -1;
90+
}
91+
92+
enum powercap_get64 {
93+
GET_ENERGY_UJ,
94+
GET_MAX_ENERGY_RANGE_UJ,
95+
GET_POWER_UW,
96+
GET_MAX_POWER_RANGE_UW,
97+
MAX_GET_64_FILES
98+
};
99+
100+
static const char *powercap_get64_files[MAX_GET_64_FILES] = {
101+
[GET_POWER_UW] = "power_uw",
102+
[GET_MAX_POWER_RANGE_UW] = "max_power_range_uw",
103+
[GET_ENERGY_UJ] = "energy_uj",
104+
[GET_MAX_ENERGY_RANGE_UJ] = "max_energy_range_uj",
105+
};
106+
107+
static int sysfs_powercap_get64_val(struct powercap_zone *zone,
108+
enum powercap_get64 which,
109+
uint64_t *val)
110+
{
111+
char file[SYSFS_PATH_MAX] = PATH_TO_POWERCAP "/";
112+
int ret;
113+
char buf[MAX_LINE_LEN];
114+
115+
strcat(file, zone->sys_name);
116+
strcat(file, "/");
117+
strcat(file, powercap_get64_files[which]);
118+
119+
ret = sysfs_read_file(file, buf, MAX_LINE_LEN);
120+
if (ret < 0)
121+
return ret;
122+
if (ret == 0)
123+
return -1;
124+
125+
*val = strtoll(buf, NULL, 10);
126+
return 0;
127+
}
128+
129+
int powercap_get_max_energy_range_uj(struct powercap_zone *zone, uint64_t *val)
130+
{
131+
return sysfs_powercap_get64_val(zone, GET_MAX_ENERGY_RANGE_UJ, val);
132+
}
133+
134+
int powercap_get_energy_uj(struct powercap_zone *zone, uint64_t *val)
135+
{
136+
return sysfs_powercap_get64_val(zone, GET_ENERGY_UJ, val);
137+
}
138+
139+
int powercap_get_max_power_range_uw(struct powercap_zone *zone, uint64_t *val)
140+
{
141+
return sysfs_powercap_get64_val(zone, GET_MAX_POWER_RANGE_UW, val);
142+
}
143+
144+
int powercap_get_power_uw(struct powercap_zone *zone, uint64_t *val)
145+
{
146+
return sysfs_powercap_get64_val(zone, GET_POWER_UW, val);
147+
}
148+
149+
int powercap_zone_get_enabled(struct powercap_zone *zone, int *mode)
150+
{
151+
char path[SYSFS_PATH_MAX] = PATH_TO_POWERCAP;
152+
153+
if ((strlen(PATH_TO_POWERCAP) + strlen(zone->sys_name)) +
154+
strlen("/enabled") + 1 >= SYSFS_PATH_MAX)
155+
return -1;
156+
157+
strcat(path, "/");
158+
strcat(path, zone->sys_name);
159+
strcat(path, "/enabled");
160+
161+
return sysfs_get_enabled(path, mode);
162+
}
163+
164+
int powercap_zone_set_enabled(struct powercap_zone *zone, int mode)
165+
{
166+
/* To be done if needed */
167+
return 0;
168+
}
169+
170+
171+
int powercap_read_zone(struct powercap_zone *zone)
172+
{
173+
struct dirent *dent;
174+
DIR *zone_dir;
175+
char sysfs_dir[SYSFS_PATH_MAX] = PATH_TO_POWERCAP;
176+
struct powercap_zone *child_zone;
177+
char file[SYSFS_PATH_MAX] = PATH_TO_POWERCAP;
178+
int i, ret = 0;
179+
uint64_t val = 0;
180+
181+
strcat(sysfs_dir, "/");
182+
strcat(sysfs_dir, zone->sys_name);
183+
184+
zone_dir = opendir(sysfs_dir);
185+
if (zone_dir == NULL)
186+
return -1;
187+
188+
strcat(file, "/");
189+
strcat(file, zone->sys_name);
190+
strcat(file, "/name");
191+
sysfs_read_file(file, zone->name, MAX_LINE_LEN);
192+
if (zone->parent)
193+
zone->tree_depth = zone->parent->tree_depth + 1;
194+
ret = powercap_get_energy_uj(zone, &val);
195+
if (ret == 0)
196+
zone->has_energy_uj = 1;
197+
ret = powercap_get_power_uw(zone, &val);
198+
if (ret == 0)
199+
zone->has_power_uw = 1;
200+
201+
while ((dent = readdir(zone_dir)) != NULL) {
202+
struct stat st;
203+
204+
if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
205+
continue;
206+
207+
if (stat(dent->d_name, &st) != 0 || !S_ISDIR(st.st_mode))
208+
if (fstatat(dirfd(zone_dir), dent->d_name, &st, 0) < 0)
209+
continue;
210+
211+
if (strncmp(dent->d_name, "intel-rapl:", 11) != 0)
212+
continue;
213+
214+
child_zone = calloc(1, sizeof(struct powercap_zone));
215+
if (child_zone == NULL)
216+
return -1;
217+
for (i = 0; i < POWERCAP_MAX_CHILD_ZONES; i++) {
218+
if (zone->children[i] == NULL) {
219+
zone->children[i] = child_zone;
220+
break;
221+
}
222+
if (i == POWERCAP_MAX_CHILD_ZONES - 1) {
223+
free(child_zone);
224+
fprintf(stderr, "Reached POWERCAP_MAX_CHILD_ZONES %d\n",
225+
POWERCAP_MAX_CHILD_ZONES);
226+
return -1;
227+
}
228+
}
229+
strcpy(child_zone->sys_name, zone->sys_name);
230+
strcat(child_zone->sys_name, "/");
231+
strcat(child_zone->sys_name, dent->d_name);
232+
child_zone->parent = zone;
233+
if (zone->tree_depth >= POWERCAP_MAX_TREE_DEPTH) {
234+
fprintf(stderr, "Maximum zone hierarchy depth[%d] reached\n",
235+
POWERCAP_MAX_TREE_DEPTH);
236+
ret = -1;
237+
break;
238+
}
239+
powercap_read_zone(child_zone);
240+
}
241+
closedir(zone_dir);
242+
return ret;
243+
}
244+
245+
struct powercap_zone *powercap_init_zones(void)
246+
{
247+
int enabled;
248+
struct powercap_zone *root_zone;
249+
int ret;
250+
char file[SYSFS_PATH_MAX] = PATH_TO_RAPL "/enabled";
251+
252+
ret = sysfs_get_enabled(file, &enabled);
253+
254+
if (ret)
255+
return NULL;
256+
257+
if (!enabled)
258+
return NULL;
259+
260+
root_zone = calloc(1, sizeof(struct powercap_zone));
261+
if (!root_zone)
262+
return NULL;
263+
264+
strcpy(root_zone->sys_name, "intel-rapl/intel-rapl:0");
265+
266+
powercap_read_zone(root_zone);
267+
268+
return root_zone;
269+
}
270+
271+
/* Call function *f on the passed zone and all its children */
272+
273+
int powercap_walk_zones(struct powercap_zone *zone,
274+
int (*f)(struct powercap_zone *zone))
275+
{
276+
int i, ret;
277+
278+
if (!zone)
279+
return -1;
280+
281+
ret = f(zone);
282+
if (ret)
283+
return ret;
284+
285+
for (i = 0; i < POWERCAP_MAX_CHILD_ZONES; i++) {
286+
if (zone->children[i] != NULL)
287+
powercap_walk_zones(zone->children[i], f);
288+
}
289+
return 0;
290+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* (C) 2016 SUSE Software Solutions GmbH
4+
* Thomas Renninger <trenn@suse.de>
5+
*/
6+
7+
#ifndef __CPUPOWER_RAPL_H__
8+
#define __CPUPOWER_RAPL_H__
9+
10+
#define PATH_TO_POWERCAP "/sys/devices/virtual/powercap"
11+
#define PATH_TO_RAPL "/sys/devices/virtual/powercap/intel-rapl"
12+
#define PATH_TO_RAPL_CLASS "/sys/devices/virtual/powercap/intel-rapl"
13+
14+
#define POWERCAP_MAX_CHILD_ZONES 10
15+
#define POWERCAP_MAX_TREE_DEPTH 10
16+
17+
#define MAX_LINE_LEN 4096
18+
#define SYSFS_PATH_MAX 255
19+
20+
#include <stdint.h>
21+
22+
struct powercap_zone {
23+
char name[MAX_LINE_LEN];
24+
/*
25+
* sys_name relative to PATH_TO_POWERCAP,
26+
* do not forget the / in between
27+
*/
28+
char sys_name[SYSFS_PATH_MAX];
29+
int tree_depth;
30+
struct powercap_zone *parent;
31+
struct powercap_zone *children[POWERCAP_MAX_CHILD_ZONES];
32+
/* More possible caps or attributes to be added? */
33+
uint32_t has_power_uw:1,
34+
has_energy_uj:1;
35+
36+
};
37+
38+
int powercap_walk_zones(struct powercap_zone *zone,
39+
int (*f)(struct powercap_zone *zone));
40+
41+
struct powercap_zone *powercap_init_zones(void);
42+
int powercap_get_enabled(int *mode);
43+
int powercap_set_enabled(int mode);
44+
int powercap_get_driver(char *driver, int buflen);
45+
46+
int powercap_get_max_energy_range_uj(struct powercap_zone *zone, uint64_t *val);
47+
int powercap_get_energy_uj(struct powercap_zone *zone, uint64_t *val);
48+
int powercap_get_max_power_range_uw(struct powercap_zone *zone, uint64_t *val);
49+
int powercap_get_power_uw(struct powercap_zone *zone, uint64_t *val);
50+
int powercap_zone_get_enabled(struct powercap_zone *zone, int *mode);
51+
int powercap_zone_set_enabled(struct powercap_zone *zone, int mode);
52+
53+
54+
#endif /* __CPUPOWER_RAPL_H__ */

0 commit comments

Comments
 (0)