forked from pool/cpupower
Accepting request 1030431 from hardware
OBS-URL: https://build.opensuse.org/request/show/1030431 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/cpupower?expand=0&rev=55
This commit is contained in:
commit
84fb99eaaf
@ -1,3 +1,23 @@
|
||||
-------------------------------------------------------------------
|
||||
Fri Oct 21 13:59:41 UTC 2022 - Dominique Leuenberger <dimstar@opensuse.org>
|
||||
|
||||
- clean up sources: drop rapl_monitor.patch and
|
||||
cpupower_rapl.patch.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Oct 7 15:59:26 UTC 2022 - Callum Farmer <gmbr3@opensuse.org>
|
||||
|
||||
- Move bash-completion to subpackage so it isn't installed when
|
||||
not needed
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue Jul 5 09:02:11 UTC 2022 - Thomas Renninger <trenn@suse.de>
|
||||
|
||||
- Remove powercap capabilities to patch againt latest kernel sources
|
||||
-> still keep the patches, will be removed after trying to get this
|
||||
mainline
|
||||
- Add netlink (libnl-devel) requires
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Fri Apr 8 14:57:24 UTC 2022 - Dirk Müller <dmueller@suse.com>
|
||||
|
||||
|
@ -24,18 +24,18 @@
|
||||
%define version %(rpm -q --qf '%%{VERSION}' kernel-source)
|
||||
Name: cpupower
|
||||
Version: %{version}
|
||||
#Version: 5.19
|
||||
Release: 0
|
||||
Summary: Tools to determine and set CPU Power related Settings
|
||||
License: GPL-2.0-only
|
||||
Group: System/Base
|
||||
URL: https://git.kernel.org/cgit/linux/kernel/git/rafael/linux-pm.git
|
||||
Patch1: cpupower_rapl.patch
|
||||
Patch2: rapl_monitor.patch
|
||||
Patch3: cpupower_exclude_kernel_Makefile.patch
|
||||
Patch6: amd_do_not_show_amount_of_boost_states_if_zero.patch
|
||||
BuildRequires: gettext-tools
|
||||
BuildRequires: kernel-source
|
||||
BuildRequires: libcap-devel
|
||||
BuildRequires: libnl-devel
|
||||
BuildRequires: pciutils
|
||||
BuildRequires: pciutils-devel
|
||||
|
||||
@ -71,6 +71,16 @@ governor (e.g. ondemand, userspace, conservative) and the cpufreq HW driver
|
||||
For that purpose, it compares the performance governor to a configured
|
||||
powersave module.
|
||||
|
||||
%package bash-completion
|
||||
Summary: Bash completion for cpupower
|
||||
Group: System/Shells
|
||||
Requires: %{name}
|
||||
Requires: bash-completion
|
||||
Supplements: (%{name} and bash-completion)
|
||||
|
||||
%description bash-completion
|
||||
bash command line completion support for cpupower.
|
||||
|
||||
%package rebuild
|
||||
Summary: Empty package to ensure rebuilding cpupower in OBS
|
||||
Group: System/Monitoring
|
||||
@ -89,8 +99,6 @@ There is no reason to install this package.
|
||||
(cd %{_prefix}/src/linux ; tar -cf - COPYING CREDITS README tools include scripts Kbuild Makefile arch/*/{include,lib,Makefile} lib) | tar -xf -
|
||||
chmod +x tools/power/cpupower/utils/version-gen.sh
|
||||
cd %{maindir}
|
||||
%patch1 -p1
|
||||
%patch2 -p1
|
||||
%patch3 -p1
|
||||
%patch6 -p1
|
||||
|
||||
@ -126,7 +134,6 @@ mv %{buildroot}//%{_docdir}/%{name}/cpufreq-bench_script.sh %{buildroot}/%{_docd
|
||||
%postun -n libcpupower0 -p /sbin/ldconfig
|
||||
|
||||
%files
|
||||
%{_datadir}/bash-completion/completions/cpupower
|
||||
%{_mandir}/man1/cpupower*%{?ext_man}
|
||||
%{_bindir}/cpupower
|
||||
%ifarch %{ix86} x86_64
|
||||
@ -152,9 +159,14 @@ mv %{buildroot}//%{_docdir}/%{name}/cpufreq-bench_script.sh %{buildroot}/%{_docd
|
||||
%files devel
|
||||
%{_includedir}/cpufreq.h
|
||||
%{_includedir}/cpuidle.h
|
||||
%{_includedir}/powercap.h
|
||||
#%%{_includedir}/powercap.h
|
||||
%{_libdir}/libcpu*.so
|
||||
|
||||
%files bash-completion
|
||||
%dir %{_datadir}/bash-completion
|
||||
%dir %{_datadir}/bash-completion/completions
|
||||
%{_datadir}/bash-completion/completions/cpupower
|
||||
|
||||
%files lang -f %{name}.lang
|
||||
|
||||
%files rebuild
|
||||
|
@ -1,600 +0,0 @@
|
||||
cpupower: Introduce powercap intel-rapl library helpers and powercap-info command
|
||||
|
||||
Read out powercap zone information via:
|
||||
cpupower powercap-info
|
||||
and show the zone hierarchy to the user:
|
||||
|
||||
./cpupower powercap-info
|
||||
Driver: intel-rapl
|
||||
Powercap domain hierarchy:
|
||||
|
||||
Zone: package-0 (enabled)
|
||||
Power consumption can be monitored in micro Watts
|
||||
|
||||
Zone: core (disabled)
|
||||
Power consumption can be monitored in micro Watts
|
||||
|
||||
Zone: uncore (disabled)
|
||||
Power consumption can be monitored in micro Watts
|
||||
|
||||
Zone: dram (disabled)
|
||||
Power consumption can be monitored in micro Watts
|
||||
|
||||
There is a dummy -a option for powercap-info which can/should be used to show
|
||||
more detailed info later. Like that other args can be added easily later as well.
|
||||
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.com>
|
||||
|
||||
---
|
||||
Makefile | 11 +
|
||||
lib/powercap.c | 290 +++++++++++++++++++++++++++++++++++++++++++
|
||||
lib/powercap.h | 54 ++++++++
|
||||
man/cpupower-powercap-info.1 | 25 +++
|
||||
utils/builtin.h | 2
|
||||
utils/cpupower.c | 1
|
||||
utils/powercap-info.c | 113 ++++++++++++++++
|
||||
7 files changed, 492 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -133,7 +133,7 @@
|
||||
utils/idle_monitor/mperf_monitor.o utils/idle_monitor/cpupower-monitor.o \
|
||||
utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \
|
||||
utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o \
|
||||
- utils/cpuidle-set.o
|
||||
+ utils/cpuidle-set.o utils/powercap-info.o
|
||||
|
||||
UTIL_SRC := $(UTIL_OBJS:.o=.c)
|
||||
|
||||
@@ -143,9 +143,9 @@
|
||||
utils/helpers/bitmask.h \
|
||||
utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def
|
||||
|
||||
-LIB_HEADERS = lib/cpufreq.h lib/cpupower.h lib/cpuidle.h
|
||||
-LIB_SRC = lib/cpufreq.c lib/cpupower.c lib/cpuidle.c
|
||||
-LIB_OBJS = lib/cpufreq.o lib/cpupower.o lib/cpuidle.o
|
||||
+LIB_HEADERS = lib/cpufreq.h lib/cpupower.h lib/cpuidle.h lib/powercap.h
|
||||
+LIB_SRC = lib/cpufreq.c lib/cpupower.c lib/cpuidle.c lib/powercap.c
|
||||
+LIB_OBJS = lib/cpufreq.o lib/cpupower.o lib/cpuidle.o lib/powercap.o
|
||||
LIB_OBJS := $(addprefix $(OUTPUT),$(LIB_OBJS))
|
||||
|
||||
override CFLAGS += -pipe
|
||||
@@ -276,6 +276,7 @@
|
||||
$(INSTALL) -d $(DESTDIR)${includedir}
|
||||
$(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h
|
||||
$(INSTALL_DATA) lib/cpuidle.h $(DESTDIR)${includedir}/cpuidle.h
|
||||
+ $(INSTALL_DATA) lib/powercap.h $(DESTDIR)${includedir}/powercap.h
|
||||
|
||||
install-tools: $(OUTPUT)cpupower
|
||||
$(INSTALL) -d $(DESTDIR)${bindir}
|
||||
@@ -292,6 +293,7 @@
|
||||
$(INSTALL_DATA) -D man/cpupower-set.1 $(DESTDIR)${mandir}/man1/cpupower-set.1
|
||||
$(INSTALL_DATA) -D man/cpupower-info.1 $(DESTDIR)${mandir}/man1/cpupower-info.1
|
||||
$(INSTALL_DATA) -D man/cpupower-monitor.1 $(DESTDIR)${mandir}/man1/cpupower-monitor.1
|
||||
+ $(INSTALL_DATA) -D man/cpupower-powercap-info.1 $(DESTDIR)${mandir}/man1/cpupower-powercap-info.1
|
||||
|
||||
install-gmo: create-gmo
|
||||
$(INSTALL) -d $(DESTDIR)${localedir}
|
||||
@@ -321,6 +323,7 @@
|
||||
- rm -f $(DESTDIR)${mandir}/man1/cpupower-set.1
|
||||
- rm -f $(DESTDIR)${mandir}/man1/cpupower-info.1
|
||||
- rm -f $(DESTDIR)${mandir}/man1/cpupower-monitor.1
|
||||
+ - rm -f $(DESTDIR)${mandir}/man1/cpupower-powercap-info.1
|
||||
- for HLANG in $(LANGUAGES); do \
|
||||
rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \
|
||||
done;
|
||||
--- /dev/null
|
||||
+++ b/lib/powercap.c
|
||||
@@ -0,0 +1,290 @@
|
||||
+/*
|
||||
+ * (C) 2016 Thomas Renninger <trenn@suse.com>
|
||||
+ *
|
||||
+ * Licensed under the terms of the GNU GPL License version 2.
|
||||
+ */
|
||||
+
|
||||
+#include <sys/types.h>
|
||||
+#include <sys/stat.h>
|
||||
+#include <unistd.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <stdio.h>
|
||||
+#include <dirent.h>
|
||||
+
|
||||
+#include "powercap.h"
|
||||
+
|
||||
+static unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
|
||||
+{
|
||||
+ int fd;
|
||||
+ ssize_t numread;
|
||||
+
|
||||
+ fd = open(path, O_RDONLY);
|
||||
+ if (fd == -1)
|
||||
+ return 0;
|
||||
+
|
||||
+ numread = read(fd, buf, buflen - 1);
|
||||
+ if (numread < 1) {
|
||||
+ close(fd);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ buf[numread] = '\0';
|
||||
+ close(fd);
|
||||
+
|
||||
+ return (unsigned int) numread;
|
||||
+}
|
||||
+
|
||||
+static int sysfs_get_enabled(char *path, int *mode)
|
||||
+{
|
||||
+ int fd;
|
||||
+ char yes_no;
|
||||
+
|
||||
+ *mode = 0;
|
||||
+
|
||||
+ fd = open(path, O_RDONLY);
|
||||
+ if (fd == -1)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (read(fd, &yes_no, 1) != 1) {
|
||||
+ close(fd);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (yes_no == '1') {
|
||||
+ *mode = 1;
|
||||
+ return 0;
|
||||
+ } else if (yes_no == '0') {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+int powercap_get_enabled(int *mode)
|
||||
+{
|
||||
+ char path[SYSFS_PATH_MAX] = PATH_TO_POWERCAP "/intel-rapl/enabled";
|
||||
+ return sysfs_get_enabled(path, mode);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Hardcoded, because rapl is the only powercap implementation
|
||||
+- * this needs to get more generic if more powercap implementations
|
||||
+ * should show up
|
||||
+ */
|
||||
+int powercap_get_driver(char *driver, int buflen)
|
||||
+{
|
||||
+ char file[SYSFS_PATH_MAX] = PATH_TO_RAPL;
|
||||
+ struct stat statbuf;
|
||||
+
|
||||
+ if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) {
|
||||
+ driver = "";
|
||||
+ return -1;
|
||||
+ } else if (buflen > 10) {
|
||||
+ strcpy(driver, "intel-rapl");
|
||||
+ return 0;
|
||||
+ } else
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+enum powercap_get64 {
|
||||
+ GET_ENERGY_UJ,
|
||||
+ GET_MAX_ENERGY_RANGE_UJ,
|
||||
+ GET_POWER_UW,
|
||||
+ GET_MAX_POWER_RANGE_UW,
|
||||
+ MAX_GET_64_FILES
|
||||
+};
|
||||
+
|
||||
+static const char *powercap_get64_files[MAX_GET_64_FILES] = {
|
||||
+ [GET_POWER_UW] = "power_uw",
|
||||
+ [GET_MAX_POWER_RANGE_UW] = "max_power_range_uw",
|
||||
+ [GET_ENERGY_UJ] = "energy_uj",
|
||||
+ [GET_MAX_ENERGY_RANGE_UJ] = "max_energy_range_uj",
|
||||
+};
|
||||
+
|
||||
+static int sysfs_powercap_get64_val(struct powercap_zone *zone,
|
||||
+ enum powercap_get64 which,
|
||||
+ uint64_t *val)
|
||||
+{
|
||||
+ char file[SYSFS_PATH_MAX] = PATH_TO_POWERCAP "/";
|
||||
+ int ret;
|
||||
+ char buf[MAX_LINE_LEN];
|
||||
+
|
||||
+ strcat(file, zone->sys_name);
|
||||
+ strcat(file, "/");
|
||||
+ strcat (file, powercap_get64_files[which]);
|
||||
+
|
||||
+ ret = sysfs_read_file(file, buf, MAX_LINE_LEN);
|
||||
+ if (ret < 0 )
|
||||
+ return ret;
|
||||
+ if (ret == 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ *val = strtoll(buf, NULL, 10);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+int powercap_get_max_energy_range_uj (struct powercap_zone *zone, uint64_t *val)
|
||||
+{
|
||||
+ return sysfs_powercap_get64_val(zone, GET_MAX_ENERGY_RANGE_UJ, val);
|
||||
+}
|
||||
+
|
||||
+int powercap_get_energy_uj (struct powercap_zone *zone, uint64_t *val)
|
||||
+{
|
||||
+ return sysfs_powercap_get64_val(zone, GET_ENERGY_UJ, val);
|
||||
+}
|
||||
+
|
||||
+int powercap_get_max_power_range_uw (struct powercap_zone *zone, uint64_t *val)
|
||||
+{
|
||||
+ return sysfs_powercap_get64_val(zone, GET_MAX_POWER_RANGE_UW, val);
|
||||
+}
|
||||
+
|
||||
+int powercap_get_power_uw (struct powercap_zone *zone, uint64_t *val)
|
||||
+{
|
||||
+ return sysfs_powercap_get64_val(zone, GET_POWER_UW, val);
|
||||
+}
|
||||
+
|
||||
+int powercap_zone_get_enabled (struct powercap_zone *zone, int *mode)
|
||||
+{
|
||||
+ char path[SYSFS_PATH_MAX] = PATH_TO_POWERCAP;
|
||||
+
|
||||
+ if ((strlen(PATH_TO_POWERCAP) + strlen(zone->sys_name)) +
|
||||
+ strlen("/enabled") + 1 >= SYSFS_PATH_MAX)
|
||||
+ return -1;
|
||||
+
|
||||
+ strcat(path, "/");
|
||||
+ strcat(path, zone->sys_name);
|
||||
+ strcat(path, "/enabled");
|
||||
+
|
||||
+ return sysfs_get_enabled(path, mode);
|
||||
+}
|
||||
+
|
||||
+int powercap_zone_set_enabled (struct powercap_zone *zone, int mode)
|
||||
+{
|
||||
+ /* To be done if needed */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+int powercap_read_zone(struct powercap_zone *zone)
|
||||
+{
|
||||
+ struct dirent* dent;
|
||||
+ DIR* zone_dir;
|
||||
+ char sysfs_dir[SYSFS_PATH_MAX] = PATH_TO_POWERCAP;
|
||||
+ struct powercap_zone *child_zone;
|
||||
+ char file[SYSFS_PATH_MAX] = PATH_TO_POWERCAP;
|
||||
+ int i, ret = 0;
|
||||
+ uint64_t val = 0;
|
||||
+
|
||||
+ strcat(sysfs_dir, "/");
|
||||
+ strcat(sysfs_dir, zone->sys_name);
|
||||
+
|
||||
+ zone_dir = opendir(sysfs_dir);
|
||||
+ if (zone_dir == NULL)
|
||||
+ return -1;
|
||||
+
|
||||
+ strcat(file, "/");
|
||||
+ strcat(file, zone->sys_name);
|
||||
+ strcat(file, "/name");
|
||||
+ sysfs_read_file(file, zone->name, MAX_LINE_LEN);
|
||||
+ if (zone->parent)
|
||||
+ zone->tree_depth = zone->parent->tree_depth + 1;
|
||||
+ ret = powercap_get_energy_uj(zone, &val);
|
||||
+ if (ret == 0)
|
||||
+ zone->has_energy_uj = 1;
|
||||
+ ret = powercap_get_power_uw(zone, &val);
|
||||
+ if (ret == 0)
|
||||
+ zone->has_power_uw = 1;
|
||||
+
|
||||
+ while((dent = readdir(zone_dir)) != NULL) {
|
||||
+ struct stat st;
|
||||
+
|
||||
+ if(strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (stat(dent->d_name, &st) != 0 || !S_ISDIR(st.st_mode))
|
||||
+ if (fstatat(dirfd(zone_dir), dent->d_name, &st, 0) < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (strncmp(dent->d_name, "intel-rapl:", 11) != 0)
|
||||
+ continue;
|
||||
+
|
||||
+ child_zone = calloc(1, sizeof(struct powercap_zone));
|
||||
+ if (child_zone == NULL)
|
||||
+ return -1;
|
||||
+ for (i = 0; i < POWERCAP_MAX_CHILD_ZONES; i++) {
|
||||
+ if (zone->children[i] == NULL) {
|
||||
+ zone->children[i] = child_zone;
|
||||
+ break;
|
||||
+ }
|
||||
+ if (i == POWERCAP_MAX_CHILD_ZONES - 1) {
|
||||
+ free(child_zone);
|
||||
+ fprintf(stderr, "Reached POWERCAP_MAX_CHILD_ZONES %d\n",
|
||||
+ POWERCAP_MAX_CHILD_ZONES);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+ strcpy(child_zone->sys_name, zone->sys_name);
|
||||
+ strcat(child_zone->sys_name, "/");
|
||||
+ strcat(child_zone->sys_name, dent->d_name);
|
||||
+ child_zone->parent = zone;
|
||||
+ if (zone->tree_depth >= POWERCAP_MAX_TREE_DEPTH) {
|
||||
+ fprintf(stderr, "Maximum zone hierachy depth[%d] reached\n",
|
||||
+ POWERCAP_MAX_TREE_DEPTH);
|
||||
+ ret = -1;
|
||||
+ break;
|
||||
+ }
|
||||
+ powercap_read_zone(child_zone);
|
||||
+ }
|
||||
+ closedir(zone_dir);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+struct powercap_zone *powercap_init_zones()
|
||||
+{
|
||||
+ int enabled;
|
||||
+ struct powercap_zone *root_zone;
|
||||
+ int ret;
|
||||
+ char file[SYSFS_PATH_MAX] = PATH_TO_RAPL "/enabled";
|
||||
+
|
||||
+ ret = sysfs_get_enabled(file, &enabled);
|
||||
+
|
||||
+ if (ret)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (!enabled)
|
||||
+ return NULL;
|
||||
+
|
||||
+ root_zone = calloc(1, sizeof(struct powercap_zone));
|
||||
+ if (!root_zone)
|
||||
+ return NULL;
|
||||
+
|
||||
+ strcpy(root_zone->sys_name, "intel-rapl/intel-rapl:0");
|
||||
+
|
||||
+ powercap_read_zone(root_zone);
|
||||
+
|
||||
+ return root_zone;
|
||||
+}
|
||||
+
|
||||
+/* Call function *f on the passed zone and all its children */
|
||||
+
|
||||
+int powercap_walk_zones(struct powercap_zone *zone,
|
||||
+ int (*f)(struct powercap_zone *zone))
|
||||
+{
|
||||
+ int i, ret;
|
||||
+
|
||||
+ if (!zone)
|
||||
+ return -1;
|
||||
+
|
||||
+ ret = f(zone);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ for (i = 0; i < POWERCAP_MAX_CHILD_ZONES; i++) {
|
||||
+ if (zone->children[i] != NULL) {
|
||||
+ powercap_walk_zones(zone->children[i], f);
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/lib/powercap.h
|
||||
@@ -0,0 +1,54 @@
|
||||
+/*
|
||||
+ * (C) 2016 Thomas Renninger <trenn@suse.com>
|
||||
+ *
|
||||
+ * Licensed under the terms of the GNU GPL License version 2.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __CPUPOWER_RAPL_H__
|
||||
+#define __CPUPOWER_RAPL_H__
|
||||
+
|
||||
+#define PATH_TO_POWERCAP "/sys/devices/virtual/powercap"
|
||||
+#define PATH_TO_RAPL "/sys/devices/virtual/powercap/intel-rapl"
|
||||
+#define PATH_TO_RAPL_CLASS "/sys/devices/virtual/powercap/intel-rapl"
|
||||
+
|
||||
+#define POWERCAP_MAX_CHILD_ZONES 10
|
||||
+#define POWERCAP_MAX_TREE_DEPTH 10
|
||||
+
|
||||
+#define MAX_LINE_LEN 4096
|
||||
+#define SYSFS_PATH_MAX 255
|
||||
+
|
||||
+#include <stdint.h>
|
||||
+
|
||||
+struct powercap_zone {
|
||||
+ char name[MAX_LINE_LEN];
|
||||
+ /*
|
||||
+ * sys_name relative to PATH_TO_POWERCAP,
|
||||
+ * do not forget the / in between
|
||||
+ */
|
||||
+ char sys_name[SYSFS_PATH_MAX];
|
||||
+ int tree_depth;
|
||||
+ struct powercap_zone *parent;
|
||||
+ struct powercap_zone *children[POWERCAP_MAX_CHILD_ZONES];
|
||||
+ /* More possible caps or attributes to be added? */
|
||||
+ uint32_t has_power_uw:1,
|
||||
+ has_energy_uj:1;
|
||||
+
|
||||
+};
|
||||
+
|
||||
+int powercap_walk_zones(struct powercap_zone *zone,
|
||||
+ int (*f)(struct powercap_zone *zone));
|
||||
+
|
||||
+struct powercap_zone *powercap_init_zones();
|
||||
+int powercap_get_enabled(int *mode);
|
||||
+int powercap_set_enabled(int mode);
|
||||
+int powercap_get_driver(char *driver, int buflen);
|
||||
+
|
||||
+int powercap_get_max_energy_range_uj (struct powercap_zone *zone, uint64_t *val);
|
||||
+int powercap_get_energy_uj (struct powercap_zone *zone, uint64_t *val);
|
||||
+int powercap_get_max_power_range_uw (struct powercap_zone *zone , uint64_t *val);
|
||||
+int powercap_get_power_uw (struct powercap_zone *zone, uint64_t *val);
|
||||
+int powercap_zone_get_enabled (struct powercap_zone *zone, int *mode);
|
||||
+int powercap_zone_set_enabled (struct powercap_zone *zone, int mode);
|
||||
+
|
||||
+
|
||||
+#endif /* __CPUPOWER_RAPL_H__ */
|
||||
--- /dev/null
|
||||
+++ b/man/cpupower-powercap-info.1
|
||||
@@ -0,0 +1,25 @@
|
||||
+.TH CPUPOWER\-POWERCAP\-INFO "1" "05/08/2016" "" "cpupower Manual"
|
||||
+.SH NAME
|
||||
+cpupower\-powercap\-info \- Shows powercapping related kernel and hardware configurations
|
||||
+.SH SYNOPSIS
|
||||
+.ft B
|
||||
+.B cpupower powercap-info
|
||||
+
|
||||
+.SH DESCRIPTION
|
||||
+\fBcpupower powercap-info \fP shows kernel powercapping subsystem information.
|
||||
+This needs hardware support and a loaded powercapping driver (at this time only
|
||||
+intel_rapl driver exits) exporting hardware values userspace via sysfs.
|
||||
+
|
||||
+Some options are platform wide, some affect single cores. By default values
|
||||
+of core zero are displayed only. cpupower --cpu all cpuinfo will show the
|
||||
+settings of all cores, see cpupower(1) how to choose specific cores.
|
||||
+
|
||||
+.SH "DOCUMENTATION"
|
||||
+
|
||||
+kernel sources:
|
||||
+Documentation/power/powercap/powercap.txt
|
||||
+
|
||||
+
|
||||
+.SH "SEE ALSO"
|
||||
+
|
||||
+cpupower(1)
|
||||
--- a/utils/builtin.h
|
||||
+++ b/utils/builtin.h
|
||||
@@ -8,6 +8,8 @@
|
||||
extern int cmd_freq_info(int argc, const char **argv);
|
||||
extern int cmd_idle_set(int argc, const char **argv);
|
||||
extern int cmd_idle_info(int argc, const char **argv);
|
||||
+extern int cmd_cap_info(int argc, const char **argv);
|
||||
+extern int cmd_cap_set(int argc, const char **argv);
|
||||
extern int cmd_monitor(int argc, const char **argv);
|
||||
|
||||
#endif
|
||||
--- a/utils/cpupower.c
|
||||
+++ b/utils/cpupower.c
|
||||
@@ -54,6 +54,7 @@
|
||||
{ "frequency-set", cmd_freq_set, 1 },
|
||||
{ "idle-info", cmd_idle_info, 0 },
|
||||
{ "idle-set", cmd_idle_set, 1 },
|
||||
+ { "powercap-info", cmd_cap_info, 0 },
|
||||
{ "set", cmd_set, 1 },
|
||||
{ "info", cmd_info, 0 },
|
||||
{ "monitor", cmd_monitor, 0 },
|
||||
--- /dev/null
|
||||
+++ b/utils/powercap-info.c
|
||||
@@ -0,0 +1,113 @@
|
||||
+#include <unistd.h>
|
||||
+#include <stdio.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdint.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#include <getopt.h>
|
||||
+
|
||||
+#include "powercap.h"
|
||||
+#include "helpers/helpers.h"
|
||||
+
|
||||
+int powercap_show_all = 0;
|
||||
+
|
||||
+static struct option info_opts[] =
|
||||
+{
|
||||
+ { "all", no_argument, NULL, 'a'},
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
+static int powercap_print_one_zone(struct powercap_zone *zone)
|
||||
+{
|
||||
+ int mode, i, ret = 0;
|
||||
+ char pr_prefix[1024] = "";
|
||||
+
|
||||
+ for (i = 0; i < zone->tree_depth && i < POWERCAP_MAX_TREE_DEPTH; i++)
|
||||
+ strcat (pr_prefix, "\t");
|
||||
+
|
||||
+ printf("%sZone: %s", pr_prefix, zone->name);
|
||||
+ ret = powercap_zone_get_enabled(zone, &mode);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ printf(" (%s)\n", mode ? "enabled" : "disabled");
|
||||
+
|
||||
+ if (zone->has_power_uw)
|
||||
+printf(_("%sEnergy consumption can be monitored in micro Jules\n"),
|
||||
+ pr_prefix);
|
||||
+
|
||||
+ if (zone->has_energy_uj)
|
||||
+printf(_("%sPower consumption can be monitored in micro Watts\n"),
|
||||
+ pr_prefix);
|
||||
+
|
||||
+ printf("\n");
|
||||
+
|
||||
+ if (ret != 0)
|
||||
+ return ret;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int powercap_show()
|
||||
+{
|
||||
+ struct powercap_zone *root_zone;
|
||||
+ char line[MAX_LINE_LEN] = "";
|
||||
+ int ret, val;
|
||||
+
|
||||
+ ret = powercap_get_driver(line, MAX_LINE_LEN);
|
||||
+ if (ret < 0) {
|
||||
+ printf(_("No powercapping driver loaded\n"));
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ printf("Driver: %s\n", line);
|
||||
+ ret = powercap_get_enabled(&val);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ if (!val) {
|
||||
+ printf(_("Powercapping is disabled\n"));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ printf(_("Powercap domain hierarchy:\n\n"));
|
||||
+ root_zone = powercap_init_zones();
|
||||
+
|
||||
+ if (root_zone == NULL) {
|
||||
+ printf(_("No powercap info found\n"));
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ powercap_walk_zones(root_zone, powercap_print_one_zone);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int cmd_cap_set(int argc, char **argv)
|
||||
+{
|
||||
+ return 0;
|
||||
+};
|
||||
+int cmd_cap_info(int argc, char **argv)
|
||||
+{
|
||||
+ extern char *optarg;
|
||||
+ extern int optind, opterr, optopt;
|
||||
+ int ret = 0, cont = 1;
|
||||
+ do {
|
||||
+ ret = getopt_long(argc, argv, "a", info_opts, NULL);
|
||||
+ switch (ret) {
|
||||
+ case '?':
|
||||
+ cont = 0;
|
||||
+ break;
|
||||
+ case -1:
|
||||
+ cont = 0;
|
||||
+ break;
|
||||
+ case 'a':
|
||||
+ powercap_show_all = 1;
|
||||
+ break;
|
||||
+ default:
|
||||
+ fprintf(stderr, _("invalid or unknown argument\n"));
|
||||
+ return EXIT_FAILURE;
|
||||
+ }
|
||||
+ } while (cont);
|
||||
+
|
||||
+ powercap_show();
|
||||
+ return 0;
|
||||
+}
|
@ -1,191 +0,0 @@
|
||||
cpupower: rapl monitor - shows the used power consumption in uj for each rapl domain
|
||||
|
||||
|
||||
Signed-off-by: Thomas Renninger <trenn@suse.com>
|
||||
|
||||
---
|
||||
Makefile | 1
|
||||
utils/idle_monitor/cpupower-monitor.c | 7 -
|
||||
utils/idle_monitor/idle_monitors.def | 1
|
||||
utils/idle_monitor/rapl_monitor.c | 141 ++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 147 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -131,6 +131,7 @@
|
||||
utils/idle_monitor/hsw_ext_idle.o \
|
||||
utils/idle_monitor/amd_fam14h_idle.o utils/idle_monitor/cpuidle_sysfs.o \
|
||||
utils/idle_monitor/mperf_monitor.o utils/idle_monitor/cpupower-monitor.o \
|
||||
+ utils/idle_monitor/rapl_monitor.o \
|
||||
utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \
|
||||
utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o \
|
||||
utils/cpuidle-set.o utils/powercap-info.o
|
||||
--- a/utils/idle_monitor/cpupower-monitor.c
|
||||
+++ b/utils/idle_monitor/cpupower-monitor.c
|
||||
@@ -459,9 +459,10 @@
|
||||
print_results(1, cpu);
|
||||
}
|
||||
|
||||
- for (num = 0; num < avail_monitors; num++)
|
||||
- monitors[num]->unregister();
|
||||
-
|
||||
+ for (num = 0; num < avail_monitors; num++) {
|
||||
+ if (monitors[num]->unregister)
|
||||
+ monitors[num]->unregister();
|
||||
+ }
|
||||
cpu_topology_release(cpu_top);
|
||||
return 0;
|
||||
}
|
||||
--- a/utils/idle_monitor/idle_monitors.def
|
||||
+++ b/utils/idle_monitor/idle_monitors.def
|
||||
@@ -4,5 +4,6 @@
|
||||
DEF(intel_snb)
|
||||
DEF(intel_hsw_ext)
|
||||
DEF(mperf)
|
||||
+DEF(rapl)
|
||||
#endif
|
||||
DEF(cpuidle_sysfs)
|
||||
--- /dev/null
|
||||
+++ b/utils/idle_monitor/rapl_monitor.c
|
||||
@@ -0,0 +1,141 @@
|
||||
+/*
|
||||
+ * (C) 2016 Thomas Renninger <trenn@suse.com>
|
||||
+ *
|
||||
+ * Licensed under the terms of the GNU GPL License version 2.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#if defined(__i386__) || defined(__x86_64__)
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdint.h>
|
||||
+#include <time.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#include <pci/pci.h>
|
||||
+
|
||||
+#include "idle_monitor/cpupower-monitor.h"
|
||||
+#include "helpers/helpers.h"
|
||||
+#include "powercap.h"
|
||||
+
|
||||
+#define MAX_RAPL_ZONES 10
|
||||
+
|
||||
+int rapl_zone_count = 0;
|
||||
+cstate_t rapl_zones[MAX_RAPL_ZONES];
|
||||
+struct powercap_zone *rapl_zones_pt[MAX_RAPL_ZONES] = { 0 };
|
||||
+
|
||||
+unsigned long long rapl_zone_previous_count[MAX_RAPL_ZONES];
|
||||
+unsigned long long rapl_zone_current_count[MAX_RAPL_ZONES];
|
||||
+unsigned long long rapl_max_count;
|
||||
+
|
||||
+static int rapl_get_count_uj(unsigned int id, unsigned long long *count,
|
||||
+ unsigned int cpu)
|
||||
+{
|
||||
+ if (rapl_zones_pt[id] == NULL)
|
||||
+ /* error */
|
||||
+ return -1;
|
||||
+
|
||||
+ *count = rapl_zone_current_count[id] - rapl_zone_previous_count[id];
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int powercap_count_zones(struct powercap_zone *zone)
|
||||
+{
|
||||
+ if (rapl_zone_count >= MAX_RAPL_ZONES)
|
||||
+ return -1;
|
||||
+
|
||||
+ if (!zone->has_energy_uj)
|
||||
+ return 0;
|
||||
+
|
||||
+ strncpy(rapl_zones[rapl_zone_count].name, zone->name, CSTATE_NAME_LEN - 1);
|
||||
+ strcpy(rapl_zones[rapl_zone_count].desc, "");
|
||||
+ rapl_zones[rapl_zone_count].id = rapl_zone_count;
|
||||
+ rapl_zones[rapl_zone_count].range = RANGE_MACHINE;
|
||||
+ rapl_zones[rapl_zone_count].get_count = rapl_get_count_uj;
|
||||
+ rapl_zones_pt[rapl_zone_count] = zone;
|
||||
+ rapl_zone_count++;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int rapl_start(void)
|
||||
+{
|
||||
+ int i, ret;
|
||||
+ uint64_t uj_val;
|
||||
+
|
||||
+ for (i = 0; i < rapl_zone_count; i++) {
|
||||
+ ret = powercap_get_energy_uj(rapl_zones_pt[i], &uj_val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ rapl_zone_previous_count[i] = uj_val;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int rapl_stop(void)
|
||||
+{
|
||||
+ int i;
|
||||
+ uint64_t uj_val;
|
||||
+
|
||||
+ for (i = 0; i < rapl_zone_count; i++) {
|
||||
+ int ret;
|
||||
+ ret = powercap_get_energy_uj(rapl_zones_pt[i], &uj_val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ rapl_zone_current_count[i] = uj_val;
|
||||
+ if (rapl_max_count < uj_val)
|
||||
+ rapl_max_count = uj_val - rapl_zone_previous_count[i];
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+struct cpuidle_monitor *rapl_register(void)
|
||||
+{
|
||||
+ struct powercap_zone *root_zone;
|
||||
+ char line[MAX_LINE_LEN] = "";
|
||||
+ int ret, val;
|
||||
+
|
||||
+ ret = powercap_get_driver(line, MAX_LINE_LEN);
|
||||
+ if (ret < 0) {
|
||||
+ dprint("No powercapping driver loaded\n");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ dprint("Driver: %s\n", line);
|
||||
+ ret = powercap_get_enabled(&val);
|
||||
+ if (ret < 0)
|
||||
+ return NULL;
|
||||
+ if (!val) {
|
||||
+ dprint("Powercapping is disabled\n");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ dprint("Powercap domain hierarchy:\n\n");
|
||||
+ root_zone = powercap_init_zones();
|
||||
+
|
||||
+ if (root_zone == NULL) {
|
||||
+ dprint("No powercap info found\n");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ powercap_walk_zones(root_zone, powercap_count_zones);
|
||||
+ rapl_monitor.hw_states_num = rapl_zone_count;
|
||||
+
|
||||
+ return &rapl_monitor;
|
||||
+}
|
||||
+
|
||||
+struct cpuidle_monitor rapl_monitor = {
|
||||
+ .name = "RAPL",
|
||||
+ .hw_states = rapl_zones,
|
||||
+ .hw_states_num = 0,
|
||||
+ .start = rapl_start,
|
||||
+ .stop = rapl_stop,
|
||||
+ .do_register = rapl_register,
|
||||
+ .flags.needs_root = 0,
|
||||
+ .overflow_s = 60 * 60 * 24 * 100, /* To be implemented */
|
||||
+};
|
||||
+
|
||||
+#endif
|
Loading…
Reference in New Issue
Block a user