summaryrefslogtreecommitdiffstats
path: root/tools/power/cpupower/utils
diff options
context:
space:
mode:
Diffstat (limited to 'tools/power/cpupower/utils')
-rw-r--r--tools/power/cpupower/utils/builtin.h2
-rw-r--r--tools/power/cpupower/utils/cpufreq-info.c4
-rw-r--r--tools/power/cpupower/utils/cpuidle-info.c4
-rw-r--r--tools/power/cpupower/utils/cpupower-info.c4
-rw-r--r--tools/power/cpupower/utils/cpupower.c1
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c7
-rw-r--r--tools/power/cpupower/utils/idle_monitor/idle_monitors.def1
-rw-r--r--tools/power/cpupower/utils/idle_monitor/rapl_monitor.c148
-rw-r--r--tools/power/cpupower/utils/powercap-info.c117
9 files changed, 279 insertions, 9 deletions
diff --git a/tools/power/cpupower/utils/builtin.h b/tools/power/cpupower/utils/builtin.h
index f7065ae60a14..e1caefd467cd 100644
--- a/tools/power/cpupower/utils/builtin.h
+++ b/tools/power/cpupower/utils/builtin.h
@@ -8,6 +8,8 @@ extern int cmd_freq_set(int argc, const char **argv);
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
diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
index 0646f615fe2d..c96b77365c63 100644
--- a/tools/power/cpupower/utils/cpufreq-info.c
+++ b/tools/power/cpupower/utils/cpufreq-info.c
@@ -572,9 +572,9 @@ int cmd_freq_info(int argc, char **argv)
ret = 0;
- /* Default is: show output of CPU 0 only */
+ /* Default is: show output of base_cpu only */
if (bitmask_isallclear(cpus_chosen))
- bitmask_setbit(cpus_chosen, 0);
+ bitmask_setbit(cpus_chosen, base_cpu);
switch (output_param) {
case -1:
diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c
index f2b202c5552a..44126a87fa7a 100644
--- a/tools/power/cpupower/utils/cpuidle-info.c
+++ b/tools/power/cpupower/utils/cpuidle-info.c
@@ -176,9 +176,9 @@ int cmd_idle_info(int argc, char **argv)
cpuidle_exit(EXIT_FAILURE);
}
- /* Default is: show output of CPU 0 only */
+ /* Default is: show output of base_cpu only */
if (bitmask_isallclear(cpus_chosen))
- bitmask_setbit(cpus_chosen, 0);
+ bitmask_setbit(cpus_chosen, base_cpu);
if (output_param == 0)
cpuidle_general_output();
diff --git a/tools/power/cpupower/utils/cpupower-info.c b/tools/power/cpupower/utils/cpupower-info.c
index 06345b543786..18fd7751f509 100644
--- a/tools/power/cpupower/utils/cpupower-info.c
+++ b/tools/power/cpupower/utils/cpupower-info.c
@@ -67,9 +67,9 @@ int cmd_info(int argc, char **argv)
if (!params.params)
params.params = 0x7;
- /* Default is: show output of CPU 0 only */
+ /* Default is: show output of base_cpu only */
if (bitmask_isallclear(cpus_chosen))
- bitmask_setbit(cpus_chosen, 0);
+ bitmask_setbit(cpus_chosen, base_cpu);
/* Add more per cpu options here */
if (!params.perf_bias)
diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c
index 8ac3304a9957..9ec973165af1 100644
--- a/tools/power/cpupower/utils/cpupower.c
+++ b/tools/power/cpupower/utils/cpupower.c
@@ -54,6 +54,7 @@ static struct cmd_struct commands[] = {
{ "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 },
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
index 7c77045fef52..075e766ff1f3 100644
--- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
+++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
@@ -459,9 +459,10 @@ int cmd_monitor(int argc, char **argv)
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;
}
diff --git a/tools/power/cpupower/utils/idle_monitor/idle_monitors.def b/tools/power/cpupower/utils/idle_monitor/idle_monitors.def
index 0d6ba4dbb9c7..7c926e90c87e 100644
--- a/tools/power/cpupower/utils/idle_monitor/idle_monitors.def
+++ b/tools/power/cpupower/utils/idle_monitor/idle_monitors.def
@@ -4,5 +4,6 @@ DEF(intel_nhm)
DEF(intel_snb)
DEF(intel_hsw_ext)
DEF(mperf)
+DEF(rapl)
#endif
DEF(cpuidle_sysfs)
diff --git a/tools/power/cpupower/utils/idle_monitor/rapl_monitor.c b/tools/power/cpupower/utils/idle_monitor/rapl_monitor.c
new file mode 100644
index 000000000000..46153f1291c3
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/rapl_monitor.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * (C) 2016 SUSE Software Solutions GmbH
+ * Thomas Renninger <trenn@suse.de>
+ */
+
+#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;
+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)
+{
+ uint64_t val;
+ int uj;
+
+ if (rapl_zone_count >= MAX_RAPL_ZONES)
+ return -1;
+
+ if (!zone->has_energy_uj)
+ return 0;
+
+ printf("%s\n", zone->sys_name);
+ uj = powercap_get_energy_uj(zone, &val);
+ printf("%d\n", uj);
+
+ 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
diff --git a/tools/power/cpupower/utils/powercap-info.c b/tools/power/cpupower/utils/powercap-info.c
new file mode 100644
index 000000000000..3ea4486f1a0e
--- /dev/null
+++ b/tools/power/cpupower/utils/powercap-info.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * (C) 2016 SUSE Software Solutions GmbH
+ * Thomas Renninger <trenn@suse.de>
+ */
+
+#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;
+
+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(_("%sPower can be monitored in micro Jules\n"),
+ pr_prefix);
+
+ if (zone->has_energy_uj)
+ printf(_("%sPower can be monitored in micro Watts\n"),
+ pr_prefix);
+
+ printf("\n");
+
+ if (ret != 0)
+ return ret;
+ return ret;
+}
+
+static int powercap_show(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) {
+ 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)
+{
+ 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;
+}