PAPI 7.1.0.0
Loading...
Searching...
No Matches
linux-rapl.c
Go to the documentation of this file.
1
18#include <stdio.h>
19#include <unistd.h>
20#include <dirent.h>
21#include <fcntl.h>
22#include <string.h>
23#include <stdint.h>
24#include <errno.h>
25
26/* Headers required by PAPI */
27#include "papi.h"
28#include "papi_internal.h"
29#include "papi_vector.h"
30#include "papi_memory.h"
31
32// The following macro follows if a string function has an error. It should
33// never happen; but it is necessary to prevent compiler warnings. We print
34// something just in case there is programmer error in invoking the function.
35#define HANDLE_STRING_ERROR {fprintf(stderr,"%s:%i unexpected string function error.\n",__FILE__,__LINE__); exit(-1);}
36
37
38/***************/
39/* AMD Support */
40/***************/
41#define MSR_AMD_RAPL_POWER_UNIT 0xc0010299
42
43#define MSR_AMD_PKG_ENERGY_STATUS 0xc001029B
44#define MSR_AMD_PP0_ENERGY_STATUS 0xc001029A
45
46
47/*****************/
48/* Intel support */
49/*****************/
50
51/*
52 * Platform specific RAPL Domains.
53 * Note that PP1 RAPL Domain is supported on 062A only
54 * And DRAM RAPL Domain is supported on 062D only
55 */
56
57/* RAPL defines */
58#define MSR_INTEL_RAPL_POWER_UNIT 0x606
59
60/* Package */
61#define MSR_PKG_RAPL_POWER_LIMIT 0x610
62#define MSR_INTEL_PKG_ENERGY_STATUS 0x611
63#define MSR_PKG_PERF_STATUS 0x613
64#define MSR_PKG_POWER_INFO 0x614
65
66/* PP0 */
67#define MSR_PP0_POWER_LIMIT 0x638
68#define MSR_INTEL_PP0_ENERGY_STATUS 0x639
69#define MSR_PP0_POLICY 0x63A
70#define MSR_PP0_PERF_STATUS 0x63B
71
72/* PP1 */
73#define MSR_PP1_POWER_LIMIT 0x640
74#define MSR_PP1_ENERGY_STATUS 0x641
75#define MSR_PP1_POLICY 0x642
76
77/* DRAM */
78#define MSR_DRAM_POWER_LIMIT 0x618
79#define MSR_DRAM_ENERGY_STATUS 0x619
80#define MSR_DRAM_PERF_STATUS 0x61B
81#define MSR_DRAM_POWER_INFO 0x61C
82
83/* PSYS RAPL Domain */
84#define MSR_PLATFORM_ENERGY_STATUS 0x64d
85
86/* RAPL bitsmasks */
87#define POWER_UNIT_OFFSET 0
88#define POWER_UNIT_MASK 0x0f
89
90#define ENERGY_UNIT_OFFSET 0x08
91#define ENERGY_UNIT_MASK 0x1f
92
93#define TIME_UNIT_OFFSET 0x10
94#define TIME_UNIT_MASK 0x0f
95
96/* RAPL POWER UNIT MASKS */
97#define POWER_INFO_UNIT_MASK 0x7fff
98#define THERMAL_SHIFT 0
99#define MINIMUM_POWER_SHIFT 16
100#define MAXIMUM_POWER_SHIFT 32
101#define MAXIMUM_TIME_WINDOW_SHIFT 48
102
103
104typedef struct _rapl_register
105{
106 unsigned int selector;
108
109typedef struct _rapl_native_event_entry
110{
113 char description[PAPI_MAX_STR_LEN];
115 int msr;
116 int type;
120
121typedef struct _rapl_reg_alloc
122{
125
126/* actually 32? But setting this to be safe? */
127#define RAPL_MAX_COUNTERS 64
128
129typedef struct _rapl_control_state
130{
131 int being_measured[RAPL_MAX_COUNTERS];
133 int need_difference[RAPL_MAX_COUNTERS];
134 long long lastupdate;
136
137// The _ENERGY_ counters should return a monotonically increasing
138// value from the _start point, but the hardware only returns a
139// uint32_t that may wrap. We keep a start_value which is reset at
140// _start and every read, handle overflows of the uint32_t, and
141// accumulate a uint64_t which we return.
142
143typedef struct _rapl_context
144{
145 long long start_value[RAPL_MAX_COUNTERS];
146 long long accumulated_value[RAPL_MAX_COUNTERS];
149
150
152
154 int fd;
155 int open;
156};
157
159static int num_events = 0;
160struct fd_array_t *fd_array=NULL;
161static int num_packages=0,num_cpus=0;
162
166
167#define PACKAGE_ENERGY 0
168#define PACKAGE_THERMAL 1
169#define PACKAGE_MINIMUM 2
170#define PACKAGE_MAXIMUM 3
171#define PACKAGE_TIME_WINDOW 4
172#define PACKAGE_ENERGY_CNT 5
173#define PACKAGE_THERMAL_CNT 6
174#define PACKAGE_MINIMUM_CNT 7
175#define PACKAGE_MAXIMUM_CNT 8
176#define PACKAGE_TIME_WINDOW_CNT 9
177#define DRAM_ENERGY 10
178#define PLATFORM_ENERGY 11
179
180/***************************************************************************/
181/****** BEGIN FUNCTIONS USED INTERNALLY SPECIFIC TO THIS COMPONENT *******/
182/***************************************************************************/
183
184
185static long long read_msr(int fd, unsigned int which) {
186
187 uint64_t data;
188
189 if ( fd<0 || pread(fd, &data, sizeof data, which) != sizeof data ) {
190 perror("rdmsr:pread");
191 fprintf(stderr,"rdmsr error, msr %x\n",which);
192 exit(127);
193 }
194
195 return (long long)data;
196}
197
198static int open_fd(int offset) {
199
200 int fd=-1;
201 char filename[BUFSIZ];
202
203 if (fd_array[offset].open==0) {
204 sprintf(filename,"/dev/cpu/%d/msr_safe",offset);
205 fd = open(filename, O_RDONLY);
206 if (fd<0) {
207 sprintf(filename,"/dev/cpu/%d/msr",offset);
208 fd = open(filename, O_RDONLY);
209 }
210 if (fd>=0) {
211 fd_array[offset].fd=fd;
212 fd_array[offset].open=1;
213 }
214 }
215 else {
216 fd=fd_array[offset].fd;
217 }
218
219 return fd;
220}
221
222static long long read_rapl_value(int index) {
223
224 int fd;
225
226 fd=open_fd(rapl_native_events[index].fd_offset);
227 return read_msr(fd,rapl_native_events[index].msr);
228
229}
230
231static long long convert_rapl_energy(int index, long long value) {
232
233 union {
234 long long ll;
235 double fp;
236 } return_val;
237
238 return_val.ll = value; /* default case: return raw input value */
239
241 return_val.ll = (long long)(((double)value/cpu_energy_divisor)*1e9);
242 }
243
244 if (rapl_native_events[index].type==DRAM_ENERGY) {
245 return_val.ll = (long long)(((double)value/dram_energy_divisor)*1e9);
246 }
247
249 return_val.ll = (long long)(((double)value/cpu_energy_divisor)*1e9);
250 }
251
253 return_val.fp = (double)
255 (double)power_divisor;
256 }
257
259 return_val.fp = (double)
261 (double)power_divisor;
262 }
263
265 return_val.fp = (double)
267 (double)power_divisor;
268 }
269
271 return_val.fp = (double)
273 (double)time_divisor;
274 }
275
277 return_val.ll = ((value>>THERMAL_SHIFT)&POWER_INFO_UNIT_MASK);
278 }
279
281 return_val.ll = ((value>>MINIMUM_POWER_SHIFT)&POWER_INFO_UNIT_MASK);
282 }
283
285 return_val.ll = ((value>>MAXIMUM_POWER_SHIFT)&POWER_INFO_UNIT_MASK);
286 }
287
289 return_val.ll = ((value>>MAXIMUM_TIME_WINDOW_SHIFT)&POWER_INFO_UNIT_MASK);
290 }
291
292 return return_val.ll;
293}
294
295static int
297{
298 FILE *fff;
299 int num_read, nr_cpus = 1;
300 fff=fopen("/sys/devices/system/cpu/kernel_max","r");
301 if (fff==NULL) return nr_cpus;
302 num_read=fscanf(fff,"%d",&nr_cpus);
303 fclose(fff);
304 if (num_read==1) {
305 nr_cpus++;
306 } else {
307 nr_cpus = 1;
308 }
309 return nr_cpus;
310}
311
312/************************* PAPI Functions **********************************/
313
314
315/*
316 * This is called whenever a thread is initialized
317 */
318static int
320{
321 ( void ) ctx;
322
323 return PAPI_OK;
324}
325
326
327
328/*
329 * Called when PAPI process is initialized (i.e. PAPI_library_init)
330 */
331static int
333{
334 int retval = PAPI_OK;
335 int i,j,k,fd;
336 FILE *fff;
337 char filename[BUFSIZ];
338 long unsigned int strErr;
339 char *strCpy;
340
341 int package_avail, dram_avail, pp0_avail, pp1_avail, psys_avail;
342 int different_units;
343
344 long long result;
345 int package;
346
347 const PAPI_hw_info_t *hw_info;
348
349 int nr_cpus = get_kernel_nr_cpus();
350 int packages[nr_cpus];
351 int cpu_to_use[nr_cpus];
352
353 unsigned int msr_pkg_energy_status,msr_pp0_energy_status;
354
355
356 /* Fill with sentinel values */
357 for (i=0; i<nr_cpus; ++i) {
358 packages[i] = -1;
359 cpu_to_use[i] = -1;
360 }
361
362
363 /* check if supported processor */
365
366 /* Ugh can't use PAPI_get_hardware_info() if
367 PAPI library not done initializing yet */
368
369 switch(hw_info->vendor) {
371 case PAPI_VENDOR_AMD:
372 break;
373 default:
375 "Not a supported processor",PAPI_MAX_STR_LEN);
377 if (strCpy == NULL) HANDLE_STRING_ERROR;
379 goto fn_fail;
380 }
381
382
383 /* Make sure it is a family 6 Intel Chip */
384
386
388 msr_pkg_energy_status=MSR_INTEL_PKG_ENERGY_STATUS;
389 msr_pp0_energy_status=MSR_INTEL_PP0_ENERGY_STATUS;
390
391 if (hw_info->cpuid_family!=6) {
392 /* Not a family 6 machine */
394 "CPU family not supported",PAPI_MAX_STR_LEN);
396 if (strCpy == NULL) HANDLE_STRING_ERROR;
398 goto fn_fail;
399 }
400
401 /* Detect RAPL support */
402 switch(hw_info->cpuid_model) {
403
404 /* Desktop / Laptops */
405
406 case 42: /* SandyBridge */
407 case 58: /* IvyBridge */
408 package_avail=1;
409 pp0_avail=1;
410 pp1_avail=1;
411 dram_avail=0;
412 psys_avail=0;
413 different_units=0;
414 break;
415
416 case 60: /* Haswell */
417 case 69: /* Haswell ULT */
418 case 70: /* Haswell GT3E */
419 case 92: /* Atom Goldmont */
420 case 122: /* Atom Gemini Lake */
421 case 95: /* Atom Denverton */
422 package_avail=1;
423 pp0_avail=1;
424 pp1_avail=1;
425 dram_avail=1;
426 psys_avail=0;
427 different_units=0;
428 break;
429
430 case 61: /* Broadwell */
431 case 71: /* Broadwell-H (GT3E) */
432 case 86: /* Broadwell XEON_D */
433 package_avail=1;
434 pp0_avail=1;
435 pp1_avail=0;
436 dram_avail=1;
437 psys_avail=0;
438 different_units=0;
439 break;
440
441 case 78: /* Skylake Mobile */
442 case 94: /* Skylake Desktop (H/S) */
443 case 142: /* Kabylake Mobile */
444 case 158: /* Kabylake Desktop */
445 package_avail=1;
446 pp0_avail=1;
447 pp1_avail=0;
448 dram_avail=1;
449 psys_avail=1;
450 different_units=0;
451 break;
452
453 /* Server Class Machines */
454
455 case 45: /* SandyBridge-EP */
456 case 62: /* IvyBridge-EP */
457 package_avail=1;
458 pp0_avail=1;
459 pp1_avail=0;
460 dram_avail=1;
461 psys_avail=0;
462 different_units=0;
463 break;
464
465 case 63: /* Haswell-EP */
466 case 79: /* Broadwell-EP */
467 case 85: /* Skylake-X */
468 case 106: /* Icelake-SP */
469 package_avail=1;
470 pp0_avail=1;
471 pp1_avail=0;
472 dram_avail=1;
473 psys_avail=0;
474 different_units=1;
475 break;
476
477
478 case 87: /* Knights Landing (KNL) */
479 case 133: /* Knights Mill (KNM) */
480 package_avail=1;
481 pp0_avail=0;
482 pp1_avail=0;
483 dram_avail=1;
484 psys_avail=0;
485 different_units=1;
486 break;
487
488 default: /* not a supported model */
490 "CPU model not supported",
493 if (strCpy == NULL) HANDLE_STRING_ERROR;
495 goto fn_fail;
496 }
497 }
498
500
502 msr_pkg_energy_status=MSR_AMD_PKG_ENERGY_STATUS;
503 msr_pp0_energy_status=MSR_AMD_PP0_ENERGY_STATUS;
504
505 if (hw_info->cpuid_family!=0x17) {
506 /* Not a family 17h machine */
508 "CPU family not supported",PAPI_MAX_STR_LEN);
510 if (strCpy == NULL) HANDLE_STRING_ERROR;
512 goto fn_fail;
513 }
514
515 package_avail=1;
516 pp0_avail=1; /* Doesn't work on EPYC? */
517 pp1_avail=0;
518 dram_avail=0;
519 psys_avail=0;
520 different_units=0;
521 }
522
523
524 /* Detect how many packages */
525 // Some code below may be flagged by Coverity due to uninitialized array
526 // entries of cpu_to_use[]. This is not a bug; the 'filename' listed below
527 // will have 'cpu0', 'cpu1', sequentially on up to the maximum. Coverity
528 // cannot know that, so its code analysis allows the possibility that the
529 // cpu_to_use[] array is only partially filled in. [Tony C. 11-27-19].
530
531 j=0;
532 while(1) {
533 int num_read;
534
535 strErr=snprintf(filename, BUFSIZ,
536 "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",j);
537 filename[BUFSIZ-1]=0;
538 if (strErr > BUFSIZ) HANDLE_STRING_ERROR;
539 fff=fopen(filename,"r");
540 if (fff==NULL) break;
541 num_read=fscanf(fff,"%d",&package);
542 fclose(fff);
543 if (num_read!=1) {
544 strCpy=strcpy(_rapl_vector.cmp_info.disabled_reason, "Error reading file: ");
545 if (strCpy == NULL) HANDLE_STRING_ERROR;
548 if (strCpy == NULL) HANDLE_STRING_ERROR;
550 goto fn_fail;
551 }
552
553 /* Check if a new package */
554 if ((package >= 0) && (package < nr_cpus)) {
555 if (packages[package] == -1) {
556 SUBDBG("Found package %d out of total %d\n",package,num_packages);
557 packages[package]=package;
558 cpu_to_use[package]=j;
559 num_packages++;
560 }
561 } else {
562 SUBDBG("Package outside of allowed range\n");
564 "Package outside of allowed range",PAPI_MAX_STR_LEN);
566 if (strCpy == NULL) HANDLE_STRING_ERROR;
568 goto fn_fail;
569 }
570
571 j++;
572 }
573 num_cpus=j;
574
575 if (num_packages==0) {
576 SUBDBG("Can't access /dev/cpu/*/<msr_safe | msr>\n");
578 "Can't access /dev/cpu/*/<msr_safe | msr>",PAPI_MAX_STR_LEN);
580 if (strCpy == NULL) HANDLE_STRING_ERROR;
582 goto fn_fail;
583 }
584
585 SUBDBG("Found %d packages with %d cpus\n",num_packages,num_cpus);
586
587 /* Init fd_array */
588
589 fd_array=papi_calloc(num_cpus, sizeof(struct fd_array_t));
590 if (fd_array==NULL) {
592 goto fn_fail;
593 }
594
595 fd=open_fd(cpu_to_use[0]);
596 if (fd<0) {
598 "Can't open fd for cpu0: %s",strerror(errno));
602 goto fn_fail;
603 }
604
605 /* Verify needed MSR is readable. In a guest VM it may not be readable*/
606 if (pread(fd, &result, sizeof result, msr_rapl_power_unit) != sizeof result ) {
608 "Unable to access RAPL registers",PAPI_MAX_STR_LEN);
610 if (strCpy == NULL) HANDLE_STRING_ERROR;
612 goto fn_fail;
613 }
614
615 /* Calculate the units used */
617
618 /* units are 0.5^UNIT_VALUE */
619 /* which is the same as 1/(2^UNIT_VALUE) */
620
624
625 /* Note! On Haswell-EP DRAM energy is fixed at 15.3uJ */
626 /* see https://lkml.org/lkml/2015/3/20/582 */
627 /* Knights Landing is the same */
628 /* so is Broadwell-EP */
629 if ( different_units ) {
631 }
632 else {
634 }
635
636 SUBDBG("Power units = %.3fW\n",1.0/power_divisor);
637 SUBDBG("CPU Energy units = %.8fJ\n",1.0/cpu_energy_divisor);
638 SUBDBG("DRAM Energy units = %.8fJ\n",1.0/dram_energy_divisor);
639 SUBDBG("Time units = %.8fs\n",1.0/time_divisor);
640
641 /* Allocate space for events */
642 /* Include room for both counts and scaled values */
643
644 num_events= ((package_avail*num_packages) +
645 (pp0_avail*num_packages) +
646 (pp1_avail*num_packages) +
647 (dram_avail*num_packages) +
648 (psys_avail*num_packages)) * 2;
649
651 num_events+=(4*num_packages) * 2;
652 }
653
656 if (rapl_native_events == NULL) {
658 "%s:%i rapl_native_events papi_calloc for %lu bytes failed.", __FILE__, __LINE__, num_events*sizeof(_rapl_native_event_entry_t));
662 goto fn_fail;
663 }
664
665 i = 0;
666 k = num_events/2;
667
668 /* Create events for package power info */
669
671 for(j=0;j<num_packages;j++) {
672 strErr=snprintf(rapl_native_events[i].name, PAPI_MAX_STR_LEN,
673 "THERMAL_SPEC_CNT:PACKAGE%d",j);
676
677 strErr=snprintf(rapl_native_events[i].description, PAPI_MAX_STR_LEN,
678 "Thermal specification in counts; package %d",j);
681 rapl_native_events[i].fd_offset=cpu_to_use[j];
686
687 strErr=snprintf(rapl_native_events[k].name, PAPI_MAX_STR_LEN,
688 "THERMAL_SPEC:PACKAGE%d",j);
691
692 strCpy=strncpy(rapl_native_events[k].units,"W",PAPI_MIN_STR_LEN);
694 if (strCpy == NULL) HANDLE_STRING_ERROR;
695
696 strErr=snprintf(rapl_native_events[k].description, PAPI_MAX_STR_LEN,
697 "Thermal specification for package %d",j);
700 rapl_native_events[k].fd_offset=cpu_to_use[j];
705
706 i++;
707 k++;
708 }
709
711 for(j=0;j<num_packages;j++) {
712 strErr=snprintf(rapl_native_events[i].name, PAPI_MAX_STR_LEN,
713 "MINIMUM_POWER_CNT:PACKAGE%d",j);
716 strErr=snprintf(rapl_native_events[i].description, PAPI_MAX_STR_LEN,
717 "Minimum power in counts; package %d",j);
720 rapl_native_events[i].fd_offset=cpu_to_use[j];
725
726 strErr=snprintf(rapl_native_events[k].name, PAPI_MAX_STR_LEN,
727 "MINIMUM_POWER:PACKAGE%d",j);
730 strCpy=strncpy(rapl_native_events[k].units,"W",PAPI_MIN_STR_LEN);
732 if (strCpy == NULL) HANDLE_STRING_ERROR;
733 strErr=snprintf(rapl_native_events[k].description, PAPI_MAX_STR_LEN,
734 "Minimum power for package %d",j);
737 rapl_native_events[k].fd_offset=cpu_to_use[j];
742
743 i++;
744 k++;
745 }
746
748 for(j=0;j<num_packages;j++) {
749 strErr=snprintf(rapl_native_events[i].name, PAPI_MAX_STR_LEN,
750 "MAXIMUM_POWER_CNT:PACKAGE%d",j);
753 strErr=snprintf(rapl_native_events[i].description, PAPI_MAX_STR_LEN,
754 "Maximum power in counts; package %d",j);
757 rapl_native_events[i].fd_offset=cpu_to_use[j];
762
763 strErr=snprintf(rapl_native_events[k].name, PAPI_MAX_STR_LEN,
764 "MAXIMUM_POWER:PACKAGE%d",j);
767 strCpy=strncpy(rapl_native_events[k].units,"W",PAPI_MIN_STR_LEN);
769 if (strCpy == NULL) HANDLE_STRING_ERROR;
770 strErr=snprintf(rapl_native_events[k].description, PAPI_MAX_STR_LEN,
771 "Maximum power for package %d",j);
774 rapl_native_events[k].fd_offset=cpu_to_use[j];
779
780 i++;
781 k++;
782 }
783
785 for(j=0;j<num_packages;j++) {
786 strErr=snprintf(rapl_native_events[i].name, PAPI_MAX_STR_LEN,
787 "MAXIMUM_TIME_WINDOW_CNT:PACKAGE%d",j);
790 strErr=snprintf(rapl_native_events[i].description, PAPI_MAX_STR_LEN,
791 "Maximum time window in counts; package %d",j);
794 rapl_native_events[i].fd_offset=cpu_to_use[j];
799
800 strErr=snprintf(rapl_native_events[k].name, PAPI_MAX_STR_LEN,
801 "MAXIMUM_TIME_WINDOW:PACKAGE%d",j);
804 strCpy=strncpy(rapl_native_events[k].units,"s",PAPI_MIN_STR_LEN);
806 if (strCpy == NULL) HANDLE_STRING_ERROR;
807 strErr=snprintf(rapl_native_events[k].description, PAPI_MAX_STR_LEN,
808 "Maximum time window for package %d",j);
811 rapl_native_events[k].fd_offset=cpu_to_use[j];
816
817 i++;
818 k++;
819 }
820
821 /* Create Events for energy measurements */
822
823 if (package_avail) {
824 for(j=0;j<num_packages;j++) {
825 strErr=snprintf(rapl_native_events[i].name, PAPI_MAX_STR_LEN,
826 "PACKAGE_ENERGY_CNT:PACKAGE%d",j);
829 strErr=snprintf(rapl_native_events[i].description, PAPI_MAX_STR_LEN,
830 "Energy used in counts by chip package %d",j);
833 rapl_native_events[i].fd_offset=cpu_to_use[j];
834 rapl_native_events[i].msr=msr_pkg_energy_status;
838
839 strErr=snprintf(rapl_native_events[k].name, PAPI_MAX_STR_LEN,
840 "PACKAGE_ENERGY:PACKAGE%d",j);
843 strCpy=strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
845 if (strCpy == NULL) HANDLE_STRING_ERROR;
846 strErr=snprintf(rapl_native_events[k].description, PAPI_MAX_STR_LEN,
847 "Energy used by chip package %d",j);
850 rapl_native_events[k].fd_offset=cpu_to_use[j];
851 rapl_native_events[k].msr=msr_pkg_energy_status;
855
856 i++;
857 k++;
858 }
859 }
860
861 if (pp1_avail) {
862 for(j=0;j<num_packages;j++) {
863 strErr=snprintf(rapl_native_events[i].name, PAPI_MAX_STR_LEN,
864 "PP1_ENERGY_CNT:PACKAGE%d",j);
867 strErr=snprintf(rapl_native_events[i].description, PAPI_MAX_STR_LEN,
868 "Energy used in counts by Power Plane 1 (Often GPU) on package %d",j);
871 rapl_native_events[i].fd_offset=cpu_to_use[j];
876
877 strErr=snprintf(rapl_native_events[k].name, PAPI_MAX_STR_LEN,
878 "PP1_ENERGY:PACKAGE%d",j);
881 strCpy=strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
883 if (strCpy == NULL) HANDLE_STRING_ERROR;
884 strErr=snprintf(rapl_native_events[k].description, PAPI_MAX_STR_LEN,
885 "Energy used by Power Plane 1 (Often GPU) on package %d",j);
888 rapl_native_events[k].fd_offset=cpu_to_use[j];
893
894 i++;
895 k++;
896 }
897 }
898
899 if (dram_avail) {
900 for(j=0;j<num_packages;j++) {
901 strErr=snprintf(rapl_native_events[i].name, PAPI_MAX_STR_LEN,
902 "DRAM_ENERGY_CNT:PACKAGE%d",j);
905 strErr=snprintf(rapl_native_events[i].description, PAPI_MAX_STR_LEN,
906 "Energy used in counts by DRAM on package %d",j);
909 rapl_native_events[i].fd_offset=cpu_to_use[j];
914
915 strErr=snprintf(rapl_native_events[k].name,PAPI_MAX_STR_LEN,
916 "DRAM_ENERGY:PACKAGE%d",j);
919 strCpy=strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
921 if (strCpy == NULL) HANDLE_STRING_ERROR;
922 strErr=snprintf(rapl_native_events[k].description, PAPI_MAX_STR_LEN,
923 "Energy used by DRAM on package %d",j);
926 rapl_native_events[k].fd_offset=cpu_to_use[j];
931
932 i++;
933 k++;
934 }
935 }
936
937 if (psys_avail) {
938 for(j=0;j<num_packages;j++) {
939
940 strErr=snprintf(rapl_native_events[i].name, PAPI_MAX_STR_LEN,
941 "PSYS_ENERGY_CNT:PACKAGE%d",j);
944 strErr=snprintf(rapl_native_events[i].description, PAPI_MAX_STR_LEN,
945 "Energy used in counts by SoC on package %d",j);
948 rapl_native_events[i].fd_offset=cpu_to_use[j];
953
954 strErr=snprintf(rapl_native_events[k].name, PAPI_MAX_STR_LEN,
955 "PSYS_ENERGY:PACKAGE%d",j);
958 strCpy=strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
960 if (strCpy == NULL) HANDLE_STRING_ERROR;
961 strErr=snprintf(rapl_native_events[k].description, PAPI_MAX_STR_LEN,
962 "Energy used by SoC on package %d",j);
965 rapl_native_events[k].fd_offset=cpu_to_use[j];
970
971 i++;
972 k++;
973 }
974 }
975
976 if (pp0_avail) {
977 for(j=0;j<num_packages;j++) {
978 strErr=snprintf(rapl_native_events[i].name, PAPI_MAX_STR_LEN,
979 "PP0_ENERGY_CNT:PACKAGE%d",j);
982 strErr=snprintf(rapl_native_events[i].description, PAPI_MAX_STR_LEN,
983 "Energy used in counts by all cores in package %d",j);
986 rapl_native_events[i].fd_offset=cpu_to_use[j];
987 rapl_native_events[i].msr=msr_pp0_energy_status;
991
992 strErr=snprintf(rapl_native_events[k].name, PAPI_MAX_STR_LEN,
993 "PP0_ENERGY:PACKAGE%d",j);
996 strCpy=strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
998 if (strCpy == NULL) HANDLE_STRING_ERROR;
999 strErr=snprintf(rapl_native_events[k].description, PAPI_MAX_STR_LEN,
1000 "Energy used by all cores in package %d",j);
1003 rapl_native_events[k].fd_offset=cpu_to_use[j];
1004 rapl_native_events[k].msr=msr_pp0_energy_status;
1008
1009 i++;
1010 k++;
1011 }
1012 }
1013
1014 /* Export the total number of events available */
1016
1019
1020
1021 /* Export the component id */
1023
1024 fn_exit:
1025 _papi_hwd[cidx]->cmp_info.disabled = retval;
1026 return retval;
1027 fn_fail:
1028 goto fn_exit;
1029}
1030
1031
1032/*
1033 * Control of counters (Reading/Writing/Starting/Stopping/Setup)
1034 * functions
1035 */
1036static int
1038{
1039
1041 int i;
1042
1043 for(i=0;i<RAPL_MAX_COUNTERS;i++) {
1044 control->being_measured[i]=0;
1045 }
1046
1047 return PAPI_OK;
1048}
1049
1050static int
1052{
1053 _rapl_context_t* context = (_rapl_context_t*) ctx;
1055 long long now = PAPI_get_real_usec();
1056 int i;
1057
1058
1059 for( i = 0; i < RAPL_MAX_COUNTERS; i++ ) {
1060 if ((control->being_measured[i]) && (control->need_difference[i])) {
1061 context->start_value[i]=(read_rapl_value(i) & 0xFFFFFFFF);
1062 context->accumulated_value[i]=0;
1063 }
1064 }
1065
1066 control->lastupdate = now;
1067
1068 return PAPI_OK;
1069}
1070
1071static int
1073{
1074 /* read values */
1075 _rapl_context_t* context = (_rapl_context_t*) ctx;
1077 long long now = PAPI_get_real_usec();
1078 int i;
1079 long long temp, newstart;
1080
1081 for ( i = 0; i < RAPL_MAX_COUNTERS; i++ ) {
1082 if (control->being_measured[i]) {
1083 temp = read_rapl_value(i);
1084 if (control->need_difference[i]) {
1085 temp &= 0xFFFFFFFF;
1086 newstart = temp;
1087 /* test for wrap around */
1088 if (temp < context->start_value[i] ) {
1089 SUBDBG("Wraparound!\nstart:\t%#016x\ttemp:\t%#016x",
1090 (unsigned)context->start_value[i], (unsigned)temp);
1091 temp += (0x100000000 - context->start_value[i]);
1092 SUBDBG("\tresult:\t%#016x\n", (unsigned)temp);
1093 } else {
1094 temp -= context->start_value[i];
1095 }
1096 // reset the start value, add to accum, set temp for convert call.
1097 context->start_value[i]=newstart;
1098 context->accumulated_value[i] += temp;
1099 temp = context->accumulated_value[i];
1100 }
1101 control->count[i] = convert_rapl_energy( i, temp );
1102 }
1103 }
1104 control->lastupdate = now;
1105 return PAPI_OK;
1106}
1107
1108/* Shutdown a thread */
1109static int
1111{
1112 ( void ) ctx;
1113 return PAPI_OK;
1114}
1115
1116int
1118 long long **events, int flags)
1119{
1120 (void) flags;
1121
1122 _rapl_stop( ctx, ctl );
1123
1124 /* Pass back a pointer to our results */
1125 *events = ((_rapl_control_state_t*) ctl)->count;
1126
1127 return PAPI_OK;
1128}
1129
1130
1131/*
1132 * Clean up what was setup in rapl_init_component().
1133 */
1134static int
1136{
1137 int i;
1138
1140 if (fd_array) {
1141 for(i=0;i<num_cpus;i++) {
1142 if (fd_array[i].open) close(fd_array[i].fd);
1143 }
1145 }
1146
1147 return PAPI_OK;
1148}
1149
1150
1151/* This function sets various options in the component
1152 * The valid codes being passed in are PAPI_SET_DEFDOM,
1153 * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
1154 */
1155static int
1157{
1158 ( void ) ctx;
1159 ( void ) code;
1160 ( void ) option;
1161
1162 return PAPI_OK;
1163}
1164
1165
1166static int
1169 hwd_context_t *ctx )
1170{
1171 int i, index;
1172 ( void ) ctx;
1173
1175
1176 /* Ugh, what is this native[] stuff all about ?*/
1177 /* Mostly remap stuff in papi_internal */
1178
1179 for(i=0;i<RAPL_MAX_COUNTERS;i++) {
1180 control->being_measured[i]=0;
1181 }
1182
1183 for( i = 0; i < count; i++ ) {
1184 index=native[i].ni_event&PAPI_NATIVE_AND_MASK;
1185 native[i].ni_position=rapl_native_events[index].resources.selector - 1;
1186 control->being_measured[index]=1;
1187
1188 /* Only need to subtract if it's a PACKAGE_ENERGY or ENERGY_CNT type */
1189 control->need_difference[index]=
1194 }
1195
1196 return PAPI_OK;
1197}
1198
1199
1200/*
1201 * This function has to set the bits needed to count different domains
1202 * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
1203 * By default return PAPI_EINVAL if none of those are specified
1204 * and PAPI_OK with success
1205 * PAPI_DOM_USER is only user context is counted
1206 * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
1207 * PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses)
1208 * PAPI_DOM_ALL is all of the domains
1209 */
1210static int
1212{
1213 ( void ) ctl;
1214
1215 /* In theory we only support system-wide mode */
1216 /* How to best handle that? */
1217 if ( PAPI_DOM_ALL != domain )
1218 return PAPI_EINVAL;
1219
1220 return PAPI_OK;
1221}
1222
1223
1224static int
1226{
1227 ( void ) ctx;
1228 ( void ) ctl;
1229
1230 return PAPI_OK;
1231}
1232
1233
1234/*
1235 * Native Event functions
1236 */
1237static int
1238_rapl_ntv_enum_events( unsigned int *EventCode, int modifier )
1239{
1240
1241 int index;
1242
1243 switch ( modifier ) {
1244
1245 case PAPI_ENUM_FIRST:
1246
1247 if (num_events==0) {
1248 return PAPI_ENOEVNT;
1249 }
1250 *EventCode = 0;
1251
1252 return PAPI_OK;
1253
1254
1255 case PAPI_ENUM_EVENTS:
1256
1257 index = *EventCode & PAPI_NATIVE_AND_MASK;
1258
1259 if ( index < num_events - 1 ) {
1260 *EventCode = *EventCode + 1;
1261 return PAPI_OK;
1262 } else {
1263 return PAPI_ENOEVNT;
1264 }
1265 break;
1266
1267 default:
1268 return PAPI_EINVAL;
1269 }
1270
1271 return PAPI_EINVAL;
1272}
1273
1274/*
1275 *
1276 */
1277static int
1278_rapl_ntv_code_to_name( unsigned int EventCode, char *name, int len )
1279{
1280
1281 int index = EventCode & PAPI_NATIVE_AND_MASK;
1282
1283 if ( index >= 0 && index < num_events ) {
1284 strncpy( name, rapl_native_events[index].name, len );
1285 return PAPI_OK;
1286 }
1287
1288 return PAPI_ENOEVNT;
1289}
1290
1291/*
1292 *
1293 */
1294static int
1295_rapl_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
1296{
1297 int index = EventCode;
1298
1299 if ( index >= 0 && index < num_events ) {
1300 strncpy( name, rapl_native_events[index].description, len );
1301 return PAPI_OK;
1302 }
1303 return PAPI_ENOEVNT;
1304}
1305
1306static int
1307_rapl_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
1308{
1309
1310 int index = EventCode;
1311
1312 if ( ( index < 0) || (index >= num_events )) return PAPI_ENOEVNT;
1313
1314 strncpy( info->symbol, rapl_native_events[index].name, sizeof(info->symbol)-1);
1315 info->symbol[sizeof(info->symbol)-1] = '\0';
1316
1317 strncpy( info->long_descr, rapl_native_events[index].description, sizeof(info->long_descr)-1);
1318 info->long_descr[sizeof(info->long_descr)-1] = '\0';
1319
1320 strncpy( info->units, rapl_native_events[index].units, sizeof(info->units)-1);
1321 info->units[sizeof(info->units)-1] = '\0';
1322
1324
1325 return PAPI_OK;
1326}
1327
1328
1329
1331 .cmp_info = { /* (unspecified values are initialized to 0) */
1332 .name = "rapl",
1333 .short_name = "rapl",
1334 .description = "Linux RAPL energy measurements",
1335 .version = "5.3.0",
1336 .default_domain = PAPI_DOM_ALL,
1337 .default_granularity = PAPI_GRN_SYS,
1338 .available_granularities = PAPI_GRN_SYS,
1339 .hardware_intr_sig = PAPI_INT_SIGNAL,
1340 .available_domains = PAPI_DOM_ALL,
1341 },
1342
1343 /* sizes of framework-opaque component-private structures */
1344 .size = {
1345 .context = sizeof ( _rapl_context_t ),
1346 .control_state = sizeof ( _rapl_control_state_t ),
1347 .reg_value = sizeof ( _rapl_register_t ),
1348 .reg_alloc = sizeof ( _rapl_reg_alloc_t ),
1349 },
1350 /* function pointers in this component */
1351 .init_thread = _rapl_init_thread,
1352 .init_component = _rapl_init_component,
1353 .init_control_state = _rapl_init_control_state,
1354 .start = _rapl_start,
1355 .stop = _rapl_stop,
1356 .read = _rapl_read,
1357 .shutdown_thread = _rapl_shutdown_thread,
1358 .shutdown_component = _rapl_shutdown_component,
1359 .ctl = _rapl_ctl,
1360
1361 .update_control_state = _rapl_update_control_state,
1362 .set_domain = _rapl_set_domain,
1363 .reset = _rapl_reset,
1364
1365 .ntv_enum_events = _rapl_ntv_enum_events,
1366 .ntv_code_to_name = _rapl_ntv_code_to_name,
1367 .ntv_code_to_descr = _rapl_ntv_code_to_descr,
1368 .ntv_code_to_info = _rapl_ntv_code_to_info,
1369};
volatile int result
int i
int open(const char *pathname, int flags, mode_t mode)
Definition: appio.c:188
int close(int fd)
Definition: appio.c:179
int errno
static const PAPI_hw_info_t * hw_info
Definition: byte_profile.c:28
static long count
get real time counter value in microseconds
struct papi_vectors * _papi_hwd[]
#define PAPI_ENUM_EVENTS
Definition: f90papi.h:224
#define PAPI_OK
Definition: f90papi.h:73
#define PAPI_ENUM_FIRST
Definition: f90papi.h:85
#define PAPI_MIN_STR_LEN
Definition: f90papi.h:208
#define PAPI_ENOEVNT
Definition: f90papi.h:139
#define PAPI_DATATYPE_FP64
Definition: f90papi.h:171
#define PAPI_VENDOR_INTEL
Definition: f90papi.h:275
#define PAPI_VENDOR_AMD
Definition: f90papi.h:230
#define PAPI_EINVAL
Definition: f90papi.h:115
#define PAPI_ENOSUPP
Definition: f90papi.h:244
#define PAPI_MAX_STR_LEN
Definition: f90papi.h:77
#define PAPI_DATATYPE_UINT64
Definition: f90papi.h:278
#define PAPI_ESYS
Definition: f90papi.h:136
#define PAPI_GRN_SYS
Definition: f90papi.h:43
#define PAPI_ENOMEM
Definition: f90papi.h:16
#define PAPI_ENOIMPL
Definition: f90papi.h:219
#define PAPI_DOM_ALL
Definition: f90papi.h:261
FILE * fff[MAX_EVENTS]
char events[MAX_EVENTS][BUFSIZ]
static int _rapl_init_thread(hwd_context_t *ctx)
Definition: linux-rapl.c:319
#define MSR_INTEL_PKG_ENERGY_STATUS
Definition: linux-rapl.c:62
static int _rapl_set_domain(hwd_control_state_t *ctl, int domain)
Definition: linux-rapl.c:1211
#define ENERGY_UNIT_OFFSET
Definition: linux-rapl.c:90
#define RAPL_MAX_COUNTERS
Definition: linux-rapl.c:127
struct fd_array_t * fd_array
Definition: linux-rapl.c:160
#define PACKAGE_TIME_WINDOW
Definition: linux-rapl.c:171
static int _rapl_ntv_code_to_name(unsigned int EventCode, char *name, int len)
Definition: linux-rapl.c:1278
#define POWER_UNIT_MASK
Definition: linux-rapl.c:88
static int _rapl_ntv_enum_events(unsigned int *EventCode, int modifier)
Definition: linux-rapl.c:1238
#define MSR_AMD_PP0_ENERGY_STATUS
Definition: linux-rapl.c:44
#define PACKAGE_MINIMUM_CNT
Definition: linux-rapl.c:174
static int _rapl_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-rapl.c:1072
#define MSR_PLATFORM_ENERGY_STATUS
Definition: linux-rapl.c:84
#define THERMAL_SHIFT
Definition: linux-rapl.c:98
static _rapl_native_event_entry_t * rapl_native_events
Definition: linux-rapl.c:158
#define MSR_DRAM_ENERGY_STATUS
Definition: linux-rapl.c:79
#define PACKAGE_MAXIMUM
Definition: linux-rapl.c:170
#define MSR_INTEL_PP0_ENERGY_STATUS
Definition: linux-rapl.c:68
static long long read_rapl_value(int index)
Definition: linux-rapl.c:222
int cpu_energy_divisor
Definition: linux-rapl.c:164
static int num_events
Definition: linux-rapl.c:159
#define MAXIMUM_POWER_SHIFT
Definition: linux-rapl.c:100
#define TIME_UNIT_OFFSET
Definition: linux-rapl.c:93
static int _rapl_shutdown_component(void)
Definition: linux-rapl.c:1135
#define PACKAGE_THERMAL
Definition: linux-rapl.c:168
#define MSR_PKG_POWER_INFO
Definition: linux-rapl.c:64
#define POWER_UNIT_OFFSET
Definition: linux-rapl.c:87
static int _rapl_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
Definition: linux-rapl.c:1156
#define TIME_UNIT_MASK
Definition: linux-rapl.c:94
int dram_energy_divisor
Definition: linux-rapl.c:164
static long long convert_rapl_energy(int index, long long value)
Definition: linux-rapl.c:231
#define MSR_AMD_PKG_ENERGY_STATUS
Definition: linux-rapl.c:43
static int _rapl_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-rapl.c:1051
#define MSR_PP1_ENERGY_STATUS
Definition: linux-rapl.c:74
static int _rapl_shutdown_thread(hwd_context_t *ctx)
Definition: linux-rapl.c:1110
static int _rapl_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
Definition: linux-rapl.c:1307
int _rapl_read(hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags)
Definition: linux-rapl.c:1117
#define MSR_INTEL_RAPL_POWER_UNIT
Definition: linux-rapl.c:58
#define MSR_AMD_RAPL_POWER_UNIT
Definition: linux-rapl.c:41
unsigned int msr_rapl_power_unit
Definition: linux-rapl.c:165
static int num_packages
Definition: linux-rapl.c:161
#define PACKAGE_MAXIMUM_CNT
Definition: linux-rapl.c:175
papi_vector_t _rapl_vector
Definition: linux-rapl.c:151
#define DRAM_ENERGY
Definition: linux-rapl.c:177
#define POWER_INFO_UNIT_MASK
Definition: linux-rapl.c:97
static int _rapl_reset(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-rapl.c:1225
#define PACKAGE_THERMAL_CNT
Definition: linux-rapl.c:173
#define PACKAGE_MINIMUM
Definition: linux-rapl.c:169
int power_divisor
Definition: linux-rapl.c:163
#define PACKAGE_TIME_WINDOW_CNT
Definition: linux-rapl.c:176
#define ENERGY_UNIT_MASK
Definition: linux-rapl.c:91
static int open_fd(int offset)
Definition: linux-rapl.c:198
#define PLATFORM_ENERGY
Definition: linux-rapl.c:178
#define MINIMUM_POWER_SHIFT
Definition: linux-rapl.c:99
#define PACKAGE_ENERGY
Definition: linux-rapl.c:167
static int _rapl_ntv_code_to_descr(unsigned int EventCode, char *name, int len)
Definition: linux-rapl.c:1295
static long long read_msr(int fd, unsigned int which)
Definition: linux-rapl.c:185
static int _rapl_init_component(int cidx)
Definition: linux-rapl.c:332
#define MAXIMUM_TIME_WINDOW_SHIFT
Definition: linux-rapl.c:101
#define PACKAGE_ENERGY_CNT
Definition: linux-rapl.c:172
static int _rapl_update_control_state(hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx)
Definition: linux-rapl.c:1167
static int _rapl_init_control_state(hwd_control_state_t *ctl)
Definition: linux-rapl.c:1037
static int num_cpus
Definition: linux-rapl.c:161
int time_divisor
Definition: linux-rapl.c:163
static int get_kernel_nr_cpus(void)
Definition: linux-rapl.c:296
#define HANDLE_STRING_ERROR
Definition: linux-rapl.c:35
uint16_t type
#define PAPI_NATIVE_AND_MASK
Return codes and api definitions.
#define SUBDBG(format, args...)
Definition: papi_debug.h:64
FILE * stderr
int fclose(FILE *__stream)
#define PAPI_INT_SIGNAL
Definition: papi_internal.h:52
#define papi_calloc(a, b)
Definition: papi_memory.h:37
#define papi_free(a)
Definition: papi_memory.h:35
static FILE * fp
static int native
static int cidx
papi_mdi_t _papi_hwi_system_info
Definition: papi_internal.c:56
char units[MAX_EVENTS][BUFSIZ]
Definition: powercap_plot.c:15
const char * name
Definition: rocs.c:225
long long int long long
Definition: sde_internal.h:85
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:627
char disabled_reason[PAPI_HUGE_STR_LEN]
Definition: papi.h:634
char units[PAPI_MIN_STR_LEN]
Definition: papi.h:969
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:960
char long_descr[PAPI_HUGE_STR_LEN]
Definition: papi.h:963
Hardware info structure.
Definition: papi.h:774
int cpuid_family
Definition: papi.h:786
int cpuid_model
Definition: papi.h:787
int vendor
Definition: papi.h:781
long long start_value[RAPL_MAX_COUNTERS]
Definition: linux-rapl.c:145
_rapl_control_state_t state
Definition: linux-rapl.c:147
long long accumulated_value[RAPL_MAX_COUNTERS]
Definition: linux-rapl.c:146
long long count[RAPL_MAX_COUNTERS]
Definition: linux-rapl.c:132
int need_difference[RAPL_MAX_COUNTERS]
Definition: linux-rapl.c:133
int being_measured[RAPL_MAX_COUNTERS]
Definition: linux-rapl.c:131
Definition: linux-rapl.c:110
int return_type
Definition: linux-rapl.c:117
char name[PAPI_MAX_STR_LEN]
Definition: linux-rapl.c:111
char units[PAPI_MIN_STR_LEN]
Definition: linux-rapl.c:112
int fd_offset
Definition: linux-rapl.c:114
char description[PAPI_MAX_STR_LEN]
Definition: linux-rapl.c:113
int msr
Definition: linux-rapl.c:115
_rapl_register_t resources
Definition: linux-rapl.c:118
int type
Definition: linux-rapl.c:116
_rapl_register_t ra_bits
Definition: linux-rapl.c:123
unsigned int selector
Definition: linux-rapl.c:106
PAPI_hw_info_t hw_info
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
int retval
Definition: zero_fork.c:53