PAPI  5.3.0.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 if SandyBridge */
326 
327  if (hw_info->cpuid_family==6) {
328  if (hw_info->cpuid_model==42) {
329  /* SandyBridge */
330  package_avail=1;
331  pp0_avail=1;
332  pp1_avail=1;
333  dram_avail=0;
334  }
335  else if (hw_info->cpuid_model==45) {
336  /* SandyBridge-EP */
337  package_avail=1;
338  pp0_avail=1;
339  pp1_avail=0;
340  dram_avail=1;
341  }
342  else if (hw_info->cpuid_model==58) {
343  /* IvyBridge */
344  package_avail=1;
345  pp0_avail=1;
346  pp1_avail=1;
347  dram_avail=0;
348  }
349  else if (hw_info->cpuid_model==62) {
350  /* IvyBridge-EP */
351  package_avail=1;
352  pp0_avail=1;
353  pp1_avail=0;
354  dram_avail=1;
355  }
356  else if (hw_info->cpuid_model==60 || hw_info->cpuid_model==69 || hw_info->cpuid_model==70 ) {
357  /* Haswell */
358  package_avail=1;
359  pp0_avail=1;
360  pp1_avail=1;dram_avail=0;
361  }
362  else {
363  /* not a supported model */
364  strncpy(_rapl_vector.cmp_info.disabled_reason,
365  "CPU model not supported",
367  return PAPI_ENOIMPL;
368  }
369  }
370  else {
371  /* Not a family 6 machine */
372  strncpy(_rapl_vector.cmp_info.disabled_reason,
373  "CPU family not supported",PAPI_MAX_STR_LEN);
374  return PAPI_ENOIMPL;
375  }
376 
377 
378  /* Detect how many packages */
379  j=0;
380  while(1) {
381  int num_read;
382 
383  sprintf(filename,
384  "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",j);
385  fff=fopen(filename,"r");
386  if (fff==NULL) break;
387  num_read=fscanf(fff,"%d",&package);
388  fclose(fff);
389  if (num_read!=1) {
390  fprintf(stderr,"error reading %s\n",filename);
391  }
392 
393  /* Check if a new package */
394  if (package < nr_cpus) {
395  if (packages[package] == -1) {
396  SUBDBG("Found package %d out of total %d\n",package,num_packages);
397  packages[package]=package;
398  cpu_to_use[package]=j;
399  num_packages++;
400  }
401  } else {
402  SUBDBG("Package outside of allowed range\n");
403  strncpy(_rapl_vector.cmp_info.disabled_reason,
404  "Package outside of allowed range",PAPI_MAX_STR_LEN);
405  return PAPI_ESYS;
406  }
407 
408  j++;
409  }
410  num_cpus=j;
411 
412  if (num_packages==0) {
413  SUBDBG("Can't access /dev/cpu/*/msr\n");
414  strncpy(_rapl_vector.cmp_info.disabled_reason,
415  "Can't access /dev/cpu/*/msr",PAPI_MAX_STR_LEN);
416  return PAPI_ESYS;
417  }
418 
419  SUBDBG("Found %d packages with %d cpus\n",num_packages,num_cpus);
420 
421  /* Init fd_array */
422 
423  fd_array=papi_calloc(sizeof(struct fd_array_t),num_cpus);
424  if (fd_array==NULL) return PAPI_ENOMEM;
425 
426  fd=open_fd(cpu_to_use[0]);
427  if (fd<0) {
428  sprintf(_rapl_vector.cmp_info.disabled_reason,
429  "Can't open fd for cpu0: %s",strerror(errno));
430  return PAPI_ESYS;
431  }
432 
433  /* Calculate the units used */
434  result=read_msr(fd,MSR_RAPL_POWER_UNIT);
435 
436  /* units are 0.5^UNIT_VALUE */
437  /* which is the same as 1/(2^UNIT_VALUE) */
438 
442 
443  SUBDBG("Power units = %.3fW\n",1.0/power_divisor);
444  SUBDBG("Energy units = %.8fJ\n",1.0/energy_divisor);
445  SUBDBG("Time units = %.8fs\n",1.0/time_divisor);
446 
447  /* Allocate space for events */
448  /* Include room for both counts and scaled values */
449 
450  num_events= ((package_avail*num_packages) +
451  (pp0_avail*num_packages) +
452  (pp1_avail*num_packages) +
453  (dram_avail*num_packages) +
454  (4*num_packages)) * 2;
455 
456  rapl_native_events = (_rapl_native_event_entry_t*)
458 
459 
460  i = 0;
461  k = num_events/2;
462 
463  /* Create events for package power info */
464 
465  for(j=0;j<num_packages;j++) {
466  sprintf(rapl_native_events[i].name,
467  "THERMAL_SPEC_CNT:PACKAGE%d",j);
468  sprintf(rapl_native_events[i].description,
469  "Thermal specification in counts; package %d",j);
470  rapl_native_events[i].fd_offset=cpu_to_use[j];
471  rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
472  rapl_native_events[i].resources.selector = i + 1;
473  rapl_native_events[i].type=PACKAGE_THERMAL_CNT;
474  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
475 
476  sprintf(rapl_native_events[k].name,
477  "THERMAL_SPEC:PACKAGE%d",j);
478  strncpy(rapl_native_events[k].units,"W",PAPI_MIN_STR_LEN);
479  sprintf(rapl_native_events[k].description,
480  "Thermal specification for package %d",j);
481  rapl_native_events[k].fd_offset=cpu_to_use[j];
482  rapl_native_events[k].msr=MSR_PKG_POWER_INFO;
483  rapl_native_events[k].resources.selector = k + 1;
484  rapl_native_events[k].type=PACKAGE_THERMAL;
485  rapl_native_events[k].return_type=PAPI_DATATYPE_FP64;
486 
487  i++;
488  k++;
489  }
490 
491  for(j=0;j<num_packages;j++) {
492  sprintf(rapl_native_events[i].name,
493  "MINIMUM_POWER_CNT:PACKAGE%d",j);
494  sprintf(rapl_native_events[i].description,
495  "Minimum power in counts; package %d",j);
496  rapl_native_events[i].fd_offset=cpu_to_use[j];
497  rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
498  rapl_native_events[i].resources.selector = i + 1;
499  rapl_native_events[i].type=PACKAGE_MINIMUM_CNT;
500  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
501 
502  sprintf(rapl_native_events[k].name,
503  "MINIMUM_POWER:PACKAGE%d",j);
504  strncpy(rapl_native_events[k].units,"W",PAPI_MIN_STR_LEN);
505  sprintf(rapl_native_events[k].description,
506  "Minimum power for package %d",j);
507  rapl_native_events[k].fd_offset=cpu_to_use[j];
508  rapl_native_events[k].msr=MSR_PKG_POWER_INFO;
509  rapl_native_events[k].resources.selector = k + 1;
510  rapl_native_events[k].type=PACKAGE_MINIMUM;
511  rapl_native_events[k].return_type=PAPI_DATATYPE_FP64;
512 
513  i++;
514  k++;
515  }
516 
517  for(j=0;j<num_packages;j++) {
518  sprintf(rapl_native_events[i].name,
519  "MAXIMUM_POWER_CNT:PACKAGE%d",j);
520  sprintf(rapl_native_events[i].description,
521  "Maximum power in counts; package %d",j);
522  rapl_native_events[i].fd_offset=cpu_to_use[j];
523  rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
524  rapl_native_events[i].resources.selector = i + 1;
525  rapl_native_events[i].type=PACKAGE_MAXIMUM_CNT;
526  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
527 
528  sprintf(rapl_native_events[k].name,
529  "MAXIMUM_POWER:PACKAGE%d",j);
530  strncpy(rapl_native_events[k].units,"W",PAPI_MIN_STR_LEN);
531  sprintf(rapl_native_events[k].description,
532  "Maximum power for package %d",j);
533  rapl_native_events[k].fd_offset=cpu_to_use[j];
534  rapl_native_events[k].msr=MSR_PKG_POWER_INFO;
535  rapl_native_events[k].resources.selector = k + 1;
536  rapl_native_events[k].type=PACKAGE_MAXIMUM;
537  rapl_native_events[k].return_type=PAPI_DATATYPE_FP64;
538 
539  i++;
540  k++;
541  }
542 
543  for(j=0;j<num_packages;j++) {
544  sprintf(rapl_native_events[i].name,
545  "MAXIMUM_TIME_WINDOW_CNT:PACKAGE%d",j);
546  sprintf(rapl_native_events[i].description,
547  "Maximum time window in counts; package %d",j);
548  rapl_native_events[i].fd_offset=cpu_to_use[j];
549  rapl_native_events[i].msr=MSR_PKG_POWER_INFO;
550  rapl_native_events[i].resources.selector = i + 1;
551  rapl_native_events[i].type=PACKAGE_TIME_WINDOW_CNT;
552  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
553 
554  sprintf(rapl_native_events[k].name,
555  "MAXIMUM_TIME_WINDOW:PACKAGE%d",j);
556  strncpy(rapl_native_events[k].units,"s",PAPI_MIN_STR_LEN);
557  sprintf(rapl_native_events[k].description,
558  "Maximum time window for package %d",j);
559  rapl_native_events[k].fd_offset=cpu_to_use[j];
560  rapl_native_events[k].msr=MSR_PKG_POWER_INFO;
561  rapl_native_events[k].resources.selector = k + 1;
562  rapl_native_events[k].type=PACKAGE_TIME_WINDOW;
563  rapl_native_events[k].return_type=PAPI_DATATYPE_FP64;
564 
565  i++;
566  k++;
567  }
568 
569  /* Create Events for energy measurements */
570 
571  if (package_avail) {
572  for(j=0;j<num_packages;j++) {
573  sprintf(rapl_native_events[i].name,
574  "PACKAGE_ENERGY_CNT:PACKAGE%d",j);
575  sprintf(rapl_native_events[i].description,
576  "Energy used in counts by chip package %d",j);
577  rapl_native_events[i].fd_offset=cpu_to_use[j];
578  rapl_native_events[i].msr=MSR_PKG_ENERGY_STATUS;
579  rapl_native_events[i].resources.selector = i + 1;
580  rapl_native_events[i].type=PACKAGE_ENERGY_CNT;
581  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
582 
583  sprintf(rapl_native_events[k].name,
584  "PACKAGE_ENERGY:PACKAGE%d",j);
585  strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
586  sprintf(rapl_native_events[k].description,
587  "Energy used by chip package %d",j);
588  rapl_native_events[k].fd_offset=cpu_to_use[j];
589  rapl_native_events[k].msr=MSR_PKG_ENERGY_STATUS;
590  rapl_native_events[k].resources.selector = k + 1;
591  rapl_native_events[k].type=PACKAGE_ENERGY;
592  rapl_native_events[k].return_type=PAPI_DATATYPE_UINT64;
593 
594  i++;
595  k++;
596  }
597  }
598 
599  if (pp1_avail) {
600  for(j=0;j<num_packages;j++) {
601  sprintf(rapl_native_events[i].name,
602  "PP1_ENERGY_CNT:PACKAGE%d",j);
603  sprintf(rapl_native_events[i].description,
604  "Energy used in counts by Power Plane 1 (Often GPU) on package %d",j);
605  rapl_native_events[i].fd_offset=cpu_to_use[j];
606  rapl_native_events[i].msr=MSR_PP1_ENERGY_STATUS;
607  rapl_native_events[i].resources.selector = i + 1;
608  rapl_native_events[i].type=PACKAGE_ENERGY_CNT;
609  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
610 
611  sprintf(rapl_native_events[k].name,
612  "PP1_ENERGY:PACKAGE%d",j);
613  strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
614  sprintf(rapl_native_events[k].description,
615  "Energy used by Power Plane 1 (Often GPU) on package %d",j);
616  rapl_native_events[k].fd_offset=cpu_to_use[j];
617  rapl_native_events[k].msr=MSR_PP1_ENERGY_STATUS;
618  rapl_native_events[k].resources.selector = k + 1;
619  rapl_native_events[k].type=PACKAGE_ENERGY;
620  rapl_native_events[k].return_type=PAPI_DATATYPE_UINT64;
621 
622  i++;
623  k++;
624  }
625  }
626 
627  if (dram_avail) {
628  for(j=0;j<num_packages;j++) {
629  sprintf(rapl_native_events[i].name,
630  "DRAM_ENERGY_CNT:PACKAGE%d",j);
631  sprintf(rapl_native_events[i].description,
632  "Energy used in counts by DRAM on package %d",j);
633  rapl_native_events[i].fd_offset=cpu_to_use[j];
634  rapl_native_events[i].msr=MSR_DRAM_ENERGY_STATUS;
635  rapl_native_events[i].resources.selector = i + 1;
636  rapl_native_events[i].type=PACKAGE_ENERGY_CNT;
637  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
638 
639  sprintf(rapl_native_events[k].name,
640  "DRAM_ENERGY:PACKAGE%d",j);
641  strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
642  sprintf(rapl_native_events[k].description,
643  "Energy used by DRAM on package %d",j);
644  rapl_native_events[k].fd_offset=cpu_to_use[j];
645  rapl_native_events[k].msr=MSR_DRAM_ENERGY_STATUS;
646  rapl_native_events[k].resources.selector = k + 1;
647  rapl_native_events[k].type=PACKAGE_ENERGY;
648  rapl_native_events[k].return_type=PAPI_DATATYPE_UINT64;
649 
650  i++;
651  k++;
652  }
653  }
654 
655  if (pp0_avail) {
656  for(j=0;j<num_packages;j++) {
657  sprintf(rapl_native_events[i].name,
658  "PP0_ENERGY_CNT:PACKAGE%d",j);
659  sprintf(rapl_native_events[i].description,
660  "Energy used in counts by all cores in package %d",j);
661  rapl_native_events[i].fd_offset=cpu_to_use[j];
662  rapl_native_events[i].msr=MSR_PP0_ENERGY_STATUS;
663  rapl_native_events[i].resources.selector = i + 1;
664  rapl_native_events[i].type=PACKAGE_ENERGY_CNT;
665  rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64;
666 
667  sprintf(rapl_native_events[k].name,
668  "PP0_ENERGY:PACKAGE%d",j);
669  strncpy(rapl_native_events[k].units,"nJ",PAPI_MIN_STR_LEN);
670  sprintf(rapl_native_events[k].description,
671  "Energy used by all cores in package %d",j);
672  rapl_native_events[k].fd_offset=cpu_to_use[j];
673  rapl_native_events[k].msr=MSR_PP0_ENERGY_STATUS;
674  rapl_native_events[k].resources.selector = k + 1;
675  rapl_native_events[k].type=PACKAGE_ENERGY;
676  rapl_native_events[k].return_type=PAPI_DATATYPE_UINT64;
677 
678  i++;
679  k++;
680  }
681  }
682 
683  /* Export the total number of events available */
684  _rapl_vector.cmp_info.num_native_events = num_events;
685 
686  _rapl_vector.cmp_info.num_cntrs = num_events;
687  _rapl_vector.cmp_info.num_mpx_cntrs = num_events;
688 
689 
690  /* Export the component id */
691  _rapl_vector.cmp_info.CmpIdx = cidx;
692 
693  return PAPI_OK;
694 }
695 
696 
697 /*
698  * Control of counters (Reading/Writing/Starting/Stopping/Setup)
699  * functions
700  */
701 int
703 {
704 
706  int i;
707 
708  for(i=0;i<RAPL_MAX_COUNTERS;i++) {
709  control->being_measured[i]=0;
710  }
711 
712  return PAPI_OK;
713 }
714 
715 int
717 {
718  _rapl_context_t* context = (_rapl_context_t*) ctx;
720  long long now = PAPI_get_real_usec();
721  int i;
722 
723  for( i = 0; i < RAPL_MAX_COUNTERS; i++ ) {
724  if ((control->being_measured[i]) && (control->need_difference[i])) {
725  context->start_value[i]=read_rapl_value(i);
726  }
727  }
728 
729  control->lastupdate = now;
730 
731  return PAPI_OK;
732 }
733 
734 int
736 {
737 
738  /* read values */
739  _rapl_context_t* context = (_rapl_context_t*) ctx;
741  long long now = PAPI_get_real_usec();
742  int i;
743  long long temp;
744 
745  for ( i = 0; i < RAPL_MAX_COUNTERS; i++ ) {
746  if (control->being_measured[i]) {
747  temp = read_rapl_value(i);
748  if (context->start_value[i])
749  if (control->need_difference[i]) {
750  /* test for wrap around */
751  if (temp < context->start_value[i] ) {
752  SUBDBG("Wraparound!\nstart:\t0x%016x\ttemp:\t0x%016x",
753  (unsigned)context->start_value[i], (unsigned)temp);
754  temp += (0x100000000 - context->start_value[i]);
755  SUBDBG("\tresult:\t0x%016x\n", (unsigned)temp);
756  } else {
757  temp -= context->start_value[i];
758  }
759  }
760  control->count[i] = convert_rapl_energy( i, temp );
761  }
762  }
763  control->lastupdate = now;
764  return PAPI_OK;
765 }
766 
767 /* Shutdown a thread */
768 int
770 {
771  ( void ) ctx;
772  return PAPI_OK;
773 }
774 
775 int
777  long long **events, int flags)
778 {
779  (void) flags;
780 
781  _rapl_stop( ctx, ctl );
782 
783  /* Pass back a pointer to our results */
784  *events = ((_rapl_control_state_t*) ctl)->count;
785 
786  return PAPI_OK;
787 }
788 
789 
790 /*
791  * Clean up what was setup in rapl_init_component().
792  */
793 int
795 {
796  int i;
797 
798  if (rapl_native_events) papi_free(rapl_native_events);
799  if (fd_array) {
800  for(i=0;i<num_cpus;i++) {
801  if (fd_array[i].open) close(fd_array[i].fd);
802  }
803  papi_free(fd_array);
804  }
805 
806  return PAPI_OK;
807 }
808 
809 
810 /* This function sets various options in the component
811  * The valid codes being passed in are PAPI_SET_DEFDOM,
812  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
813  */
814 int
815 _rapl_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option )
816 {
817  ( void ) ctx;
818  ( void ) code;
819  ( void ) option;
820 
821  return PAPI_OK;
822 }
823 
824 
825 int
827  NativeInfo_t *native, int count,
828  hwd_context_t *ctx )
829 {
830  int i, index;
831  ( void ) ctx;
832 
834 
835  /* Ugh, what is this native[] stuff all about ?*/
836  /* Mostly remap stuff in papi_internal */
837 
838  for(i=0;i<RAPL_MAX_COUNTERS;i++) {
839  control->being_measured[i]=0;
840  }
841 
842  for( i = 0; i < count; i++ ) {
843  index=native[i].ni_event&PAPI_NATIVE_AND_MASK;
844  native[i].ni_position=rapl_native_events[index].resources.selector - 1;
845  control->being_measured[index]=1;
846 
847  /* Only need to subtract if it's a PACKAGE_ENERGY or ENERGY_CNT type */
848  control->need_difference[index]=
849  (rapl_native_events[index].type==PACKAGE_ENERGY
850  || rapl_native_events[index].type==PACKAGE_ENERGY_CNT);
851  }
852 
853  return PAPI_OK;
854 }
855 
856 
857 /*
858  * This function has to set the bits needed to count different domains
859  * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
860  * By default return PAPI_EINVAL if none of those are specified
861  * and PAPI_OK with success
862  * PAPI_DOM_USER is only user context is counted
863  * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
864  * PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses)
865  * PAPI_DOM_ALL is all of the domains
866  */
867 int
869 {
870  ( void ) ctl;
871  (void) domain;
872 
873  /* In theory we only support system-wide mode */
874  /* How to best handle that? */
875 
876  return PAPI_OK;
877 }
878 
879 
880 int
882 {
883  ( void ) ctx;
884  ( void ) ctl;
885 
886  return PAPI_OK;
887 }
888 
889 
890 /*
891  * Native Event functions
892  */
893 int
894 _rapl_ntv_enum_events( unsigned int *EventCode, int modifier )
895 {
896 
897  int index;
898 
899  switch ( modifier ) {
900 
901  case PAPI_ENUM_FIRST:
902 
903  if (num_events==0) {
904  return PAPI_ENOEVNT;
905  }
906  *EventCode = 0;
907 
908  return PAPI_OK;
909 
910 
911  case PAPI_ENUM_EVENTS:
912 
913  index = *EventCode & PAPI_NATIVE_AND_MASK;
914 
915  if ( index < num_events - 1 ) {
916  *EventCode = *EventCode + 1;
917  return PAPI_OK;
918  } else {
919  return PAPI_ENOEVNT;
920  }
921  break;
922 
923  default:
924  return PAPI_EINVAL;
925  }
926 
927  return PAPI_EINVAL;
928 }
929 
930 /*
931  *
932  */
933 int
934 _rapl_ntv_code_to_name( unsigned int EventCode, char *name, int len )
935 {
936 
937  int index = EventCode & PAPI_NATIVE_AND_MASK;
938 
939  if ( index >= 0 && index < num_events ) {
940  strncpy( name, rapl_native_events[index].name, len );
941  return PAPI_OK;
942  }
943 
944  return PAPI_ENOEVNT;
945 }
946 
947 /*
948  *
949  */
950 int
951 _rapl_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
952 {
953  int index = EventCode;
954 
955  if ( index >= 0 && index < num_events ) {
956  strncpy( name, rapl_native_events[index].description, len );
957  return PAPI_OK;
958  }
959  return PAPI_ENOEVNT;
960 }
961 
962 int
963 _rapl_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
964 {
965 
966  int index = EventCode;
967 
968  if ( ( index < 0) || (index >= num_events )) return PAPI_ENOEVNT;
969 
970  strncpy( info->symbol, rapl_native_events[index].name,
971  sizeof(info->symbol));
972 
973  strncpy( info->long_descr, rapl_native_events[index].description,
974  sizeof(info->symbol));
975 
976  strncpy( info->units, rapl_native_events[index].units,
977  sizeof(info->units));
978 
979  info->data_type = rapl_native_events[index].return_type;
980 
981  return PAPI_OK;
982 }
983 
984 
985 
986 papi_vector_t _rapl_vector = {
987  .cmp_info = { /* (unspecified values are initialized to 0) */
988  .name = "rapl",
989  .short_name = "rapl",
990  .description = "Linux SandyBridge RAPL energy measurements",
991  .version = "5.3.0",
992  .default_domain = PAPI_DOM_USER,
993  .default_granularity = PAPI_GRN_THR,
994  .available_granularities = PAPI_GRN_THR,
995  .hardware_intr_sig = PAPI_INT_SIGNAL,
996  .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
997  },
998 
999  /* sizes of framework-opaque component-private structures */
1000  .size = {
1001  .context = sizeof ( _rapl_context_t ),
1002  .control_state = sizeof ( _rapl_control_state_t ),
1003  .reg_value = sizeof ( _rapl_register_t ),
1004  .reg_alloc = sizeof ( _rapl_reg_alloc_t ),
1005  },
1006  /* function pointers in this component */
1007  .init_thread = _rapl_init_thread,
1008  .init_component = _rapl_init_component,
1009  .init_control_state = _rapl_init_control_state,
1010  .start = _rapl_start,
1011  .stop = _rapl_stop,
1012  .read = _rapl_read,
1013  .shutdown_thread = _rapl_shutdown_thread,
1014  .shutdown_component = _rapl_shutdown_component,
1015  .ctl = _rapl_ctl,
1016 
1017  .update_control_state = _rapl_update_control_state,
1018  .set_domain = _rapl_set_domain,
1019  .reset = _rapl_reset,
1020 
1021  .ntv_enum_events = _rapl_ntv_enum_events,
1022  .ntv_code_to_name = _rapl_ntv_code_to_name,
1023  .ntv_code_to_descr = _rapl_ntv_code_to_descr,
1024  .ntv_code_to_info = _rapl_ntv_code_to_info,
1025 };
int _rapl_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
Definition: linux-rapl.c:735
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:702
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 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:815
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:776
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:951
char filename[MAXNAMESIZE]
Definition: iozone.c:1360
int type
Definition: linux-rapl.c:94
#define PACKAGE_ENERGY_CNT
Definition: linux-rapl.c:143
fclose(thread_wqfd)
#define PAPI_DOM_KERNEL
Definition: fpapi.h:22
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:934
#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:881
int _rapl_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
Definition: linux-rapl.c:963
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:894
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:769
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:826
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:6125
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:716
#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:794
int _rapl_init_thread(hwd_context_t *ctx)
Definition: linux-rapl.c:276
#define PAPI_DOM_USER
Definition: fpapi.h:21
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 PAPI_GRN_THR
Definition: fpapi.h:67
#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:868