PAPI  5.3.2.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
linux-rapl.c
Go to the documentation of this file.
1 
16 #include <stdio.h>
17 #include <unistd.h>
18 #include <dirent.h>
19 #include <fcntl.h>
20 #include <string.h>
21 #include <stdint.h>
22 #include <errno.h>
23 
24 /* Headers required by PAPI */
25 #include "papi.h"
26 #include "papi_internal.h"
27 #include "papi_vector.h"
28 #include "papi_memory.h"
29 
30 
31 /*
32  * Platform specific RAPL Domains.
33  * Note that PP1 RAPL Domain is supported on 062A only
34  * And DRAM RAPL Domain is supported on 062D only
35  */
36 
37 
38 /* RAPL defines */
39 #define MSR_RAPL_POWER_UNIT 0x606
40 
41 /* Package */
42 #define MSR_PKG_RAPL_POWER_LIMIT 0x610
43 #define MSR_PKG_ENERGY_STATUS 0x611
44 #define MSR_PKG_PERF_STATUS 0x613
45 #define MSR_PKG_POWER_INFO 0x614
46 
47 /* PP0 */
48 #define MSR_PP0_POWER_LIMIT 0x638
49 #define MSR_PP0_ENERGY_STATUS 0x639
50 #define MSR_PP0_POLICY 0x63A
51 #define MSR_PP0_PERF_STATUS 0x63B
52 
53 /* PP1 */
54 #define MSR_PP1_POWER_LIMIT 0x640
55 #define MSR_PP1_ENERGY_STATUS 0x641
56 #define MSR_PP1_POLICY 0x642
57 
58 /* DRAM */
59 #define MSR_DRAM_POWER_LIMIT 0x618
60 #define MSR_DRAM_ENERGY_STATUS 0x619
61 #define MSR_DRAM_PERF_STATUS 0x61B
62 #define MSR_DRAM_POWER_INFO 0x61C
63 
64 /* RAPL bitsmasks */
65 #define POWER_UNIT_OFFSET 0
66 #define POWER_UNIT_MASK 0x0f
67 
68 #define ENERGY_UNIT_OFFSET 0x08
69 #define ENERGY_UNIT_MASK 0x1f
70 
71 #define TIME_UNIT_OFFSET 0x10
72 #define TIME_UNIT_MASK 0x0f
73 
74 /* RAPL POWER UNIT MASKS */
75 #define POWER_INFO_UNIT_MASK 0x7fff
76 #define THERMAL_SHIFT 0
77 #define MINIMUM_POWER_SHIFT 16
78 #define MAXIMUM_POWER_SHIFT 32
79 #define MAXIMUM_TIME_WINDOW_SHIFT 48
80 
81 
82 typedef struct _rapl_register
83 {
84  unsigned int selector;
86 
87 typedef struct _rapl_native_event_entry
88 {
90  char units[PAPI_MIN_STR_LEN];
91  char description[PAPI_MAX_STR_LEN];
92  int fd_offset;
93  int msr;
94  int type;
98 
99 typedef struct _rapl_reg_alloc
100 {
103 
104 /* actually 32? But setting this to be safe? */
105 #define RAPL_MAX_COUNTERS 64
106 
107 typedef struct _rapl_control_state
108 {
109  int being_measured[RAPL_MAX_COUNTERS];
111  int need_difference[RAPL_MAX_COUNTERS];
112  long long lastupdate;
114 
115 
116 typedef struct _rapl_context
117 {
118  long long start_value[RAPL_MAX_COUNTERS];
121 
122 
124 
125 struct fd_array_t {
126  int fd;
127  int open;
128 };
129 
131 static int num_events = 0;
132 struct fd_array_t *fd_array=NULL;
133 static int num_packages=0,num_cpus=0;
134 
136 
137 
138 #define PACKAGE_ENERGY 0
139 #define PACKAGE_THERMAL 1
140 #define PACKAGE_MINIMUM 2
141 #define PACKAGE_MAXIMUM 3
142 #define PACKAGE_TIME_WINDOW 4
143 #define PACKAGE_ENERGY_CNT 5
144 #define PACKAGE_THERMAL_CNT 6
145 #define PACKAGE_MINIMUM_CNT 7
146 #define PACKAGE_MAXIMUM_CNT 8
147 #define PACKAGE_TIME_WINDOW_CNT 9
148 
149 
150 /***************************************************************************/
151 /****** BEGIN FUNCTIONS USED INTERNALLY SPECIFIC TO THIS COMPONENT *******/
152 /***************************************************************************/
153 
154 
155 static long long read_msr(int fd, int which) {
156 
157  uint64_t data;
158 
159  if ( fd<0 || pread(fd, &data, sizeof data, which) != sizeof data ) {
160  perror("rdmsr:pread");
161  exit(127);
162  }
163 
164  return (long long)data;
165 }
166 
167 static int open_fd(int offset) {
168 
169  int fd=-1;
170  char filename[BUFSIZ];
171 
172  if (fd_array[offset].open==0) {
173  sprintf(filename,"/dev/cpu/%d/msr",offset);
174  fd = open(filename, O_RDONLY);
175  if (fd>=0) {
176  fd_array[offset].fd=fd;
177  fd_array[offset].open=1;
178  }
179  }
180  else {
181  fd=fd_array[offset].fd;
182  }
183 
184  return fd;
185 }
186 
187 static long long read_rapl_value(int index) {
188 
189  int fd;
190 
191  fd=open_fd(rapl_native_events[index].fd_offset);
192  return read_msr(fd,rapl_native_events[index].msr);
193 
194 }
195 
196 static long long convert_rapl_energy(int index, long long value) {
197 
198  union {
199  long long ll;
200  double fp;
201  } return_val;
202 
203  return_val.ll = value; /* default case: return raw input value */
204 
205  if (rapl_native_events[index].type==PACKAGE_ENERGY) {
206  return_val.ll = (long long)(((double)value/energy_divisor)*1e9);
207  }
208 
209  if (rapl_native_events[index].type==PACKAGE_THERMAL) {
210  return_val.fp = (double)
212  (double)power_divisor;
213  }
214 
215  if (rapl_native_events[index].type==PACKAGE_MINIMUM) {
216  return_val.fp = (double)
218  (double)power_divisor;
219  }
220 
221  if (rapl_native_events[index].type==PACKAGE_MAXIMUM) {
222  return_val.fp = (double)
224  (double)power_divisor;
225  }
226 
227  if (rapl_native_events[index].type==PACKAGE_TIME_WINDOW) {
228  return_val.fp = (double)
230  (double)time_divisor;
231  }
232 
233  if (rapl_native_events[index].type==PACKAGE_THERMAL_CNT) {
234  return_val.ll = ((value>>THERMAL_SHIFT)&POWER_INFO_UNIT_MASK);
235  }
236 
237  if (rapl_native_events[index].type==PACKAGE_MINIMUM_CNT) {
238  return_val.ll = ((value>>MINIMUM_POWER_SHIFT)&POWER_INFO_UNIT_MASK);
239  }
240 
241  if (rapl_native_events[index].type==PACKAGE_MAXIMUM_CNT) {
242  return_val.ll = ((value>>MAXIMUM_POWER_SHIFT)&POWER_INFO_UNIT_MASK);
243  }
244 
245  if (rapl_native_events[index].type==PACKAGE_TIME_WINDOW_CNT) {
246  return_val.ll = ((value>>MAXIMUM_TIME_WINDOW_SHIFT)&POWER_INFO_UNIT_MASK);
247  }
248 
249  return return_val.ll;
250 }
251 
252 static int
254 {
255  FILE *fff;
256  int num_read, nr_cpus = 1;
257  fff=fopen("/sys/devices/system/cpu/kernel_max","r");
258  if (fff==NULL) return nr_cpus;
259  num_read=fscanf(fff,"%d",&nr_cpus);
260  fclose(fff);
261  if (num_read==1) {
262  nr_cpus++;
263  } else {
264  nr_cpus = 1;
265  }
266  return nr_cpus;
267 }
268 
269 /************************* PAPI Functions **********************************/
270 
271 
272 /*
273  * This is called whenever a thread is initialized
274  */
275 int
277 {
278  ( void ) ctx;
279 
280  return PAPI_OK;
281 }
282 
283 
284 
285 /*
286  * Called when PAPI process is initialized (i.e. PAPI_library_init)
287  */
288 int
290 {
291  int i,j,k,fd;
292  FILE *fff;
293  char filename[BUFSIZ];
294 
295  int package_avail, dram_avail, pp0_avail, pp1_avail;
296 
297  long long result;
298  int package;
299 
300  const PAPI_hw_info_t *hw_info;
301 
302  int nr_cpus = get_kernel_nr_cpus();
303  int packages[nr_cpus];
304  int cpu_to_use[nr_cpus];
305 
306  /* Fill with sentinel values */
307  for (i=0; i<nr_cpus; ++i) {
308  packages[i] = -1;
309  cpu_to_use[i] = -1;
310  }
311 
312 
313  /* check if Intel processor */
314  hw_info=&(_papi_hwi_system_info.hw_info);
315 
316  /* Ugh can't use PAPI_get_hardware_info() if
317  PAPI library not done initializing yet */
318 
319  if (hw_info->vendor!=PAPI_VENDOR_INTEL) {
320  strncpy(_rapl_vector.cmp_info.disabled_reason,
321  "Not an Intel processor",PAPI_MAX_STR_LEN);
322  return PAPI_ENOSUPP;
323  }
324 
325  /* check model to support */
326  if (hw_info->cpuid_family==6) {
327  if (hw_info->cpuid_model==42) {
328  /* SandyBridge */
329  package_avail=1;
330  pp0_avail=1;
331  pp1_avail=1;
332  dram_avail=0;
333  }
334  else if (hw_info->cpuid_model==45) {
335  /* SandyBridge-EP */
336  package_avail=1;
337  pp0_avail=1;
338  pp1_avail=0;
339  dram_avail=1;
340  }
341  else if (hw_info->cpuid_model==58) {
342  /* IvyBridge */
343  package_avail=1;
344  pp0_avail=1;
345  pp1_avail=1;
346  dram_avail=0;
347  }
348  else if (hw_info->cpuid_model==62) {
349  /* IvyBridge-EP */
350  package_avail=1;
351  pp0_avail=1;
352  pp1_avail=0;
353  dram_avail=1;
354  }
355  else if (hw_info->cpuid_model==60 || hw_info->cpuid_model==69 || hw_info->cpuid_model==70 ) {
356  /* Haswell */
357  package_avail=1;
358  pp0_avail=1;
359  pp1_avail=1;
360  /* Not documented by Intel but seems to work */
361  dram_avail=1;
362  }
363  else if ( hw_info->cpuid_model==63) {
364  /* Haswell-EP */
365  package_avail=1;
366  pp0_avail=1;
367  pp1_avail=0;
368  dram_avail=1;
369  }
370  else {
371  /* not a supported model */
372  strncpy(_rapl_vector.cmp_info.disabled_reason,
373  "CPU model not supported",
375  return PAPI_ENOIMPL;
376  }
377  }
378  else {
379  /* Not a family 6 machine */
380  strncpy(_rapl_vector.cmp_info.disabled_reason,
381  "CPU family not supported",PAPI_MAX_STR_LEN);
382  return PAPI_ENOIMPL;
383  }
384 
385 
386  /* Detect how many packages */
387  j=0;
388  while(1) {
389  int num_read;
390 
391  sprintf(filename,
392  "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",j);
393  fff=fopen(filename,"r");
394  if (fff==NULL) break;
395  num_read=fscanf(fff,"%d",&package);
396  fclose(fff);
397  if (num_read!=1) {
398  fprintf(stderr,"error reading %s\n",filename);
399  }
400 
401  /* Check if a new package */
402  if (package < nr_cpus) {
403  if (packages[package] == -1) {
404  SUBDBG("Found package %d out of total %d\n",package,num_packages);
405  packages[package]=package;
406  cpu_to_use[package]=j;
407  num_packages++;
408  }
409  } else {
410  SUBDBG("Package outside of allowed range\n");
411  strncpy(_rapl_vector.cmp_info.disabled_reason,
412  "Package outside of allowed range",PAPI_MAX_STR_LEN);
413  return PAPI_ESYS;
414  }
415 
416  j++;
417  }
418  num_cpus=j;
419 
420  if (num_packages==0) {
421  SUBDBG("Can't access /dev/cpu/*/msr\n");
422  strncpy(_rapl_vector.cmp_info.disabled_reason,
423  "Can't access /dev/cpu/*/msr",PAPI_MAX_STR_LEN);
424  return PAPI_ESYS;
425  }
426 
427  SUBDBG("Found %d packages with %d cpus\n",num_packages,num_cpus);
428 
429  /* Init fd_array */
430 
431  fd_array=papi_calloc(sizeof(struct fd_array_t),num_cpus);
432  if (fd_array==NULL) return PAPI_ENOMEM;
433 
434  fd=open_fd(cpu_to_use[0]);
435  if (fd<0) {
436  sprintf(_rapl_vector.cmp_info.disabled_reason,
437  "Can't open fd for cpu0: %s",strerror(errno));
438  return PAPI_ESYS;
439  }
440 
441  /* Calculate the units used */
442  result=read_msr(fd,MSR_RAPL_POWER_UNIT);
443 
444  /* units are 0.5^UNIT_VALUE */
445  /* which is the same as 1/(2^UNIT_VALUE) */
446 
450 
451  SUBDBG("Power units = %.3fW\n",1.0/power_divisor);
452  SUBDBG("Energy units = %.8fJ\n",1.0/energy_divisor);
453  SUBDBG("Time units = %.8fs\n",1.0/time_divisor);
454 
455  /* Allocate space for events */
456  /* Include room for both counts and scaled values */
457 
458  num_events= ((package_avail*num_packages) +
459  (pp0_avail*num_packages) +
460  (pp1_avail*num_packages) +
461  (dram_avail*num_packages) +
462  (4*num_packages)) * 2;
463 
464  rapl_native_events = (_rapl_native_event_entry_t*)
466 
467 
468  i = 0;
469  k = num_events/2;
470 
471  /* Create events for package power info */
472 
473  for(j=0;j<num_packages;j++) {
474  sprintf(rapl_native_events[i].name,
475  "THERMAL_SPEC_CNT:PACKAGE%d",j);
476  sprintf(rapl_native_events[i].description,
477  "Thermal specification in counts; package %d",j);
478  rapl_native_events[i].fd_offset=cpu_to_use[j];
479  rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
480  rapl_native_events[i].resources.selector = i + 1;
481  rapl_native_events[i].type=PACKAGE_THERMAL_CNT;
482  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
483 
484  sprintf(rapl_native_events[k].name,
485  "THERMAL_SPEC:PACKAGE%d",j);
486  strncpy(rapl_native_events[k].units,"W",PAPI_MIN_STR_LEN);
487  sprintf(rapl_native_events[k].description,
488  "Thermal specification for package %d",j);
489  rapl_native_events[k].fd_offset=cpu_to_use[j];
490  rapl_native_events[k].msr=MSR_PKG_POWER_INFO;
491  rapl_native_events[k].resources.selector = k + 1;
492  rapl_native_events[k].type=PACKAGE_THERMAL;
493  rapl_native_events[k].return_type=PAPI_DATATYPE_FP64;
494 
495  i++;
496  k++;
497  }
498 
499  for(j=0;j<num_packages;j++) {
500  sprintf(rapl_native_events[i].name,
501  "MINIMUM_POWER_CNT:PACKAGE%d",j);
502  sprintf(rapl_native_events[i].description,
503  "Minimum power in counts; package %d",j);
504  rapl_native_events[i].fd_offset=cpu_to_use[j];
505  rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
506  rapl_native_events[i].resources.selector = i + 1;
507  rapl_native_events[i].type=PACKAGE_MINIMUM_CNT;
508  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
509 
510  sprintf(rapl_native_events[k].name,
511  "MINIMUM_POWER:PACKAGE%d",j);
512  strncpy(rapl_native_events[k].units,"W",PAPI_MIN_STR_LEN);
513  sprintf(rapl_native_events[k].description,
514  "Minimum power for package %d",j);
515  rapl_native_events[k].fd_offset=cpu_to_use[j];
516  rapl_native_events[k].msr=MSR_PKG_POWER_INFO;
517  rapl_native_events[k].resources.selector = k + 1;
518  rapl_native_events[k].type=PACKAGE_MINIMUM;
519  rapl_native_events[k].return_type=PAPI_DATATYPE_FP64;
520 
521  i++;
522  k++;
523  }
524 
525  for(j=0;j<num_packages;j++) {
526  sprintf(rapl_native_events[i].name,
527  "MAXIMUM_POWER_CNT:PACKAGE%d",j);
528  sprintf(rapl_native_events[i].description,
529  "Maximum power in counts; package %d",j);
530  rapl_native_events[i].fd_offset=cpu_to_use[j];
531  rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
532  rapl_native_events[i].resources.selector = i + 1;
533  rapl_native_events[i].type=PACKAGE_MAXIMUM_CNT;
534  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
535 
536  sprintf(rapl_native_events[k].name,
537  "MAXIMUM_POWER:PACKAGE%d",j);
538  strncpy(rapl_native_events[k].units,"W",PAPI_MIN_STR_LEN);
539  sprintf(rapl_native_events[k].description,
540  "Maximum power for package %d",j);
541  rapl_native_events[k].fd_offset=cpu_to_use[j];
542  rapl_native_events[k].msr=MSR_PKG_POWER_INFO;
543  rapl_native_events[k].resources.selector = k + 1;
544  rapl_native_events[k].type=PACKAGE_MAXIMUM;
545  rapl_native_events[k].return_type=PAPI_DATATYPE_FP64;
546 
547  i++;
548  k++;
549  }
550 
551  for(j=0;j<num_packages;j++) {
552  sprintf(rapl_native_events[i].name,
553  "MAXIMUM_TIME_WINDOW_CNT:PACKAGE%d",j);
554  sprintf(rapl_native_events[i].description,
555  "Maximum time window in counts; package %d",j);
556  rapl_native_events[i].fd_offset=cpu_to_use[j];
557  rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
558  rapl_native_events[i].resources.selector = i + 1;
559  rapl_native_events[i].type=PACKAGE_TIME_WINDOW_CNT;
560  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
561 
562  sprintf(rapl_native_events[k].name,
563  "MAXIMUM_TIME_WINDOW:PACKAGE%d",j);
564  strncpy(rapl_native_events[k].units,"s",PAPI_MIN_STR_LEN);
565  sprintf(rapl_native_events[k].description,
566  "Maximum time window for package %d",j);
567  rapl_native_events[k].fd_offset=cpu_to_use[j];
568  rapl_native_events[k].msr=MSR_PKG_POWER_INFO;
569  rapl_native_events[k].resources.selector = k + 1;
570  rapl_native_events[k].type=PACKAGE_TIME_WINDOW;
571  rapl_native_events[k].return_type=PAPI_DATATYPE_FP64;
572 
573  i++;
574  k++;
575  }
576 
577  /* Create Events for energy measurements */
578 
579  if (package_avail) {
580  for(j=0;j<num_packages;j++) {
581  sprintf(rapl_native_events[i].name,
582  "PACKAGE_ENERGY_CNT:PACKAGE%d",j);
583  sprintf(rapl_native_events[i].description,
584  "Energy used in counts by chip package %d",j);
585  rapl_native_events[i].fd_offset=cpu_to_use[j];
586  rapl_native_events[i].msr=MSR_PKG_ENERGY_STATUS;
587  rapl_native_events[i].resources.selector = i + 1;
588  rapl_native_events[i].type=PACKAGE_ENERGY_CNT;
589  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
590 
591  sprintf(rapl_native_events[k].name,
592  "PACKAGE_ENERGY:PACKAGE%d",j);
593  strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
594  sprintf(rapl_native_events[k].description,
595  "Energy used by chip package %d",j);
596  rapl_native_events[k].fd_offset=cpu_to_use[j];
597  rapl_native_events[k].msr=MSR_PKG_ENERGY_STATUS;
598  rapl_native_events[k].resources.selector = k + 1;
599  rapl_native_events[k].type=PACKAGE_ENERGY;
600  rapl_native_events[k].return_type=PAPI_DATATYPE_UINT64;
601 
602  i++;
603  k++;
604  }
605  }
606 
607  if (pp1_avail) {
608  for(j=0;j<num_packages;j++) {
609  sprintf(rapl_native_events[i].name,
610  "PP1_ENERGY_CNT:PACKAGE%d",j);
611  sprintf(rapl_native_events[i].description,
612  "Energy used in counts by Power Plane 1 (Often GPU) on package %d",j);
613  rapl_native_events[i].fd_offset=cpu_to_use[j];
614  rapl_native_events[i].msr=MSR_PP1_ENERGY_STATUS;
615  rapl_native_events[i].resources.selector = i + 1;
616  rapl_native_events[i].type=PACKAGE_ENERGY_CNT;
617  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
618 
619  sprintf(rapl_native_events[k].name,
620  "PP1_ENERGY:PACKAGE%d",j);
621  strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
622  sprintf(rapl_native_events[k].description,
623  "Energy used by Power Plane 1 (Often GPU) on package %d",j);
624  rapl_native_events[k].fd_offset=cpu_to_use[j];
625  rapl_native_events[k].msr=MSR_PP1_ENERGY_STATUS;
626  rapl_native_events[k].resources.selector = k + 1;
627  rapl_native_events[k].type=PACKAGE_ENERGY;
628  rapl_native_events[k].return_type=PAPI_DATATYPE_UINT64;
629 
630  i++;
631  k++;
632  }
633  }
634 
635  if (dram_avail) {
636  for(j=0;j<num_packages;j++) {
637  sprintf(rapl_native_events[i].name,
638  "DRAM_ENERGY_CNT:PACKAGE%d",j);
639  sprintf(rapl_native_events[i].description,
640  "Energy used in counts by DRAM on package %d",j);
641  rapl_native_events[i].fd_offset=cpu_to_use[j];
642  rapl_native_events[i].msr=MSR_DRAM_ENERGY_STATUS;
643  rapl_native_events[i].resources.selector = i + 1;
644  rapl_native_events[i].type=PACKAGE_ENERGY_CNT;
645  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
646 
647  sprintf(rapl_native_events[k].name,
648  "DRAM_ENERGY:PACKAGE%d",j);
649  strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
650  sprintf(rapl_native_events[k].description,
651  "Energy used by DRAM on package %d",j);
652  rapl_native_events[k].fd_offset=cpu_to_use[j];
653  rapl_native_events[k].msr=MSR_DRAM_ENERGY_STATUS;
654  rapl_native_events[k].resources.selector = k + 1;
655  rapl_native_events[k].type=PACKAGE_ENERGY;
656  rapl_native_events[k].return_type=PAPI_DATATYPE_UINT64;
657 
658  i++;
659  k++;
660  }
661  }
662 
663  if (pp0_avail) {
664  for(j=0;j<num_packages;j++) {
665  sprintf(rapl_native_events[i].name,
666  "PP0_ENERGY_CNT:PACKAGE%d",j);
667  sprintf(rapl_native_events[i].description,
668  "Energy used in counts by all cores in package %d",j);
669  rapl_native_events[i].fd_offset=cpu_to_use[j];
670  rapl_native_events[i].msr=MSR_PP0_ENERGY_STATUS;
671  rapl_native_events[i].resources.selector = i + 1;
672  rapl_native_events[i].type=PACKAGE_ENERGY_CNT;
673  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
674 
675  sprintf(rapl_native_events[k].name,
676  "PP0_ENERGY:PACKAGE%d",j);
677  strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
678  sprintf(rapl_native_events[k].description,
679  "Energy used by all cores in package %d",j);
680  rapl_native_events[k].fd_offset=cpu_to_use[j];
681  rapl_native_events[k].msr=MSR_PP0_ENERGY_STATUS;
682  rapl_native_events[k].resources.selector = k + 1;
683  rapl_native_events[k].type=PACKAGE_ENERGY;
684  rapl_native_events[k].return_type=PAPI_DATATYPE_UINT64;
685 
686  i++;
687  k++;
688  }
689  }
690 
691  /* Export the total number of events available */
692  _rapl_vector.cmp_info.num_native_events = num_events;
693 
694  _rapl_vector.cmp_info.num_cntrs = num_events;
695  _rapl_vector.cmp_info.num_mpx_cntrs = num_events;
696 
697 
698  /* Export the component id */
699  _rapl_vector.cmp_info.CmpIdx = cidx;
700 
701  return PAPI_OK;
702 }
703 
704 
705 /*
706  * Control of counters (Reading/Writing/Starting/Stopping/Setup)
707  * functions
708  */
709 int
711 {
712 
714  int i;
715 
716  for(i=0;i<RAPL_MAX_COUNTERS;i++) {
717  control->being_measured[i]=0;
718  }
719 
720  return PAPI_OK;
721 }
722 
723 int
725 {
726  _rapl_context_t* context = (_rapl_context_t*) ctx;
728  long long now = PAPI_get_real_usec();
729  int i;
730 
731  for( i = 0; i < RAPL_MAX_COUNTERS; i++ ) {
732  if ((control->being_measured[i]) && (control->need_difference[i])) {
733  context->start_value[i]=read_rapl_value(i);
734  }
735  }
736 
737  control->lastupdate = now;
738 
739  return PAPI_OK;
740 }
741 
742 int
744 {
745 
746  /* read values */
747  _rapl_context_t* context = (_rapl_context_t*) ctx;
749  long long now = PAPI_get_real_usec();
750  int i;
751  long long temp;
752 
753  for ( i = 0; i < RAPL_MAX_COUNTERS; i++ ) {
754  if (control->being_measured[i]) {
755  temp = read_rapl_value(i);
756  if (context->start_value[i])
757  if (control->need_difference[i]) {
758  /* test for wrap around */
759  if (temp < context->start_value[i] ) {
760  SUBDBG("Wraparound!\nstart:\t%#016x\ttemp:\t%#016x",
761  (unsigned)context->start_value[i], (unsigned)temp);
762  temp += (0x100000000 - context->start_value[i]);
763  SUBDBG("\tresult:\t%#016x\n", (unsigned)temp);
764  } else {
765  temp -= context->start_value[i];
766  }
767  }
768  control->count[i] = convert_rapl_energy( i, temp );
769  }
770  }
771  control->lastupdate = now;
772  return PAPI_OK;
773 }
774 
775 /* Shutdown a thread */
776 int
778 {
779  ( void ) ctx;
780  return PAPI_OK;
781 }
782 
783 int
785  long long **events, int flags)
786 {
787  (void) flags;
788 
789  _rapl_stop( ctx, ctl );
790 
791  /* Pass back a pointer to our results */
792  *events = ((_rapl_control_state_t*) ctl)->count;
793 
794  return PAPI_OK;
795 }
796 
797 
798 /*
799  * Clean up what was setup in rapl_init_component().
800  */
801 int
803 {
804  int i;
805 
806  if (rapl_native_events) papi_free(rapl_native_events);
807  if (fd_array) {
808  for(i=0;i<num_cpus;i++) {
809  if (fd_array[i].open) close(fd_array[i].fd);
810  }
811  papi_free(fd_array);
812  }
813 
814  return PAPI_OK;
815 }
816 
817 
818 /* This function sets various options in the component
819  * The valid codes being passed in are PAPI_SET_DEFDOM,
820  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
821  */
822 int
823 _rapl_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option )
824 {
825  ( void ) ctx;
826  ( void ) code;
827  ( void ) option;
828 
829  return PAPI_OK;
830 }
831 
832 
833 int
835  NativeInfo_t *native, int count,
836  hwd_context_t *ctx )
837 {
838  int i, index;
839  ( void ) ctx;
840 
842 
843  /* Ugh, what is this native[] stuff all about ?*/
844  /* Mostly remap stuff in papi_internal */
845 
846  for(i=0;i<RAPL_MAX_COUNTERS;i++) {
847  control->being_measured[i]=0;
848  }
849 
850  for( i = 0; i < count; i++ ) {
851  index=native[i].ni_event&PAPI_NATIVE_AND_MASK;
852  native[i].ni_position=rapl_native_events[index].resources.selector - 1;
853  control->being_measured[index]=1;
854 
855  /* Only need to subtract if it's a PACKAGE_ENERGY or ENERGY_CNT type */
856  control->need_difference[index]=
857  (rapl_native_events[index].type==PACKAGE_ENERGY
858  || rapl_native_events[index].type==PACKAGE_ENERGY_CNT);
859  }
860 
861  return PAPI_OK;
862 }
863 
864 
865 /*
866  * This function has to set the bits needed to count different domains
867  * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
868  * By default return PAPI_EINVAL if none of those are specified
869  * and PAPI_OK with success
870  * PAPI_DOM_USER is only user context is counted
871  * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
872  * PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses)
873  * PAPI_DOM_ALL is all of the domains
874  */
875 int
877 {
878  ( void ) ctl;
879 
880  /* In theory we only support system-wide mode */
881  /* How to best handle that? */
882  if ( PAPI_DOM_ALL != domain )
883  return PAPI_EINVAL;
884 
885  return PAPI_OK;
886 }
887 
888 
889 int
891 {
892  ( void ) ctx;
893  ( void ) ctl;
894 
895  return PAPI_OK;
896 }
897 
898 
899 /*
900  * Native Event functions
901  */
902 int
903 _rapl_ntv_enum_events( unsigned int *EventCode, int modifier )
904 {
905 
906  int index;
907 
908  switch ( modifier ) {
909 
910  case PAPI_ENUM_FIRST:
911 
912  if (num_events==0) {
913  return PAPI_ENOEVNT;
914  }
915  *EventCode = 0;
916 
917  return PAPI_OK;
918 
919 
920  case PAPI_ENUM_EVENTS:
921 
922  index = *EventCode & PAPI_NATIVE_AND_MASK;
923 
924  if ( index < num_events - 1 ) {
925  *EventCode = *EventCode + 1;
926  return PAPI_OK;
927  } else {
928  return PAPI_ENOEVNT;
929  }
930  break;
931 
932  default:
933  return PAPI_EINVAL;
934  }
935 
936  return PAPI_EINVAL;
937 }
938 
939 /*
940  *
941  */
942 int
943 _rapl_ntv_code_to_name( unsigned int EventCode, char *name, int len )
944 {
945 
946  int index = EventCode & PAPI_NATIVE_AND_MASK;
947 
948  if ( index >= 0 && index < num_events ) {
949  strncpy( name, rapl_native_events[index].name, len );
950  return PAPI_OK;
951  }
952 
953  return PAPI_ENOEVNT;
954 }
955 
956 /*
957  *
958  */
959 int
960 _rapl_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
961 {
962  int index = EventCode;
963 
964  if ( index >= 0 && index < num_events ) {
965  strncpy( name, rapl_native_events[index].description, len );
966  return PAPI_OK;
967  }
968  return PAPI_ENOEVNT;
969 }
970 
971 int
972 _rapl_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
973 {
974 
975  int index = EventCode;
976 
977  if ( ( index < 0) || (index >= num_events )) return PAPI_ENOEVNT;
978 
979  strncpy( info->symbol, rapl_native_events[index].name,
980  sizeof(info->symbol));
981 
982  strncpy( info->long_descr, rapl_native_events[index].description,
983  sizeof(info->symbol));
984 
985  strncpy( info->units, rapl_native_events[index].units,
986  sizeof(info->units));
987 
988  info->data_type = rapl_native_events[index].return_type;
989 
990  return PAPI_OK;
991 }
992 
993 
994 
995 papi_vector_t _rapl_vector = {
996  .cmp_info = { /* (unspecified values are initialized to 0) */
997  .name = "rapl",
998  .short_name = "rapl",
999  .description = "Linux RAPL energy measurements",
1000  .version = "5.3.0",
1001  .default_domain = PAPI_DOM_ALL,
1002  .default_granularity = PAPI_GRN_SYS,
1003  .available_granularities = PAPI_GRN_SYS,
1004  .hardware_intr_sig = PAPI_INT_SIGNAL,
1005  .available_domains = PAPI_DOM_ALL,
1006  },
1007 
1008  /* sizes of framework-opaque component-private structures */
1009  .size = {
1010  .context = sizeof ( _rapl_context_t ),
1011  .control_state = sizeof ( _rapl_control_state_t ),
1012  .reg_value = sizeof ( _rapl_register_t ),
1013  .reg_alloc = sizeof ( _rapl_reg_alloc_t ),
1014  },
1015  /* function pointers in this component */
1016  .init_thread = _rapl_init_thread,
1017  .init_component = _rapl_init_component,
1018  .init_control_state = _rapl_init_control_state,
1019  .start = _rapl_start,
1020  .stop = _rapl_stop,
1021  .read = _rapl_read,
1022  .shutdown_thread = _rapl_shutdown_thread,
1023  .shutdown_component = _rapl_shutdown_component,
1024  .ctl = _rapl_ctl,
1025 
1026  .update_control_state = _rapl_update_control_state,
1027  .set_domain = _rapl_set_domain,
1028  .reset = _rapl_reset,
1029 
1030  .ntv_enum_events = _rapl_ntv_enum_events,
1031  .ntv_code_to_name = _rapl_ntv_code_to_name,
1032  .ntv_code_to_descr = _rapl_ntv_code_to_descr,
1033  .ntv_code_to_info = _rapl_ntv_code_to_info,
1034 };
int _rapl_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-rapl.c:743
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:625
sprintf(splash[splash_line++],"\tIozone: Performance Test of File I/O\n")
int _rapl_init_component(int cidx)
Definition: linux-rapl.c:289
#define TIME_UNIT_MASK
Definition: linux-rapl.c:72
int errno
#define PACKAGE_MAXIMUM
Definition: linux-rapl.c:141
int close(int fd)
Definition: appio.c:175
static long long convert_rapl_energy(int index, long long value)
Definition: linux-rapl.c:196
#define PAPI_ENOMEM
Definition: fpapi.h:107
_rapl_control_state_t state
Definition: linux-rapl.c:119
#define POWER_INFO_UNIT_MASK
Definition: linux-rapl.c:75
char name[PAPI_MAX_STR_LEN]
Definition: linux-rapl.c:89
#define PAPI_ENOIMPL
Definition: fpapi.h:124
Hardware info structure.
Definition: papi.h:775
int _rapl_init_control_state(hwd_control_state_t *ctl)
Definition: linux-rapl.c:710
long long flags
Definition: iozone.c:12330
static long long read_msr(int fd, int which)
Definition: linux-rapl.c:155
#define papi_free(a)
Definition: papi_memory.h:35
#define PAPI_MAX_STR_LEN
Definition: fpapi.h:43
#define PAPI_DOM_ALL
Definition: fpapi.h:25
#define PACKAGE_MAXIMUM_CNT
Definition: linux-rapl.c:146
#define PAPI_MIN_STR_LEN
Definition: fpapi.h:41
#define PACKAGE_THERMAL
Definition: linux-rapl.c:139
long which
Definition: iozone.c:19600
#define PAPI_ENOEVNT
Definition: fpapi.h:112
off64_t offset
Definition: iozone.c:1279
static int num_events
int _rapl_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
Definition: linux-rapl.c:823
char long_descr[PAPI_HUGE_STR_LEN]
Definition: papi.h:964
int _rapl_read(hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags)
Definition: linux-rapl.c:784
int fd
Definition: iozone.c:1291
char units[PAPI_MIN_STR_LEN]
Definition: linux-rapl.c:90
static int get_kernel_nr_cpus(void)
Definition: linux-rapl.c:253
static int num_packages
Definition: linux-rapl.c:133
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:961
#define ENERGY_UNIT_OFFSET
Definition: linux-rapl.c:68
return PAPI_OK
Definition: linux-nvml.c:458
int count
Definition: iozone.c:22422
int _rapl_ntv_code_to_descr(unsigned int EventCode, char *name, int len)
Definition: linux-rapl.c:960
char filename[MAXNAMESIZE]
Definition: iozone.c:1360
#define PAPI_GRN_SYS
Definition: fpapi.h:71
int type
Definition: linux-rapl.c:94
#define PACKAGE_ENERGY_CNT
Definition: linux-rapl.c:143
fclose(thread_wqfd)
void
Definition: iozone.c:18627
return PAPI_EINVAL
Definition: linux-nvml.c:408
int power_divisor
Definition: linux-rapl.c:135
#define PACKAGE_TIME_WINDOW_CNT
Definition: linux-rapl.c:147
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
#define MSR_RAPL_POWER_UNIT
Definition: linux-rapl.c:39
#define MSR_PP1_ENERGY_STATUS
Definition: linux-rapl.c:55
void double value
Definition: iozone.c:18781
static double
Definition: fileop.c:1281
int _rapl_ntv_code_to_name(unsigned int EventCode, char *name, int len)
Definition: linux-rapl.c:943
#define RAPL_MAX_COUNTERS
Definition: linux-rapl.c:105
int _rapl_reset(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-rapl.c:890
int _rapl_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
Definition: linux-rapl.c:972
Return codes and api definitions.
FILE * fff[MAX_EVENTS]
#define PACKAGE_ENERGY
Definition: linux-rapl.c:138
struct fd_array_t * fd_array
Definition: linux-rapl.c:132
char disabled_reason[PAPI_MAX_STR_LEN]
Definition: papi.h:632
papi_vector_t _rapl_vector
Definition: linux-rapl.c:123
int open(const char *pathname, int flags, mode_t mode)
Definition: appio.c:184
#define PACKAGE_MINIMUM_CNT
Definition: linux-rapl.c:145
int _rapl_ntv_enum_events(unsigned int *EventCode, int modifier)
Definition: linux-rapl.c:903
int i
Definition: fileop.c:140
static long long read_rapl_value(int index)
Definition: linux-rapl.c:187
#define PAPI_ENOSUPP
Definition: fpapi.h:123
unsigned int selector
Definition: linux-rapl.c:84
int _rapl_shutdown_thread(hwd_context_t *ctx)
Definition: linux-rapl.c:777
static _rapl_native_event_entry_t * rapl_native_events
Definition: linux-rapl.c:130
int k
Definition: iozone.c:19136
static int cidx
Definition: event_info.c:40
static int open_fd(int offset)
Definition: linux-rapl.c:167
char description[PAPI_MAX_STR_LEN]
Definition: linux-rapl.c:91
#define PACKAGE_MINIMUM
Definition: linux-rapl.c:140
#define MSR_PP0_ENERGY_STATUS
Definition: linux-rapl.c:49
static int native
Definition: event_info.c:39
int _rapl_update_control_state(hwd_control_state_t *ctl, NativeInfo_t *native, int count, hwd_context_t *ctx)
Definition: linux-rapl.c:834
int cpuid_model
Definition: papi.h:788
#define SUBDBG(format, args...)
Definition: papi_debug.h:63
long long
Definition: iozone.c:19827
#define PACKAGE_THERMAL_CNT
Definition: linux-rapl.c:144
static FILE * fp
#define ENERGY_UNIT_MASK
Definition: linux-rapl.c:69
char events[MAX_EVENTS][BUFSIZ]
#define POWER_UNIT_MASK
Definition: linux-rapl.c:66
#define PAPI_INT_SIGNAL
Definition: papi_internal.h:53
int cpuid_family
Definition: papi.h:787
#define PAPI_ESYS
Definition: fpapi.h:108
#define MSR_PKG_ENERGY_STATUS
Definition: linux-rapl.c:43
papi_mdi_t _papi_hwi_system_info
Definition: papi_internal.c:57
_rapl_register_t ra_bits
Definition: linux-rapl.c:101
PAPI_hw_info_t hw_info
Definition: linux-rapl.c:87
#define MAXIMUM_TIME_WINDOW_SHIFT
Definition: linux-rapl.c:79
#define PAPI_VENDOR_INTEL
Definition: papi.h:346
static int num_cpus
Definition: linux-rapl.c:133
int vendor
Definition: papi.h:782
#define THERMAL_SHIFT
Definition: linux-rapl.c:76
long long PAPI_get_real_usec(void)
Definition: papi.c:6138
char * name
Definition: iozone.c:23648
int time_divisor
Definition: linux-rapl.c:135
_rapl_register_t resources
Definition: linux-rapl.c:96
long long count[RAPL_MAX_COUNTERS]
Definition: linux-rapl.c:110
int being_measured[RAPL_MAX_COUNTERS]
Definition: linux-rapl.c:109
int return_type
Definition: linux-rapl.c:95
int temp
Definition: iozone.c:22158
int fd_offset
Definition: linux-rapl.c:92
#define PAPI_NATIVE_AND_MASK
int _rapl_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-rapl.c:724
#define MAXIMUM_POWER_SHIFT
Definition: linux-rapl.c:78
#define MINIMUM_POWER_SHIFT
Definition: linux-rapl.c:77
#define TIME_UNIT_OFFSET
Definition: linux-rapl.c:71
int msr
Definition: linux-rapl.c:93
int _rapl_shutdown_component(void)
Definition: linux-rapl.c:802
int _rapl_init_thread(hwd_context_t *ctx)
Definition: linux-rapl.c:276
long j
Definition: iozone.c:19135
#define MSR_DRAM_ENERGY_STATUS
Definition: linux-rapl.c:60
int need_difference[RAPL_MAX_COUNTERS]
Definition: linux-rapl.c:111
#define PACKAGE_TIME_WINDOW
Definition: linux-rapl.c:142
static const PAPI_hw_info_t * hw_info
Definition: byte_profile.c:23
void exit()
int energy_divisor
Definition: linux-rapl.c:135
#define POWER_UNIT_OFFSET
Definition: linux-rapl.c:65
char units[PAPI_MIN_STR_LEN]
Definition: papi.h:970
#define MSR_PKG_POWER_INFO
Definition: linux-rapl.c:45
#define papi_calloc(a, b)
Definition: papi_memory.h:37
long long start_value[RAPL_MAX_COUNTERS]
Definition: linux-rapl.c:118
int _rapl_set_domain(hwd_control_state_t *ctl, int domain)
Definition: linux-rapl.c:876