PAPI  5.7.0.0
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 
33 /***************/
34 /* AMD Support */
35 /***************/
36 #define MSR_AMD_RAPL_POWER_UNIT 0xc0010299
37 
38 #define MSR_AMD_PKG_ENERGY_STATUS 0xc001029B
39 #define MSR_AMD_PP0_ENERGY_STATUS 0xc001029A
40 
41 
42 /*****************/
43 /* Intel support */
44 /*****************/
45 
46 /*
47  * Platform specific RAPL Domains.
48  * Note that PP1 RAPL Domain is supported on 062A only
49  * And DRAM RAPL Domain is supported on 062D only
50  */
51 
52 /* RAPL defines */
53 #define MSR_INTEL_RAPL_POWER_UNIT 0x606
54 
55 /* Package */
56 #define MSR_PKG_RAPL_POWER_LIMIT 0x610
57 #define MSR_INTEL_PKG_ENERGY_STATUS 0x611
58 #define MSR_PKG_PERF_STATUS 0x613
59 #define MSR_PKG_POWER_INFO 0x614
60 
61 /* PP0 */
62 #define MSR_PP0_POWER_LIMIT 0x638
63 #define MSR_INTEL_PP0_ENERGY_STATUS 0x639
64 #define MSR_PP0_POLICY 0x63A
65 #define MSR_PP0_PERF_STATUS 0x63B
66 
67 /* PP1 */
68 #define MSR_PP1_POWER_LIMIT 0x640
69 #define MSR_PP1_ENERGY_STATUS 0x641
70 #define MSR_PP1_POLICY 0x642
71 
72 /* DRAM */
73 #define MSR_DRAM_POWER_LIMIT 0x618
74 #define MSR_DRAM_ENERGY_STATUS 0x619
75 #define MSR_DRAM_PERF_STATUS 0x61B
76 #define MSR_DRAM_POWER_INFO 0x61C
77 
78 /* PSYS RAPL Domain */
79 #define MSR_PLATFORM_ENERGY_STATUS 0x64d
80 
81 /* RAPL bitsmasks */
82 #define POWER_UNIT_OFFSET 0
83 #define POWER_UNIT_MASK 0x0f
84 
85 #define ENERGY_UNIT_OFFSET 0x08
86 #define ENERGY_UNIT_MASK 0x1f
87 
88 #define TIME_UNIT_OFFSET 0x10
89 #define TIME_UNIT_MASK 0x0f
90 
91 /* RAPL POWER UNIT MASKS */
92 #define POWER_INFO_UNIT_MASK 0x7fff
93 #define THERMAL_SHIFT 0
94 #define MINIMUM_POWER_SHIFT 16
95 #define MAXIMUM_POWER_SHIFT 32
96 #define MAXIMUM_TIME_WINDOW_SHIFT 48
97 
98 
99 typedef struct _rapl_register
100 {
101  unsigned int selector;
103 
104 typedef struct _rapl_native_event_entry
105 {
108  char description[PAPI_MAX_STR_LEN];
110  int msr;
111  int type;
115 
116 typedef struct _rapl_reg_alloc
117 {
120 
121 /* actually 32? But setting this to be safe? */
122 #define RAPL_MAX_COUNTERS 64
123 
124 typedef struct _rapl_control_state
125 {
126  int being_measured[RAPL_MAX_COUNTERS];
128  int need_difference[RAPL_MAX_COUNTERS];
129  long long lastupdate;
131 
132 
133 typedef struct _rapl_context
134 {
135  long long start_value[RAPL_MAX_COUNTERS];
138 
139 
141 
142 struct fd_array_t {
143  int fd;
144  int open;
145 };
146 
148 static int num_events = 0;
149 struct fd_array_t *fd_array=NULL;
150 static int num_packages=0,num_cpus=0;
151 
154 unsigned int msr_rapl_power_unit;
155 
156 #define PACKAGE_ENERGY 0
157 #define PACKAGE_THERMAL 1
158 #define PACKAGE_MINIMUM 2
159 #define PACKAGE_MAXIMUM 3
160 #define PACKAGE_TIME_WINDOW 4
161 #define PACKAGE_ENERGY_CNT 5
162 #define PACKAGE_THERMAL_CNT 6
163 #define PACKAGE_MINIMUM_CNT 7
164 #define PACKAGE_MAXIMUM_CNT 8
165 #define PACKAGE_TIME_WINDOW_CNT 9
166 #define DRAM_ENERGY 10
167 #define PLATFORM_ENERGY 11
168 
169 /***************************************************************************/
170 /****** BEGIN FUNCTIONS USED INTERNALLY SPECIFIC TO THIS COMPONENT *******/
171 /***************************************************************************/
172 
173 
174 static long long read_msr(int fd, unsigned int which) {
175 
176  uint64_t data;
177 
178  if ( fd<0 || pread(fd, &data, sizeof data, which) != sizeof data ) {
179  perror("rdmsr:pread");
180  fprintf(stderr,"rdmsr error, msr %x\n",which);
181  exit(127);
182  }
183 
184  return (long long)data;
185 }
186 
187 static int open_fd(int offset) {
188 
189  int fd=-1;
190  char filename[BUFSIZ];
191 
192  if (fd_array[offset].open==0) {
193  sprintf(filename,"/dev/cpu/%d/msr_safe",offset);
194  fd = open(filename, O_RDONLY);
195  if (fd<0) {
196  sprintf(filename,"/dev/cpu/%d/msr",offset);
197  fd = open(filename, O_RDONLY);
198  }
199  if (fd>=0) {
200  fd_array[offset].fd=fd;
201  fd_array[offset].open=1;
202  }
203  }
204  else {
205  fd=fd_array[offset].fd;
206  }
207 
208  return fd;
209 }
210 
211 static long long read_rapl_value(int index) {
212 
213  int fd;
214 
215  fd=open_fd(rapl_native_events[index].fd_offset);
216  return read_msr(fd,rapl_native_events[index].msr);
217 
218 }
219 
220 static long long convert_rapl_energy(int index, long long value) {
221 
222  union {
223  long long ll;
224  double fp;
225  } return_val;
226 
227  return_val.ll = value; /* default case: return raw input value */
228 
229  if (rapl_native_events[index].type==PACKAGE_ENERGY) {
230  return_val.ll = (long long)(((double)value/cpu_energy_divisor)*1e9);
231  }
232 
233  if (rapl_native_events[index].type==DRAM_ENERGY) {
234  return_val.ll = (long long)(((double)value/dram_energy_divisor)*1e9);
235  }
236 
237  if (rapl_native_events[index].type==PLATFORM_ENERGY) {
238  return_val.ll = (long long)(((double)value/cpu_energy_divisor)*1e9);
239  }
240 
241  if (rapl_native_events[index].type==PACKAGE_THERMAL) {
242  return_val.fp = (double)
244  (double)power_divisor;
245  }
246 
247  if (rapl_native_events[index].type==PACKAGE_MINIMUM) {
248  return_val.fp = (double)
250  (double)power_divisor;
251  }
252 
253  if (rapl_native_events[index].type==PACKAGE_MAXIMUM) {
254  return_val.fp = (double)
256  (double)power_divisor;
257  }
258 
259  if (rapl_native_events[index].type==PACKAGE_TIME_WINDOW) {
260  return_val.fp = (double)
262  (double)time_divisor;
263  }
264 
265  if (rapl_native_events[index].type==PACKAGE_THERMAL_CNT) {
266  return_val.ll = ((value>>THERMAL_SHIFT)&POWER_INFO_UNIT_MASK);
267  }
268 
269  if (rapl_native_events[index].type==PACKAGE_MINIMUM_CNT) {
270  return_val.ll = ((value>>MINIMUM_POWER_SHIFT)&POWER_INFO_UNIT_MASK);
271  }
272 
273  if (rapl_native_events[index].type==PACKAGE_MAXIMUM_CNT) {
274  return_val.ll = ((value>>MAXIMUM_POWER_SHIFT)&POWER_INFO_UNIT_MASK);
275  }
276 
277  if (rapl_native_events[index].type==PACKAGE_TIME_WINDOW_CNT) {
278  return_val.ll = ((value>>MAXIMUM_TIME_WINDOW_SHIFT)&POWER_INFO_UNIT_MASK);
279  }
280 
281  return return_val.ll;
282 }
283 
284 static int
286 {
287  FILE *fff;
288  int num_read, nr_cpus = 1;
289  fff=fopen("/sys/devices/system/cpu/kernel_max","r");
290  if (fff==NULL) return nr_cpus;
291  num_read=fscanf(fff,"%d",&nr_cpus);
292  fclose(fff);
293  if (num_read==1) {
294  nr_cpus++;
295  } else {
296  nr_cpus = 1;
297  }
298  return nr_cpus;
299 }
300 
301 /************************* PAPI Functions **********************************/
302 
303 
304 /*
305  * This is called whenever a thread is initialized
306  */
307 static int
309 {
310  ( void ) ctx;
311 
312  return PAPI_OK;
313 }
314 
315 
316 
317 /*
318  * Called when PAPI process is initialized (i.e. PAPI_library_init)
319  */
320 static int
322 {
323  int i,j,k,fd;
324  FILE *fff;
325  char filename[BUFSIZ];
326 
327  int package_avail, dram_avail, pp0_avail, pp1_avail, psys_avail;
328  int different_units;
329 
330  long long result;
331  int package;
332 
333  const PAPI_hw_info_t *hw_info;
334 
335  int nr_cpus = get_kernel_nr_cpus();
336  int packages[nr_cpus];
337  int cpu_to_use[nr_cpus];
338 
339  unsigned int msr_pkg_energy_status,msr_pp0_energy_status;
340 
341 
342  /* Fill with sentinel values */
343  for (i=0; i<nr_cpus; ++i) {
344  packages[i] = -1;
345  cpu_to_use[i] = -1;
346  }
347 
348 
349  /* check if supported processor */
351 
352  /* Ugh can't use PAPI_get_hardware_info() if
353  PAPI library not done initializing yet */
354 
355  switch(hw_info->vendor) {
356  case PAPI_VENDOR_INTEL:
357  case PAPI_VENDOR_AMD:
358  break;
359  default:
361  "Not a supported processor",PAPI_MAX_STR_LEN);
362  return PAPI_ENOSUPP;
363  }
364 
365 
366  /* Make sure it is a family 6 Intel Chip */
367 
369 
371  msr_pkg_energy_status=MSR_INTEL_PKG_ENERGY_STATUS;
372  msr_pp0_energy_status=MSR_INTEL_PP0_ENERGY_STATUS;
373 
374  if (hw_info->cpuid_family!=6) {
375  /* Not a family 6 machine */
377  "CPU family not supported",PAPI_MAX_STR_LEN);
378  return PAPI_ENOIMPL;
379  }
380 
381  /* Detect RAPL support */
382  switch(hw_info->cpuid_model) {
383 
384  /* Desktop / Laptops */
385 
386  case 42: /* SandyBridge */
387  case 58: /* IvyBridge */
388  package_avail=1;
389  pp0_avail=1;
390  pp1_avail=1;
391  dram_avail=0;
392  psys_avail=0;
393  different_units=0;
394  break;
395 
396  case 60: /* Haswell */
397  case 69: /* Haswell ULT */
398  case 70: /* Haswell GT3E */
399  case 92: /* Atom Goldmont */
400  case 122: /* Atom Gemini Lake */
401  case 95: /* Atom Denverton */
402  package_avail=1;
403  pp0_avail=1;
404  pp1_avail=1;
405  dram_avail=1;
406  psys_avail=0;
407  different_units=0;
408  break;
409 
410  case 61: /* Broadwell */
411  case 71: /* Broadwell-H (GT3E) */
412  case 86: /* Broadwell XEON_D */
413  package_avail=1;
414  pp0_avail=1;
415  pp1_avail=0;
416  dram_avail=1;
417  psys_avail=0;
418  different_units=0;
419  break;
420 
421  case 78: /* Skylake Mobile */
422  case 94: /* Skylake Desktop (H/S) */
423  case 142: /* Kabylake Mobile */
424  case 158: /* Kabylake Desktop */
425  package_avail=1;
426  pp0_avail=1;
427  pp1_avail=0;
428  dram_avail=1;
429  psys_avail=1;
430  different_units=0;
431  break;
432 
433  /* Server Class Machines */
434 
435  case 45: /* SandyBridge-EP */
436  case 62: /* IvyBridge-EP */
437  package_avail=1;
438  pp0_avail=1;
439  pp1_avail=0;
440  dram_avail=1;
441  psys_avail=0;
442  different_units=0;
443  break;
444 
445  case 63: /* Haswell-EP */
446  case 79: /* Broadwell-EP */
447  case 85: /* Skylake-X */
448  package_avail=1;
449  pp0_avail=1;
450  pp1_avail=0;
451  dram_avail=1;
452  psys_avail=0;
453  different_units=1;
454  break;
455 
456 
457  case 87: /* Knights Landing (KNL) */
458  case 133: /* Knights Mill (KNM) */
459  package_avail=1;
460  pp0_avail=0;
461  pp1_avail=0;
462  dram_avail=1;
463  psys_avail=0;
464  different_units=1;
465  break;
466 
467  default: /* not a supported model */
469  "CPU model not supported",
471  return PAPI_ENOIMPL;
472  }
473  }
474 
476 
478  msr_pkg_energy_status=MSR_AMD_PKG_ENERGY_STATUS;
479  msr_pp0_energy_status=MSR_AMD_PP0_ENERGY_STATUS;
480 
481  if (hw_info->cpuid_family!=0x17) {
482  /* Not a family 17h machine */
484  "CPU family not supported",PAPI_MAX_STR_LEN);
485  return PAPI_ENOIMPL;
486  }
487 
488  package_avail=1;
489  pp0_avail=1; /* Doesn't work on EPYC? */
490  pp1_avail=0;
491  dram_avail=0;
492  psys_avail=0;
493  different_units=0;
494  }
495 
496 
497  /* Detect how many packages */
498  j=0;
499  while(1) {
500  int num_read;
501 
502  sprintf(filename,
503  "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",j);
504  fff=fopen(filename,"r");
505  if (fff==NULL) break;
506  num_read=fscanf(fff,"%d",&package);
507  fclose(fff);
508  if (num_read!=1) {
509  strcpy(_rapl_vector.cmp_info.disabled_reason, "Error reading file: ");
512  return PAPI_ESYS;
513  }
514 
515  /* Check if a new package */
516  if ((package >= 0) && (package < nr_cpus)) {
517  if (packages[package] == -1) {
518  SUBDBG("Found package %d out of total %d\n",package,num_packages);
519  packages[package]=package;
520  cpu_to_use[package]=j;
521  num_packages++;
522  }
523  } else {
524  SUBDBG("Package outside of allowed range\n");
526  "Package outside of allowed range",PAPI_MAX_STR_LEN);
527  return PAPI_ESYS;
528  }
529 
530  j++;
531  }
532  num_cpus=j;
533 
534  if (num_packages==0) {
535  SUBDBG("Can't access /dev/cpu/*/<msr_safe | msr>\n");
537  "Can't access /dev/cpu/*/<msr_safe | msr>",PAPI_MAX_STR_LEN);
538  return PAPI_ESYS;
539  }
540 
541  SUBDBG("Found %d packages with %d cpus\n",num_packages,num_cpus);
542 
543  /* Init fd_array */
544 
545  fd_array=papi_calloc(num_cpus, sizeof(struct fd_array_t));
546  if (fd_array==NULL) return PAPI_ENOMEM;
547 
548  fd=open_fd(cpu_to_use[0]);
549  if (fd<0) {
551  "Can't open fd for cpu0: %s",strerror(errno));
552  return PAPI_ESYS;
553  }
554 
555  /* Verify needed MSR is readable. In a guest VM it may not be readable*/
556  if (pread(fd, &result, sizeof result, msr_rapl_power_unit) != sizeof result ) {
558  "Unable to access RAPL registers",PAPI_MAX_STR_LEN);
559  return PAPI_ESYS;
560  }
561 
562  /* Calculate the units used */
564 
565  /* units are 0.5^UNIT_VALUE */
566  /* which is the same as 1/(2^UNIT_VALUE) */
567 
571 
572  /* Note! On Haswell-EP DRAM energy is fixed at 15.3uJ */
573  /* see https://lkml.org/lkml/2015/3/20/582 */
574  /* Knights Landing is the same */
575  /* so is Broadwell-EP */
576  if ( different_units ) {
577  dram_energy_divisor=1<<16;
578  }
579  else {
581  }
582 
583  SUBDBG("Power units = %.3fW\n",1.0/power_divisor);
584  SUBDBG("CPU Energy units = %.8fJ\n",1.0/cpu_energy_divisor);
585  SUBDBG("DRAM Energy units = %.8fJ\n",1.0/dram_energy_divisor);
586  SUBDBG("Time units = %.8fs\n",1.0/time_divisor);
587 
588  /* Allocate space for events */
589  /* Include room for both counts and scaled values */
590 
591  num_events= ((package_avail*num_packages) +
592  (pp0_avail*num_packages) +
593  (pp1_avail*num_packages) +
594  (dram_avail*num_packages) +
595  (psys_avail*num_packages)) * 2;
596 
598  num_events+=(4*num_packages) * 2;
599  }
600 
603 
604 
605  i = 0;
606  k = num_events/2;
607 
608  /* Create events for package power info */
609 
611  for(j=0;j<num_packages;j++) {
612  sprintf(rapl_native_events[i].name,
613  "THERMAL_SPEC_CNT:PACKAGE%d",j);
614  sprintf(rapl_native_events[i].description,
615  "Thermal specification in counts; package %d",j);
616  rapl_native_events[i].fd_offset=cpu_to_use[j];
621 
622  sprintf(rapl_native_events[k].name,
623  "THERMAL_SPEC:PACKAGE%d",j);
624  strncpy(rapl_native_events[k].units,"W",PAPI_MIN_STR_LEN);
625  sprintf(rapl_native_events[k].description,
626  "Thermal specification for package %d",j);
627  rapl_native_events[k].fd_offset=cpu_to_use[j];
632 
633  i++;
634  k++;
635  }
636 
638  for(j=0;j<num_packages;j++) {
639  sprintf(rapl_native_events[i].name,
640  "MINIMUM_POWER_CNT:PACKAGE%d",j);
641  sprintf(rapl_native_events[i].description,
642  "Minimum power in counts; package %d",j);
643  rapl_native_events[i].fd_offset=cpu_to_use[j];
648 
649  sprintf(rapl_native_events[k].name,
650  "MINIMUM_POWER:PACKAGE%d",j);
651  strncpy(rapl_native_events[k].units,"W",PAPI_MIN_STR_LEN);
652  sprintf(rapl_native_events[k].description,
653  "Minimum power for package %d",j);
654  rapl_native_events[k].fd_offset=cpu_to_use[j];
659 
660  i++;
661  k++;
662  }
663 
665  for(j=0;j<num_packages;j++) {
666  sprintf(rapl_native_events[i].name,
667  "MAXIMUM_POWER_CNT:PACKAGE%d",j);
668  sprintf(rapl_native_events[i].description,
669  "Maximum power in counts; package %d",j);
670  rapl_native_events[i].fd_offset=cpu_to_use[j];
675 
676  sprintf(rapl_native_events[k].name,
677  "MAXIMUM_POWER:PACKAGE%d",j);
678  strncpy(rapl_native_events[k].units,"W",PAPI_MIN_STR_LEN);
679  sprintf(rapl_native_events[k].description,
680  "Maximum power for package %d",j);
681  rapl_native_events[k].fd_offset=cpu_to_use[j];
686 
687  i++;
688  k++;
689  }
690 
692  for(j=0;j<num_packages;j++) {
693  sprintf(rapl_native_events[i].name,
694  "MAXIMUM_TIME_WINDOW_CNT:PACKAGE%d",j);
695  sprintf(rapl_native_events[i].description,
696  "Maximum time window in counts; package %d",j);
697  rapl_native_events[i].fd_offset=cpu_to_use[j];
702 
703  sprintf(rapl_native_events[k].name,
704  "MAXIMUM_TIME_WINDOW:PACKAGE%d",j);
705  strncpy(rapl_native_events[k].units,"s",PAPI_MIN_STR_LEN);
706  sprintf(rapl_native_events[k].description,
707  "Maximum time window for package %d",j);
708  rapl_native_events[k].fd_offset=cpu_to_use[j];
713 
714  i++;
715  k++;
716  }
717 
718  /* Create Events for energy measurements */
719 
720  if (package_avail) {
721  for(j=0;j<num_packages;j++) {
722  sprintf(rapl_native_events[i].name,
723  "PACKAGE_ENERGY_CNT:PACKAGE%d",j);
724  sprintf(rapl_native_events[i].description,
725  "Energy used in counts by chip package %d",j);
726  rapl_native_events[i].fd_offset=cpu_to_use[j];
727  rapl_native_events[i].msr=msr_pkg_energy_status;
731 
732  sprintf(rapl_native_events[k].name,
733  "PACKAGE_ENERGY:PACKAGE%d",j);
734  strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
735  sprintf(rapl_native_events[k].description,
736  "Energy used by chip package %d",j);
737  rapl_native_events[k].fd_offset=cpu_to_use[j];
738  rapl_native_events[k].msr=msr_pkg_energy_status;
742 
743  i++;
744  k++;
745  }
746  }
747 
748  if (pp1_avail) {
749  for(j=0;j<num_packages;j++) {
750  sprintf(rapl_native_events[i].name,
751  "PP1_ENERGY_CNT:PACKAGE%d",j);
752  sprintf(rapl_native_events[i].description,
753  "Energy used in counts by Power Plane 1 (Often GPU) on package %d",j);
754  rapl_native_events[i].fd_offset=cpu_to_use[j];
759 
760  sprintf(rapl_native_events[k].name,
761  "PP1_ENERGY:PACKAGE%d",j);
762  strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
763  sprintf(rapl_native_events[k].description,
764  "Energy used by Power Plane 1 (Often GPU) on package %d",j);
765  rapl_native_events[k].fd_offset=cpu_to_use[j];
770 
771  i++;
772  k++;
773  }
774  }
775 
776  if (dram_avail) {
777  for(j=0;j<num_packages;j++) {
778  sprintf(rapl_native_events[i].name,
779  "DRAM_ENERGY_CNT:PACKAGE%d",j);
780  sprintf(rapl_native_events[i].description,
781  "Energy used in counts by DRAM on package %d",j);
782  rapl_native_events[i].fd_offset=cpu_to_use[j];
787 
788  sprintf(rapl_native_events[k].name,
789  "DRAM_ENERGY:PACKAGE%d",j);
790  strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
791  sprintf(rapl_native_events[k].description,
792  "Energy used by DRAM on package %d",j);
793  rapl_native_events[k].fd_offset=cpu_to_use[j];
798 
799  i++;
800  k++;
801  }
802  }
803 
804  if (psys_avail) {
805  for(j=0;j<num_packages;j++) {
806 
807  sprintf(rapl_native_events[i].name,
808  "PSYS_ENERGY_CNT:PACKAGE%d",j);
809  sprintf(rapl_native_events[i].description,
810  "Energy used in counts by SoC on package %d",j);
811  rapl_native_events[i].fd_offset=cpu_to_use[j];
816 
817  sprintf(rapl_native_events[k].name,
818  "PSYS_ENERGY:PACKAGE%d",j);
819  strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
820  sprintf(rapl_native_events[k].description,
821  "Energy used by SoC on package %d",j);
822  rapl_native_events[k].fd_offset=cpu_to_use[j];
827 
828  i++;
829  k++;
830  }
831  }
832 
833  if (pp0_avail) {
834  for(j=0;j<num_packages;j++) {
835  sprintf(rapl_native_events[i].name,
836  "PP0_ENERGY_CNT:PACKAGE%d",j);
837  sprintf(rapl_native_events[i].description,
838  "Energy used in counts by all cores in package %d",j);
839  rapl_native_events[i].fd_offset=cpu_to_use[j];
840  rapl_native_events[i].msr=msr_pp0_energy_status;
844 
845  sprintf(rapl_native_events[k].name,
846  "PP0_ENERGY:PACKAGE%d",j);
847  strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
848  sprintf(rapl_native_events[k].description,
849  "Energy used by all cores in package %d",j);
850  rapl_native_events[k].fd_offset=cpu_to_use[j];
851  rapl_native_events[k].msr=msr_pp0_energy_status;
855 
856  i++;
857  k++;
858  }
859  }
860 
861  /* Export the total number of events available */
863 
866 
867 
868  /* Export the component id */
870 
871  return PAPI_OK;
872 }
873 
874 
875 /*
876  * Control of counters (Reading/Writing/Starting/Stopping/Setup)
877  * functions
878  */
879 static int
881 {
882 
884  int i;
885 
886  for(i=0;i<RAPL_MAX_COUNTERS;i++) {
887  control->being_measured[i]=0;
888  }
889 
890  return PAPI_OK;
891 }
892 
893 static int
895 {
896  _rapl_context_t* context = (_rapl_context_t*) ctx;
898  long long now = PAPI_get_real_usec();
899  int i;
900 
901  for( i = 0; i < RAPL_MAX_COUNTERS; i++ ) {
902  if ((control->being_measured[i]) && (control->need_difference[i])) {
903  context->start_value[i]=read_rapl_value(i);
904  }
905  }
906 
907  control->lastupdate = now;
908 
909  return PAPI_OK;
910 }
911 
912 static int
914 {
915 
916  /* read values */
917  _rapl_context_t* context = (_rapl_context_t*) ctx;
919  long long now = PAPI_get_real_usec();
920  int i;
921  long long temp;
922 
923  for ( i = 0; i < RAPL_MAX_COUNTERS; i++ ) {
924  if (control->being_measured[i]) {
925  temp = read_rapl_value(i);
926  if (context->start_value[i])
927  if (control->need_difference[i]) {
928  /* test for wrap around */
929  if (temp < context->start_value[i] ) {
930  SUBDBG("Wraparound!\nstart:\t%#016x\ttemp:\t%#016x",
931  (unsigned)context->start_value[i], (unsigned)temp);
932  temp += (0x100000000 - context->start_value[i]);
933  SUBDBG("\tresult:\t%#016x\n", (unsigned)temp);
934  } else {
935  temp -= context->start_value[i];
936  }
937  }
938  control->count[i] = convert_rapl_energy( i, temp );
939  }
940  }
941  control->lastupdate = now;
942  return PAPI_OK;
943 }
944 
945 /* Shutdown a thread */
946 static int
948 {
949  ( void ) ctx;
950  return PAPI_OK;
951 }
952 
953 int
955  long long **events, int flags)
956 {
957  (void) flags;
958 
959  _rapl_stop( ctx, ctl );
960 
961  /* Pass back a pointer to our results */
962  *events = ((_rapl_control_state_t*) ctl)->count;
963 
964  return PAPI_OK;
965 }
966 
967 
968 /*
969  * Clean up what was setup in rapl_init_component().
970  */
971 static int
973 {
974  int i;
975 
977  if (fd_array) {
978  for(i=0;i<num_cpus;i++) {
979  if (fd_array[i].open) close(fd_array[i].fd);
980  }
982  }
983 
984  return PAPI_OK;
985 }
986 
987 
988 /* This function sets various options in the component
989  * The valid codes being passed in are PAPI_SET_DEFDOM,
990  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
991  */
992 static int
993 _rapl_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option )
994 {
995  ( void ) ctx;
996  ( void ) code;
997  ( void ) option;
998 
999  return PAPI_OK;
1000 }
1001 
1002 
1003 static int
1005  NativeInfo_t *native, int count,
1006  hwd_context_t *ctx )
1007 {
1008  int i, index;
1009  ( void ) ctx;
1010 
1011  _rapl_control_state_t* control = (_rapl_control_state_t*) ctl;
1012 
1013  /* Ugh, what is this native[] stuff all about ?*/
1014  /* Mostly remap stuff in papi_internal */
1015 
1016  for(i=0;i<RAPL_MAX_COUNTERS;i++) {
1017  control->being_measured[i]=0;
1018  }
1019 
1020  for( i = 0; i < count; i++ ) {
1021  index=native[i].ni_event&PAPI_NATIVE_AND_MASK;
1022  native[i].ni_position=rapl_native_events[index].resources.selector - 1;
1023  control->being_measured[index]=1;
1024 
1025  /* Only need to subtract if it's a PACKAGE_ENERGY or ENERGY_CNT type */
1026  control->need_difference[index]=
1031  }
1032 
1033  return PAPI_OK;
1034 }
1035 
1036 
1037 /*
1038  * This function has to set the bits needed to count different domains
1039  * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
1040  * By default return PAPI_EINVAL if none of those are specified
1041  * and PAPI_OK with success
1042  * PAPI_DOM_USER is only user context is counted
1043  * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
1044  * PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses)
1045  * PAPI_DOM_ALL is all of the domains
1046  */
1047 static int
1049 {
1050  ( void ) ctl;
1051 
1052  /* In theory we only support system-wide mode */
1053  /* How to best handle that? */
1054  if ( PAPI_DOM_ALL != domain )
1055  return PAPI_EINVAL;
1056 
1057  return PAPI_OK;
1058 }
1059 
1060 
1061 static int
1063 {
1064  ( void ) ctx;
1065  ( void ) ctl;
1066 
1067  return PAPI_OK;
1068 }
1069 
1070 
1071 /*
1072  * Native Event functions
1073  */
1074 static int
1075 _rapl_ntv_enum_events( unsigned int *EventCode, int modifier )
1076 {
1077 
1078  int index;
1079 
1080  switch ( modifier ) {
1081 
1082  case PAPI_ENUM_FIRST:
1083 
1084  if (num_events==0) {
1085  return PAPI_ENOEVNT;
1086  }
1087  *EventCode = 0;
1088 
1089  return PAPI_OK;
1090 
1091 
1092  case PAPI_ENUM_EVENTS:
1093 
1094  index = *EventCode & PAPI_NATIVE_AND_MASK;
1095 
1096  if ( index < num_events - 1 ) {
1097  *EventCode = *EventCode + 1;
1098  return PAPI_OK;
1099  } else {
1100  return PAPI_ENOEVNT;
1101  }
1102  break;
1103 
1104  default:
1105  return PAPI_EINVAL;
1106  }
1107 
1108  return PAPI_EINVAL;
1109 }
1110 
1111 /*
1112  *
1113  */
1114 static int
1115 _rapl_ntv_code_to_name( unsigned int EventCode, char *name, int len )
1116 {
1117 
1118  int index = EventCode & PAPI_NATIVE_AND_MASK;
1119 
1120  if ( index >= 0 && index < num_events ) {
1121  strncpy( name, rapl_native_events[index].name, len );
1122  return PAPI_OK;
1123  }
1124 
1125  return PAPI_ENOEVNT;
1126 }
1127 
1128 /*
1129  *
1130  */
1131 static int
1132 _rapl_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
1133 {
1134  int index = EventCode;
1135 
1136  if ( index >= 0 && index < num_events ) {
1137  strncpy( name, rapl_native_events[index].description, len );
1138  return PAPI_OK;
1139  }
1140  return PAPI_ENOEVNT;
1141 }
1142 
1143 static int
1144 _rapl_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
1145 {
1146 
1147  int index = EventCode;
1148 
1149  if ( ( index < 0) || (index >= num_events )) return PAPI_ENOEVNT;
1150 
1151  strncpy( info->symbol, rapl_native_events[index].name, sizeof(info->symbol)-1);
1152  info->symbol[sizeof(info->symbol)-1] = '\0';
1153 
1154  strncpy( info->long_descr, rapl_native_events[index].description, sizeof(info->long_descr)-1);
1155  info->long_descr[sizeof(info->long_descr)-1] = '\0';
1156 
1157  strncpy( info->units, rapl_native_events[index].units, sizeof(info->units)-1);
1158  info->units[sizeof(info->units)-1] = '\0';
1159 
1160  info->data_type = rapl_native_events[index].return_type;
1161 
1162  return PAPI_OK;
1163 }
1164 
1165 
1166 
1168  .cmp_info = { /* (unspecified values are initialized to 0) */
1169  .name = "rapl",
1170  .short_name = "rapl",
1171  .description = "Linux RAPL energy measurements",
1172  .version = "5.3.0",
1173  .default_domain = PAPI_DOM_ALL,
1174  .default_granularity = PAPI_GRN_SYS,
1175  .available_granularities = PAPI_GRN_SYS,
1176  .hardware_intr_sig = PAPI_INT_SIGNAL,
1177  .available_domains = PAPI_DOM_ALL,
1178  },
1179 
1180  /* sizes of framework-opaque component-private structures */
1181  .size = {
1182  .context = sizeof ( _rapl_context_t ),
1183  .control_state = sizeof ( _rapl_control_state_t ),
1184  .reg_value = sizeof ( _rapl_register_t ),
1185  .reg_alloc = sizeof ( _rapl_reg_alloc_t ),
1186  },
1187  /* function pointers in this component */
1188  .init_thread = _rapl_init_thread,
1189  .init_component = _rapl_init_component,
1190  .init_control_state = _rapl_init_control_state,
1191  .start = _rapl_start,
1192  .stop = _rapl_stop,
1193  .read = _rapl_read,
1194  .shutdown_thread = _rapl_shutdown_thread,
1195  .shutdown_component = _rapl_shutdown_component,
1196  .ctl = _rapl_ctl,
1197 
1198  .update_control_state = _rapl_update_control_state,
1199  .set_domain = _rapl_set_domain,
1200  .reset = _rapl_reset,
1201 
1202  .ntv_enum_events = _rapl_ntv_enum_events,
1203  .ntv_code_to_name = _rapl_ntv_code_to_name,
1204  .ntv_code_to_descr = _rapl_ntv_code_to_descr,
1205  .ntv_code_to_info = _rapl_ntv_code_to_info,
1206 };
unsigned int msr_rapl_power_unit
Definition: linux-rapl.c:154
#define PAPI_OK
Definition: fpapi.h:105
char disabled_reason[PAPI_MAX_STR_LEN]
Definition: papi.h:637
#define TIME_UNIT_MASK
Definition: linux-rapl.c:89
int errno
#define PACKAGE_MAXIMUM
Definition: linux-rapl.c:159
int close(int fd)
Definition: appio.c:175
static long long convert_rapl_energy(int index, long long value)
Definition: linux-rapl.c:220
#define PAPI_ENOMEM
Definition: fpapi.h:107
static const char * name
Definition: fork_overflow.c:31
_rapl_control_state_t state
Definition: linux-rapl.c:136
#define POWER_INFO_UNIT_MASK
Definition: linux-rapl.c:92
char name[PAPI_MAX_STR_LEN]
Definition: linux-rapl.c:106
#define MSR_INTEL_RAPL_POWER_UNIT
Definition: linux-rapl.c:53
static int num_events
Definition: linux-rapl.c:148
#define PLATFORM_ENERGY
Definition: linux-rapl.c:167
#define PAPI_EINVAL
Definition: fpapi.h:106
Hardware info structure.
Definition: papi.h:781
char units[PAPI_MIN_STR_LEN]
Definition: papi.h:976
#define papi_free(a)
Definition: papi_memory.h:35
#define PAPI_ENOSUPP
Definition: fpapi.h:123
#define PACKAGE_MAXIMUM_CNT
Definition: linux-rapl.c:164
#define PACKAGE_THERMAL
Definition: linux-rapl.c:157
off64_t offset
Definition: iozone.c:1279
static int _rapl_set_domain(hwd_control_state_t *ctl, int domain)
Definition: linux-rapl.c:1048
int _rapl_read(hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags)
Definition: linux-rapl.c:954
int fd
Definition: iozone.c:1291
char units[PAPI_MIN_STR_LEN]
Definition: linux-rapl.c:107
static int get_kernel_nr_cpus(void)
Definition: linux-rapl.c:285
static int num_packages
Definition: linux-rapl.c:150
static long long read_msr(int fd, unsigned int which)
Definition: linux-rapl.c:174
#define PAPI_GRN_SYS
Definition: fpapi.h:71
#define ENERGY_UNIT_OFFSET
Definition: linux-rapl.c:85
char long_descr[PAPI_HUGE_STR_LEN]
Definition: papi.h:970
char filename[MAXNAMESIZE]
Definition: iozone.c:1360
int type
Definition: linux-rapl.c:111
#define PACKAGE_ENERGY_CNT
Definition: linux-rapl.c:161
#define DRAM_ENERGY
Definition: linux-rapl.c:166
char units[MAX_EVENTS][BUFSIZ]
Definition: powercap_plot.c:15
int power_divisor
Definition: linux-rapl.c:152
#define PACKAGE_TIME_WINDOW_CNT
Definition: linux-rapl.c:165
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
#define MSR_PP1_ENERGY_STATUS
Definition: linux-rapl.c:69
static FILE * fp
#define PAPI_ENOIMPL
Definition: fpapi.h:124
#define RAPL_MAX_COUNTERS
Definition: linux-rapl.c:122
#define MSR_INTEL_PP0_ENERGY_STATUS
Definition: linux-rapl.c:63
Return codes and api definitions.
static int _rapl_update_control_state(hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx)
Definition: linux-rapl.c:1004
FILE * fff[MAX_EVENTS]
char events[MAX_EVENTS][BUFSIZ]
#define PACKAGE_ENERGY
Definition: linux-rapl.c:156
struct fd_array_t * fd_array
Definition: linux-rapl.c:149
#define PAPI_ESYS
Definition: fpapi.h:108
static int _rapl_shutdown_thread(hwd_context_t *ctx)
Definition: linux-rapl.c:947
static int cidx
papi_vector_t _rapl_vector
Definition: linux-rapl.c:140
static int _rapl_shutdown_component(void)
Definition: linux-rapl.c:972
int open(const char *pathname, int flags, mode_t mode)
Definition: appio.c:184
#define PACKAGE_MINIMUM_CNT
Definition: linux-rapl.c:163
static long long read_rapl_value(int index)
Definition: linux-rapl.c:211
unsigned int selector
Definition: linux-rapl.c:101
static int _rapl_init_component(int cidx)
Definition: linux-rapl.c:321
static _rapl_native_event_entry_t * rapl_native_events
Definition: linux-rapl.c:147
static int open_fd(int offset)
Definition: linux-rapl.c:187
char description[PAPI_MAX_STR_LEN]
Definition: linux-rapl.c:108
#define PACKAGE_MINIMUM
Definition: linux-rapl.c:158
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:967
#define PAPI_MIN_STR_LEN
Definition: fpapi.h:41
int cpu_energy_divisor
Definition: linux-rapl.c:153
static int native
int cpuid_model
Definition: papi.h:794
#define SUBDBG(format, args...)
Definition: papi_debug.h:63
#define PACKAGE_THERMAL_CNT
Definition: linux-rapl.c:162
static int _rapl_reset(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-rapl.c:1062
#define ENERGY_UNIT_MASK
Definition: linux-rapl.c:86
#define POWER_UNIT_MASK
Definition: linux-rapl.c:83
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:630
#define MSR_AMD_RAPL_POWER_UNIT
Definition: linux-rapl.c:36
#define PAPI_INT_SIGNAL
Definition: papi_internal.h:53
static int _rapl_init_thread(hwd_context_t *ctx)
Definition: linux-rapl.c:308
int dram_energy_divisor
Definition: linux-rapl.c:153
static int _rapl_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
Definition: linux-rapl.c:993
int cpuid_family
Definition: papi.h:793
#define MSR_AMD_PP0_ENERGY_STATUS
Definition: linux-rapl.c:39
papi_mdi_t _papi_hwi_system_info
Definition: papi_internal.c:56
_rapl_register_t ra_bits
Definition: linux-rapl.c:118
PAPI_hw_info_t hw_info
#define MSR_PLATFORM_ENERGY_STATUS
Definition: linux-rapl.c:79
Definition: linux-rapl.c:104
static int _rapl_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
Definition: linux-rapl.c:1144
#define MAXIMUM_TIME_WINDOW_SHIFT
Definition: linux-rapl.c:96
#define PAPI_VENDOR_INTEL
Definition: papi.h:349
static int num_cpus
Definition: linux-rapl.c:150
int vendor
Definition: papi.h:788
static int _rapl_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-rapl.c:913
#define THERMAL_SHIFT
Definition: linux-rapl.c:93
long long PAPI_get_real_usec(void)
Definition: papi.c:6264
int time_divisor
Definition: linux-rapl.c:152
_rapl_register_t resources
Definition: linux-rapl.c:113
long long count[RAPL_MAX_COUNTERS]
Definition: linux-rapl.c:127
int being_measured[RAPL_MAX_COUNTERS]
Definition: linux-rapl.c:126
int return_type
Definition: linux-rapl.c:112
#define PAPI_ENOEVNT
Definition: fpapi.h:112
int fd_offset
Definition: linux-rapl.c:109
#define PAPI_NATIVE_AND_MASK
static int _rapl_ntv_code_to_descr(unsigned int EventCode, char *name, int len)
Definition: linux-rapl.c:1132
#define MAXIMUM_POWER_SHIFT
Definition: linux-rapl.c:95
#define MINIMUM_POWER_SHIFT
Definition: linux-rapl.c:94
#define TIME_UNIT_OFFSET
Definition: linux-rapl.c:88
static int _rapl_init_control_state(hwd_control_state_t *ctl)
Definition: linux-rapl.c:880
int msr
Definition: linux-rapl.c:110
static int _rapl_ntv_code_to_name(unsigned int EventCode, char *name, int len)
Definition: linux-rapl.c:1115
#define MSR_DRAM_ENERGY_STATUS
Definition: linux-rapl.c:74
int need_difference[RAPL_MAX_COUNTERS]
Definition: linux-rapl.c:128
#define PACKAGE_TIME_WINDOW
Definition: linux-rapl.c:160
#define MSR_INTEL_PKG_ENERGY_STATUS
Definition: linux-rapl.c:57
static const PAPI_hw_info_t * hw_info
Definition: byte_profile.c:28
static int _rapl_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-rapl.c:894
void exit()
#define PAPI_DOM_ALL
Definition: fpapi.h:25
#define POWER_UNIT_OFFSET
Definition: linux-rapl.c:82
static long count
#define MSR_PKG_POWER_INFO
Definition: linux-rapl.c:59
#define papi_calloc(a, b)
Definition: papi_memory.h:37
#define PAPI_VENDOR_AMD
Definition: papi.h:350
int i
Definition: fileop.c:140
#define MSR_AMD_PKG_ENERGY_STATUS
Definition: linux-rapl.c:38
long long start_value[RAPL_MAX_COUNTERS]
Definition: linux-rapl.c:135
#define PAPI_MAX_STR_LEN
Definition: fpapi.h:43
static int _rapl_ntv_enum_events(unsigned int *EventCode, int modifier)
Definition: linux-rapl.c:1075