1 /* rapl_interface.cpp: rapl interface for power top implementation
3 * Copyright (C) 2012 Intel Corporation. All rights reserved.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License version
7 * 2 as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * Author Name <Srinivas.Pandruvada@linux.intel.com>
24 #include <sys/types.h>
31 #include "rapl_interface.h"
34 #define RAPL_DBG_PRINT printf
35 #define RAPL_ERROR_PRINT printf
37 #define RAPL_DBG_PRINT(...) ((void) 0)
38 #define RAPL_ERROR_PRINT(...) ((void) 0)
40 #define RAPL_INFO_PRINT printf
42 #define MAX_TEMP_STR_SIZE 20
45 #define MSR_RAPL_POWER_UNIT 0x606
46 #define MSR_PKG_POWER_LIMIT 0x610
48 #define MSR_PKG_ENERY_STATUS 0x611
49 #define MSR_PKG_POWER_INFO 0x614
50 #define MSR_PKG_PERF_STATUS 0x613
52 #define MSR_DRAM_POWER_LIMIT 0x618
53 #define MSR_DRAM_ENERY_STATUS 0x619
54 #define MSR_DRAM_PERF_STATUS 0x61B
55 #define MSR_DRAM_POWER_INFO 0x61c
57 #define MSR_PP0_POWER_LIMIT 0x638
58 #define MSR_PP0_ENERY_STATUS 0x639
59 #define MSR_PP0_POLICY 0x63A
60 #define MSR_PP0_PERF_STATUS 0x63B
62 #define MSR_PP1_POWER_LIMIT 0x640
63 #define MSR_PP1_ENERY_STATUS 0x641
64 #define MSR_PP1_POLICY 0x642
66 #define PKG_DOMAIN_PRESENT 0x01
67 #define DRAM_DOMAIN_PRESENT 0x02
68 #define PP0_DOMAIN_PRESENT 0x04
69 #define PP1_DOMAIN_PRESENT 0x08
71 c_rapl_interface::c_rapl_interface(int cpu) :
72 measurment_interval(def_sampling_interval),
74 last_pkg_energy_status(0.0),
75 last_dram_energy_status(0.0),
76 last_pp0_energy_status(0.0),
77 last_pp1_energy_status(0.0)
82 RAPL_INFO_PRINT("RAPL device for cpu %d\n", cpu);
85 // presence of each domain
86 // Check presence of PKG domain
87 ret = read_msr(first_cpu, MSR_PKG_ENERY_STATUS, &value);
89 rapl_domains |= PKG_DOMAIN_PRESENT;
90 RAPL_DBG_PRINT("Domain : PKG present\n");
92 RAPL_DBG_PRINT("Domain : PKG Not present\n");
95 // Check presence of DRAM domain
96 ret = read_msr(first_cpu, MSR_DRAM_ENERY_STATUS, &value);
98 rapl_domains |= DRAM_DOMAIN_PRESENT;
99 RAPL_DBG_PRINT("Domain : DRAM present\n");
101 RAPL_DBG_PRINT("Domain : DRAM Not present\n");
104 // Check presence of PP0 domain
105 ret = read_msr(first_cpu, MSR_PP0_ENERY_STATUS, &value);
107 rapl_domains |= PP0_DOMAIN_PRESENT;
108 RAPL_DBG_PRINT("Domain : PP0 present\n");
110 RAPL_DBG_PRINT("Domain : PP0 Not present\n");
113 // Check presence of PP1 domain
114 ret = read_msr(first_cpu, MSR_PP1_ENERY_STATUS, &value);
116 rapl_domains |= PP1_DOMAIN_PRESENT;
117 RAPL_DBG_PRINT("Domain : PP1 present\n");
119 RAPL_DBG_PRINT("Domain : PP1 Not present\n");
122 power_units = get_power_unit();
123 energy_status_units = get_energy_status_unit();
124 time_units = get_time_unit();
126 RAPL_DBG_PRINT("RAPL Domain mask: %x\n", rapl_domains);
129 bool c_rapl_interface::pkg_domain_present()
131 if ((rapl_domains & PKG_DOMAIN_PRESENT)) {
138 bool c_rapl_interface::dram_domain_present()
140 if ((rapl_domains & DRAM_DOMAIN_PRESENT)) {
147 bool c_rapl_interface::pp0_domain_present()
149 if ((rapl_domains & PP0_DOMAIN_PRESENT)) {
156 bool c_rapl_interface::pp1_domain_present()
158 if ((rapl_domains & PP1_DOMAIN_PRESENT)) {
165 int c_rapl_interface::read_msr(int cpu, unsigned int idx, uint64_t *val)
167 return ::read_msr(cpu, idx, val);
170 int c_rapl_interface::write_msr(int cpu, unsigned int idx, uint64_t val)
172 return ::write_msr(cpu, idx, val);
175 int c_rapl_interface::get_rapl_power_unit(uint64_t *value)
179 ret = read_msr(first_cpu, MSR_RAPL_POWER_UNIT, value);
184 double c_rapl_interface::get_power_unit()
189 ret = get_rapl_power_unit(&value);
195 return (double) 1/pow((double)2, (double)(value & 0xf));
198 double c_rapl_interface::get_energy_status_unit()
203 ret = get_rapl_power_unit(&value);
209 return (double)1/ pow((double)2, (double)((value & 0x1f00) >> 8));
212 double c_rapl_interface::get_time_unit()
217 ret = get_rapl_power_unit(&value);
223 return (double)1 / pow((double)2, (double)((value & 0xf0000) >> 16));
226 int c_rapl_interface::get_pkg_energy_status(double *status)
231 if (!pkg_domain_present()) {
235 ret = read_msr(first_cpu, MSR_PKG_ENERY_STATUS, &value);
238 RAPL_ERROR_PRINT("get_pkg_energy_status failed\n");
242 *status = (double) (value & 0xffffffff) * get_energy_status_unit();
247 int c_rapl_interface::get_pkg_power_info(double *thermal_spec_power,
248 double *max_power, double *min_power, double *max_time_window)
253 if (!pkg_domain_present()) {
256 ret = read_msr(first_cpu, MSR_PKG_POWER_INFO, &value);
259 RAPL_ERROR_PRINT("get_pkg_power_info failed\n");
262 *thermal_spec_power = (value & 0x7FFF) * power_units;
263 *min_power = ((value & 0x7FFF0000) >> 16) * power_units;
264 *max_power = ((value & 0x7FFF00000000) >> 32) * power_units;
265 *max_time_window = ((value & 0x3f000000000000)>>48) * time_units;
270 int c_rapl_interface::get_pkg_power_limit(uint64_t *value)
274 if (!pkg_domain_present()) {
278 ret = read_msr(first_cpu, MSR_PKG_POWER_LIMIT, value);
281 RAPL_ERROR_PRINT("get_pkg_power_limit failed\n");
288 int c_rapl_interface::set_pkg_power_limit(uint64_t value)
292 if (!pkg_domain_present()) {
296 ret = write_msr(first_cpu, MSR_PKG_POWER_LIMIT, value);
299 RAPL_ERROR_PRINT("set_pkg_power_limit failed\n");
306 int c_rapl_interface::get_dram_energy_status(double *status)
311 if (!dram_domain_present()) {
315 ret = read_msr(first_cpu, MSR_DRAM_ENERY_STATUS, &value);
318 RAPL_ERROR_PRINT("get_dram_energy_status failed\n");
322 *status = (double) (value & 0xffffffff) * get_energy_status_unit();
327 int c_rapl_interface::get_dram_power_info(double *thermal_spec_power,
328 double *max_power, double *min_power, double *max_time_window)
333 if (!dram_domain_present()) {
336 ret = read_msr(first_cpu, MSR_DRAM_POWER_INFO, &value);
339 RAPL_ERROR_PRINT("get_dram_power_info failed\n");
343 *thermal_spec_power = (value & 0x7FFF) * power_units;
344 *min_power = ((value & 0x7FFF0000) >> 16) * power_units;
345 *max_power = ((value & 0x7FFF00000000) >> 32) * power_units;
346 *max_time_window = ((value & 0x3f000000000000)>>48) * time_units;
351 int c_rapl_interface::get_dram_power_limit(uint64_t *value)
355 if (!dram_domain_present()) {
359 ret = read_msr(first_cpu, MSR_DRAM_POWER_LIMIT, value);
362 RAPL_ERROR_PRINT("get_dram_power_limit failed\n");
369 int c_rapl_interface::set_dram_power_limit(uint64_t value)
373 if (!dram_domain_present()) {
377 ret = write_msr(first_cpu, MSR_DRAM_POWER_LIMIT, value);
380 RAPL_ERROR_PRINT("set_dram_power_limit failed\n");
387 int c_rapl_interface::get_pp0_energy_status(double *status)
392 if (!pp0_domain_present()) {
396 ret = read_msr(first_cpu, MSR_PP0_ENERY_STATUS, &value);
399 RAPL_ERROR_PRINT("get_pp0_energy_status failed\n");
403 *status = (double) (value & 0xffffffff) * get_energy_status_unit();
408 int c_rapl_interface::get_pp0_power_limit(uint64_t *value)
412 if (!pp0_domain_present()) {
416 ret = read_msr(first_cpu, MSR_PP0_POWER_LIMIT, value);
419 RAPL_ERROR_PRINT("get_pp0_power_limit failed\n");
426 int c_rapl_interface::set_pp0_power_limit(uint64_t value)
430 if (!pp0_domain_present()) {
434 ret = write_msr(first_cpu, MSR_PP0_POWER_LIMIT, value);
437 RAPL_ERROR_PRINT("set_pp0_power_limit failed\n");
444 int c_rapl_interface::get_pp0_power_policy(unsigned int *pp0_power_policy)
449 if (!pp0_domain_present()) {
453 ret = read_msr(first_cpu, MSR_PP0_POLICY, &value);
456 RAPL_ERROR_PRINT("get_pp0_power_policy failed\n");
460 *pp0_power_policy = value & 0x0f;
465 int c_rapl_interface::get_pp1_energy_status(double *status)
470 if (!pp1_domain_present()) {
474 ret = read_msr(first_cpu, MSR_PP1_ENERY_STATUS, &value);
477 RAPL_ERROR_PRINT("get_pp1_energy_status failed\n");
481 *status = (double) (value & 0xffffffff) * get_energy_status_unit();
486 int c_rapl_interface::get_pp1_power_limit(uint64_t *value)
490 if (!pp1_domain_present()) {
494 ret = read_msr(first_cpu, MSR_PP1_POWER_LIMIT, value);
497 RAPL_ERROR_PRINT("get_pp1_power_info failed\n");
504 int c_rapl_interface::set_pp1_power_limit(uint64_t value)
508 if (!pp1_domain_present()) {
512 ret = write_msr(first_cpu, MSR_PP1_POWER_LIMIT, value);
515 RAPL_ERROR_PRINT("set_pp1_power_limit failed\n");
522 int c_rapl_interface::get_pp1_power_policy(unsigned int *pp1_power_policy)
527 if (!pp1_domain_present()) {
531 ret = read_msr(first_cpu, MSR_PP1_POLICY, &value);
534 RAPL_ERROR_PRINT("get_pp1_power_policy failed\n");
538 *pp1_power_policy = value & 0x0f;
543 void c_rapl_interface::rapl_measure_energy()
545 #ifdef RAPL_TEST_MODE
547 double energy_status;
548 double thermal_spec_power;
551 double max_time_window;
552 double pkg_watts = 0;
553 double dram_watts = 0;
554 double pp0_watts = 0;
555 double pp1_watts = 0;
556 double pkg_joules = 0;
557 double dram_joules = 0;
558 double pp0_joules = 0;
559 double pp1_joules = 0;
561 ret = get_pkg_power_info(&thermal_spec_power, &max_power, &min_power, &max_time_window);
562 RAPL_DBG_PRINT("Pkg Power Info: Thermal spec %f watts, max %f watts, min %f watts, max time window %f seconds\n", thermal_spec_power, max_power, min_power, max_time_window);
563 ret = get_dram_power_info(&thermal_spec_power, &max_power, &min_power, &max_time_window);
564 RAPL_DBG_PRINT("DRAM Power Info: Thermal spec %f watts, max %f watts, min %f watts, max time window %f seconds\n", thermal_spec_power, max_power, min_power, max_time_window);
567 if (pkg_domain_present()) {
568 ret = get_pkg_energy_status(&energy_status);
569 if (last_pkg_energy_status == 0)
570 last_pkg_energy_status = energy_status;
572 pkg_joules = energy_status;
573 pkg_watts = (energy_status-last_pkg_energy_status)/measurment_interval;
575 last_pkg_energy_status = energy_status;
577 if (dram_domain_present()) {
578 ret = get_dram_energy_status(&energy_status);
579 if (last_dram_energy_status == 0)
580 last_dram_energy_status = energy_status;
582 dram_joules = energy_status;
583 dram_watts = (energy_status-last_dram_energy_status)/measurment_interval;
585 last_dram_energy_status = energy_status;
587 if (pp0_domain_present()) {
588 ret = get_pp0_energy_status(&energy_status);
589 if (last_pp0_energy_status == 0)
590 last_pp0_energy_status = energy_status;
592 pp0_joules = energy_status;
593 pp0_watts = (energy_status-last_pp0_energy_status)/measurment_interval;
595 last_pp0_energy_status = energy_status;
597 if (pp1_domain_present()) {
598 ret = get_pp1_energy_status(&energy_status);
599 if (last_pp1_energy_status == 0)
600 last_pp1_energy_status = energy_status;
602 pp1_joules = energy_status;
603 pp1_watts = (energy_status-last_pp1_energy_status)/measurment_interval;
605 last_pp1_energy_status = energy_status;
607 RAPL_DBG_PRINT("%f, %f, %f, %f\n", pkg_watts, dram_watts, pp0_watts, pp1_watts);
608 sleep(measurment_interval);