diff options
author | Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> | 2014-06-04 17:35:21 -0700 |
---|---|---|
committer | Alexandra Yates <alexandra.yates@linux.intel.com> | 2014-06-10 10:40:47 -0700 |
commit | 2d6fe0fba6b853030a17bd1bcc2659137e392f8c (patch) | |
tree | a82ef1ad644813935c0c8f3ee943b27e4a3f5354 | |
parent | 25c85ab72174eee685ca9aa2c5d349522779b8b3 (diff) | |
download | powertop-2.0-2d6fe0fba6b853030a17bd1bcc2659137e392f8c.tar.gz |
RAPL: Use Powercap sysfs
Linux Powercap sysfs with Intel RAPL driver exists from 3.13.rc1.
Use this to estimate RAPL domain power instead of MSRs. Since
these MSRs are non-architectural, they can be changed from
processor model to model. But by using powercap sysfs, kernel
driver will take care about processor specific variations.
-rw-r--r-- | src/cpu/rapl/rapl_interface.cpp | 91 | ||||
-rw-r--r-- | src/cpu/rapl/rapl_interface.h | 7 |
2 files changed, 96 insertions, 2 deletions
diff --git a/src/cpu/rapl/rapl_interface.cpp b/src/cpu/rapl/rapl_interface.cpp index 6dd7b26..a19e0a9 100644 --- a/src/cpu/rapl/rapl_interface.cpp +++ b/src/cpu/rapl/rapl_interface.cpp @@ -27,6 +27,8 @@ #include <unistd.h> #include <errno.h> #include <math.h> +#include <stdlib.h> +#include <dirent.h> #include "lib.h" #include "rapl_interface.h" @@ -68,7 +70,11 @@ #define PP0_DOMAIN_PRESENT 0x04 #define PP1_DOMAIN_PRESENT 0x08 -c_rapl_interface::c_rapl_interface(int cpu) : +c_rapl_interface::c_rapl_interface(const char *dev_name, int cpu) : + powercap_sysfs_present(false), + powercap_core_path(), + powercap_uncore_path(), + powercap_dram_path(), measurment_interval(def_sampling_interval), first_cpu(cpu), last_pkg_energy_status(0.0), @@ -78,10 +84,63 @@ c_rapl_interface::c_rapl_interface(int cpu) : { uint64_t value; int ret; + string package_path; + DIR *dir; + struct dirent *entry; RAPL_INFO_PRINT("RAPL device for cpu %d\n", cpu); rapl_domains = 0; + + if (dev_name) { + string base_path = "/sys/class/powercap/intel-rapl/"; + if ((dir = opendir(base_path.c_str())) != NULL) { + while ((entry = readdir(dir)) != NULL) { + string path = base_path + entry->d_name + "/name"; + string str = read_sysfs_string(path); + if (str.length() > 0) { + if (str == dev_name) { + package_path = base_path + entry->d_name + "/"; + powercap_sysfs_present = true; + rapl_domains |= PKG_DOMAIN_PRESENT; + break; + } + } + } + closedir(dir); + } + } + + if (powercap_sysfs_present) { + if ((dir = opendir(package_path.c_str())) != NULL) { + while ((entry = readdir(dir)) != NULL) { + string path = package_path + entry->d_name; + string str = read_sysfs_string(path + "/name"); + if (str.length() > 0) { + if (str == "core") { + rapl_domains |= PP0_DOMAIN_PRESENT; + powercap_core_path = path + "/"; + } + else if (str == "dram") { + rapl_domains |= DRAM_DOMAIN_PRESENT; + powercap_dram_path = path + "/"; + } + else if (str == "uncore") { + rapl_domains |= PP1_DOMAIN_PRESENT; + powercap_uncore_path = path + "/"; + } + } + } + closedir(dir); + } + + RAPL_INFO_PRINT("RAPL Using PowerCap Sysfs : Domain Mask %x\n", + rapl_domains); + return; + } + + // Fallback to using MSRs + // presence of each domain // Check presence of PKG domain ret = read_msr(first_cpu, MSR_PKG_ENERY_STATUS, &value); @@ -312,6 +371,16 @@ int c_rapl_interface::get_dram_energy_status(double *status) return -1; } + if (powercap_sysfs_present) { + string str = read_sysfs_string(powercap_dram_path + "energy_uj"); + if (str.length() > 0) { + *status = atof(str.c_str()) / 1000000; // uj to Js + return 0; + } + + return -EINVAL; + } + ret = read_msr(first_cpu, MSR_DRAM_ENERY_STATUS, &value); if(ret < 0) { @@ -393,6 +462,16 @@ int c_rapl_interface::get_pp0_energy_status(double *status) return -1; } + if (powercap_sysfs_present) { + string str = read_sysfs_string(powercap_core_path + "energy_uj"); + if (str.length() > 0) { + *status = atof(str.c_str()) / 1000000; // uj to Js + return 0; + } + + return -EINVAL; + } + ret = read_msr(first_cpu, MSR_PP0_ENERY_STATUS, &value); if(ret < 0) { @@ -471,6 +550,16 @@ int c_rapl_interface::get_pp1_energy_status(double *status) return -1; } + if (powercap_sysfs_present) { + string str = read_sysfs_string(powercap_uncore_path + "energy_uj"); + if (str.length() > 0) { + *status = atof(str.c_str()) / 1000000; // uj to Js + return 0; + } + + return -EINVAL; + } + ret = read_msr(first_cpu, MSR_PP1_ENERY_STATUS, &value); if(ret < 0) { diff --git a/src/cpu/rapl/rapl_interface.h b/src/cpu/rapl/rapl_interface.h index be863e2..744f595 100644 --- a/src/cpu/rapl/rapl_interface.h +++ b/src/cpu/rapl/rapl_interface.h @@ -28,6 +28,11 @@ class c_rapl_interface { private: static const int def_sampling_interval = 1; //In seconds + bool powercap_sysfs_present; + string powercap_core_path; + string powercap_uncore_path; + string powercap_dram_path; + unsigned char rapl_domains; int measurment_interval; int first_cpu; @@ -45,7 +50,7 @@ private: int write_msr(int cpu, unsigned int idx, uint64_t val); public: - c_rapl_interface(int cpu = 0); + c_rapl_interface(const char *dev_name = "package-0", int cpu = 0); int get_rapl_power_unit(uint64_t *value); double get_power_unit(); |