aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>2014-06-04 17:35:21 -0700
committerAlexandra Yates <alexandra.yates@linux.intel.com>2014-06-10 10:40:47 -0700
commit2d6fe0fba6b853030a17bd1bcc2659137e392f8c (patch)
treea82ef1ad644813935c0c8f3ee943b27e4a3f5354
parent25c85ab72174eee685ca9aa2c5d349522779b8b3 (diff)
downloadpowertop-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.cpp91
-rw-r--r--src/cpu/rapl/rapl_interface.h7
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();