PAPI  5.3.0.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
linux-micpower.c
Go to the documentation of this file.
1 #include <string.h>
2 #include <unistd.h>
3 
4 /* Headers required by PAPI */
5 #include "papi.h"
6 #include "papi_internal.h"
7 #include "papi_vector.h"
8 #include "papi_memory.h"
9 
10 #include "linux-micpower.h"
11 
12 /* Intel says
13 ----
14 The power measurements can be obtained from the host as well as the MIC card
15 over a 50msec interval. The SMC is designed to sample power consumption only
16 every 50mSecs.
17 ----
18 **/
19 #define REFRESH_LAT 50000
20 
21 #define INVALID_RESULT -1000000L
22 #define MICPOWER_NUMBER_OF_NATIVE_EVENTS 16
23 
25 
27  { .name = "tot0",
28  .units = "uW",
29  .description = "Total power, win 0",
30  .resources.selector = 1
31  },
32  { .name = "tot1",
33  .units = "uW",
34  .description = "Total power, win 1",
35  .resources.selector = 2
36  },
37  { .name = "pcie",
38  .units = "uW",
39  .description = "PCI-E connector power",
40  .resources.selector = 3
41  },
42  { .name = "inst",
43  .units = "uW",
44  .description = "Instantaneous power",
45  .resources.selector = 4
46  },
47  { .name = "imax",
48  .units = "uW",
49  .description = "Max Instantaneous power",
50  .resources.selector = 5
51  },
52  { .name = "c2x3",
53  .units = "uW",
54  .description = "2x3 connector power",
55  .resources.selector = 6
56  },
57  { .name = "c2x4",
58  .units = "uW",
59  .description = "2x4 connector power",
60  .resources.selector = 7
61  },
62  { .name = "vccp:pwr",
63  .units = "uW",
64  .description = "Core rail; Power reading",
65  .resources.selector = 8
66  },
67  { .name = "vccp:cur",
68  .units = "uA",
69  .description = "Core rail; Current",
70  .resources.selector = 9
71  },
72  { .name = "vccp:volt",
73  .units = "uV",
74  .description = "Core rail; Voltage",
75  .resources.selector = 10
76  },
77  { .name = "vddg:pwr",
78  .units = "uW",
79  .description = "Uncore rail; Power reading",
80  .resources.selector = 11
81  },
82  { .name = "vddg:cur",
83  .units = "uA",
84  .description = "Uncore rail; Current",
85  .resources.selector = 12
86  },
87  { .name = "vddg:volt",
88  .units = "uV",
89  .description = "Uncore rail; Voltage",
90  .resources.selector = 13
91  },
92  { .name = "vddq:pwr",
93  .units = "uW",
94  .description = "Memory subsystem rail; Power reading",
95  .resources.selector = 14
96  },
97  { .name = "vddq:cur",
98  .units = "uA",
99  .description = "Memory subsystem rail; Current",
100  .resources.selector = 15
101  },
102  { .name = "vddq:volt",
103  .units = "uV",
104  .description = "Memory subsystem rail; Voltage",
105  .resources.selector = 16
106  }
107 };
108 
109 static int num_events = 0;
110 static int is_initialized = 0;
111 
112 /***************************************************************************/
113 /****** BEGIN FUNCTIONS USED INTERNALLY SPECIFIC TO THIS COMPONENT *******/
114 /***************************************************************************/
115 
116 #if 0
117 From Intel docs, power readings are exported via sysfs at
118 /sys/class/micras/power
119 
120 typedeftruct mr_rsp_pws { /* Power status */
121  uint32_t prr; /* Current reading, in uW */
122  uint8_t p_val; /* Valid bits, power */
123 } MrRspPws;
124 
125 typedef struct mr_rsp_vrr { /* Voltage regulator status */
126  uint32_t pwr; /* Power reading, in uW */
127  uint32_t cur; /* Current, in uA */
128  uint32_t volt; /* Voltage, in uV */
129  uint8_t p_val; /* Valid bits, power */
130  uint8_t c_val; /* Valid bits, current */
131  uint8_t v_val; /* Valid bits, voltage */
132 } MrRspVrr;
133 
134 
135 I am assuming for the purposes of this component that only
136 the readings are exported.
137 typedef struct mr_rsp_power {
138  MrRspPws tot0; /* Total power, win 0 */
139  MrRspPws tot1; /* Total power, win 1 */
140  MrRspPws pcie; /* PCI-E connector power */
141  MrRspPws inst; /* Instantaneous power */
142  MrRspPws imax; /* Max Instantaneous power */
143  MrRspPws c2x3; /* 2x3 connector power */
144  MrRspPws c2x4; /* 2x4 connector power */
145  MrRspVrr vccp; /* Core rail */
146  MrRspVrr vddg; /* Uncore rail */
147  MrRspVrr vddq; /* Memory subsystem rail */
148 } MrRspPower;
149 
150 #endif
151  static int
152 read_sysfs_file( long long* counts)
153 {
154  FILE* fp = NULL;
155  int i;
156  int retval = 1;
157  fp = fopen( "/sys/class/micras/power", "r" );
158  if (!fp)
159  return 0;
160 
161  for (i=0; i < MICPOWER_MAX_COUNTERS-9; i++) {
162  retval&= fscanf(fp, "%lld", &counts[i]);
163  }
164  for (i=MICPOWER_MAX_COUNTERS-9; i < MICPOWER_MAX_COUNTERS; i+=3) {
165  retval&= fscanf(fp, "%lld %lld %lld", &counts[i], &counts[i+1], &counts[i+2] );
166  }
167 
168  fclose(fp);
169  return retval;
170 }
171 
172 /*****************************************************************************
173  ******************* BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS *************
174  *****************************************************************************/
175 
176 /*
177  * This is called whenever a thread is initialized
178  */
179  int
181 {
182  ( void ) ctx;
183  return PAPI_OK;
184 }
185 
186 
187 
188 /* Initialize hardware counters, setup the function vector table
189  * and get hardware information, this routine is called when the
190  * PAPI process is initialized (IE PAPI_library_init)
191  */
192  int
194 {
195  if ( is_initialized )
196  return (PAPI_OK );
197 
198  is_initialized = 1;
199 
200  /* Check that /sys/class/micras/power is readable */
201  if ( 0 != access( "/sys/class/micras/power", R_OK ) ) {
202  strncpy(_micpower_vector.cmp_info.disabled_reason,
203  "Cannot read /sys/class/micras/power",PAPI_MAX_STR_LEN);
204  return PAPI_ENOCMP;
205  }
206 
207 
208  /* Export the total number of events available */
209  num_events =
211 
212  /* Export the component id */
213  _micpower_vector.cmp_info.CmpIdx = cidx;
214 
215  return PAPI_OK;
216 }
217 
218 
219 
220 
221 /*
222  * Control of counters (Reading/Writing/Starting/Stopping/Setup)
223  * functions
224  */
225  int
227 {
228  int retval = 0;
229  MICPOWER_control_state_t *micpower_ctl = (MICPOWER_control_state_t *) ctl;
230 
231  retval = read_sysfs_file(micpower_ctl->counts);
232 
233  /* Set last access time for caching results */
234  micpower_ctl->lastupdate = PAPI_get_real_usec();
235 
236  return (retval)?PAPI_OK:PAPI_ESYS;
237 }
238 
239  int
241 {
242  ( void ) ctx;
243  ( void ) ctl;
244 
245  return PAPI_OK;
246 }
247 
248  int
250  long long ** events, int flags)
251 {
252  (void) flags;
253  (void) ctx;
254  int retval = 1;
255 
257  long long now = PAPI_get_real_usec();
258 
259  /* Only read the values from the kernel if enough time has passed */
260  /* since the last read. Otherwise return cached values. */
261 
262  if ( now - control->lastupdate > REFRESH_LAT ) {
263  retval = read_sysfs_file(control->counts);
264  control->lastupdate = now;
265  }
266 
267  /* Pass back a pointer to our results */
268  *events = control->counts;
269 
270  return (retval)?PAPI_OK:PAPI_ESYS;
271 }
272 
273  int
275 {
276  (void) ctx;
277  int retval = 1;
278  long long now = PAPI_get_real_usec();
279  /* read values */
281 
282  if ( now - control->lastupdate > REFRESH_LAT ) {
283  retval = read_sysfs_file(control->counts);
284  control->lastupdate = now;
285  }
286  return (retval)?PAPI_OK:PAPI_ESYS;
287 }
288 
289 /* Shutdown a thread */
290  int
292 {
293  ( void ) ctx;
294  return PAPI_OK;
295 }
296 
297 
298 /*
299  * Clean up what was setup in micpower_init_component().
300  */
301  int
303 {
304  if ( is_initialized ) {
305  is_initialized = 0;
306  num_events = 0;
307  }
308  return PAPI_OK;
309 }
310 
311 
312 /* This function sets various options in the component
313  * The valid codes being passed in are PAPI_SET_DEFDOM,
314  * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT
315  */
316  int
318 {
319  ( void ) ctx;
320  ( void ) code;
321  ( void ) option;
322 
323  return PAPI_OK;
324 }
325 
326 
327  int
329  NativeInfo_t * native, int count,
330  hwd_context_t * ctx )
331 {
332  int i, index;
333  ( void ) ctx;
334  ( void ) ptr;
335 
336  for ( i = 0; i < count; i++ ) {
337  index = native[i].ni_event&PAPI_NATIVE_AND_MASK;
338  native[i].ni_position = _micpower_native_events[index].resources.selector - 1;
339  }
340  return PAPI_OK;
341 }
342 
343 
344 /*
345  * This function has to set the bits needed to count different domains
346  * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER
347  * By default return PAPI_EINVAL if none of those are specified
348  * and PAPI_OK with success
349  * PAPI_DOM_USER is only user context is counted
350  * PAPI_DOM_KERNEL is only the Kernel/OS context is counted
351  * PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses)
352  * PAPI_DOM_ALL is all of the domains
353  */
354  int
356 {
357  int found = 0;
358  ( void ) cntl;
359 
360  if ( PAPI_DOM_USER & domain )
361  found = 1;
362 
363  if ( PAPI_DOM_KERNEL & domain )
364  found = 1;
365 
366  if ( PAPI_DOM_OTHER & domain )
367  found = 1;
368 
369  if ( !found )
370  return PAPI_EINVAL;
371 
372  return PAPI_OK;
373 }
374 
375 
376  int
378 {
379  ( void ) ctx;
380  ( void ) ctl;
381 
382  return PAPI_OK;
383 }
384 
385 
386 /*
387  * Native Event functions
388  */
389  int
390 _micpower_ntv_enum_events( unsigned int *EventCode, int modifier )
391 {
392 
393  int index;
394 
395  switch ( modifier ) {
396 
397  case PAPI_ENUM_FIRST:
398 
399  if (num_events==0) {
400  return PAPI_ENOEVNT;
401  }
402  *EventCode = 0;
403 
404  return PAPI_OK;
405 
406 
407  case PAPI_ENUM_EVENTS:
408 
409  index = *EventCode&PAPI_NATIVE_AND_MASK;
410 
411  if ( index < num_events - 1 ) {
412  *EventCode = *EventCode + 1;
413  return PAPI_OK;
414  } else {
415  return PAPI_ENOEVNT;
416  }
417  break;
418 
419  default:
420  return PAPI_EINVAL;
421  }
422  return PAPI_EINVAL;
423 }
424 
425 /*
426  *
427  */
428  int
429 _micpower_ntv_code_to_name( unsigned int EventCode, char *name, int len )
430 {
431  int index = EventCode&PAPI_NATIVE_AND_MASK;
432 
433  if ( index >= 0 && index < num_events ) {
434  strncpy( name, _micpower_native_events[index].name, len );
435  return PAPI_OK;
436  }
437  return PAPI_ENOEVNT;
438 }
439 
440 /*
441  *
442  */
443  int
444 _micpower_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
445 {
446  int index = EventCode&PAPI_NATIVE_AND_MASK;
447 
448  if ( index >= 0 && index < num_events ) {
449  strncpy( name, _micpower_native_events[index].description, len );
450  return PAPI_OK;
451  }
452  return PAPI_ENOEVNT;
453 }
454 
455  int
456 _micpower_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
457 {
458 
459  int index = EventCode&PAPI_NATIVE_AND_MASK;
460 
461  if ( ( index < 0) || (index >= num_events )) return PAPI_ENOEVNT;
462 
463  strncpy( info->symbol, _micpower_native_events[index].name,
464  sizeof(info->symbol));
465 
466  strncpy( info->long_descr, _micpower_native_events[index].description,
467  sizeof(info->long_descr));
468 
469  strncpy( info->units, _micpower_native_events[index].units,
470  sizeof(info->units));
471 
472 
473  return PAPI_OK;
474 }
475 
476 
477 
478 /*
479  *
480  */
481 papi_vector_t _micpower_vector = {
482  .cmp_info = {
483  /* default component information (unspecified values are initialized to 0) */
484  .name = "micpower",
485  .short_name = "micpower",
486  .description = "Component for reading power on Intel Xeon Phi (MIC)",
487  .version = "5.1",
488  .num_mpx_cntrs = MICPOWER_NUMBER_OF_NATIVE_EVENTS,
490  .default_domain = PAPI_DOM_USER,
491  //.available_domains = PAPI_DOM_USER,
492  .default_granularity = PAPI_GRN_THR,
493  .available_granularities = PAPI_GRN_THR,
494  .hardware_intr_sig = PAPI_INT_SIGNAL,
495 
496  /* component specific cmp_info initializations */
497  .fast_real_timer = 0,
498  .fast_virtual_timer = 0,
499  .attach = 0,
500  .attach_must_ptrace = 0,
501  .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL,
502  }
503  ,
504 
505  /* sizes of framework-opaque component-private structures */
506  .size = {
507  .context = sizeof ( MICPOWER_context_t ),
508  .control_state = sizeof ( MICPOWER_control_state_t ),
509  .reg_value = sizeof ( MICPOWER_register_t ),
510  .reg_alloc = sizeof ( MICPOWER_reg_alloc_t ),
511  }
512  ,
513  /* function pointers in this component */
514  .init_thread = _micpower_init_thread,
515  .init_component = _micpower_init_component,
516  .init_control_state = _micpower_init_control_state,
517  .start = _micpower_start,
518  .stop = _micpower_stop,
519  .read = _micpower_read,
520  .shutdown_thread = _micpower_shutdown_thread,
521  .shutdown_component = _micpower_shutdown_component,
522  .ctl = _micpower_ctl,
523 
524  .update_control_state = _micpower_update_control_state,
525  .set_domain = _micpower_set_domain,
526  .reset = _micpower_reset,
527 
528  .ntv_enum_events = _micpower_ntv_enum_events,
529  .ntv_code_to_name = _micpower_ntv_code_to_name,
530  .ntv_code_to_descr = _micpower_ntv_code_to_descr,
531  .ntv_code_to_info = _micpower_ntv_code_to_info,
532 };
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:625
Mic power component This file has the source code for a component that enables PAPI-C to access hardw...
int _micpower_start(hwd_context_t *ctx, hwd_control_state_t *ctl)
char name[PAPI_MAX_STR_LEN]
static int is_initialized
long long flags
Definition: iozone.c:12330
int _micpower_reset(hwd_context_t *ctx, hwd_control_state_t *ctl)
int _micpower_init_component(int cidx)
#define PAPI_MAX_STR_LEN
Definition: fpapi.h:43
#define PAPI_ENOEVNT
Definition: fpapi.h:112
static int num_events
char long_descr[PAPI_HUGE_STR_LEN]
Definition: papi.h:964
int _micpower_ctl(hwd_context_t *ctx, int code, _papi_int_option_t *option)
papi_vector_t _micpower_vector
char symbol[PAPI_HUGE_STR_LEN]
Definition: papi.h:961
int _micpower_update_control_state(hwd_control_state_t *ptr, NativeInfo_t *native, int count, hwd_context_t *ctx)
return PAPI_OK
Definition: linux-nvml.c:458
MICPOWER_register_t resources
int count
Definition: iozone.c:22422
#define PAPI_ENOCMP
Definition: fpapi.h:122
#define PAPI_DOM_OTHER
Definition: fpapi.h:23
fclose(thread_wqfd)
#define PAPI_DOM_KERNEL
Definition: fpapi.h:22
void
Definition: iozone.c:18627
int _micpower_init_thread(hwd_context_t *ctx)
return PAPI_EINVAL
Definition: linux-nvml.c:408
PAPI_component_info_t cmp_info
Definition: papi_vector.h:20
Return codes and api definitions.
int _micpower_set_domain(hwd_control_state_t *cntl, int domain)
int _micpower_ntv_code_to_name(unsigned int EventCode, char *name, int len)
#define MICPOWER_NUMBER_OF_NATIVE_EVENTS
char disabled_reason[PAPI_MAX_STR_LEN]
Definition: papi.h:632
int i
Definition: fileop.c:140
int _micpower_shutdown_component()
long long counts[MICPOWER_MAX_COUNTERS]
long long found
Definition: libasync.c:735
static int cidx
Definition: event_info.c:40
int _micpower_shutdown_thread(hwd_context_t *ctx)
static int native
Definition: event_info.c:39
static FILE * fp
char units[PAPI_MIN_STR_LEN]
char events[MAX_EVENTS][BUFSIZ]
#define REFRESH_LAT
#define PAPI_INT_SIGNAL
Definition: papi_internal.h:53
static int read_sysfs_file(long long *counts)
int _micpower_read(hwd_context_t *ctx, hwd_control_state_t *ctl, long long **events, int flags)
#define PAPI_ESYS
Definition: fpapi.h:108
static MICPOWER_native_event_entry_t _micpower_native_events[]
unsigned int selector
long long PAPI_get_real_usec(void)
Definition: papi.c:6125
char * name
Definition: iozone.c:23648
int _micpower_init_control_state(hwd_control_state_t *ctl)
int _micpower_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
#define MICPOWER_MAX_COUNTERS
int _micpower_stop(hwd_context_t *ctx, hwd_control_state_t *ctl)
int _micpower_ntv_code_to_descr(unsigned int EventCode, char *name, int len)
#define PAPI_NATIVE_AND_MASK
char description[PAPI_MAX_STR_LEN]
#define PAPI_DOM_USER
Definition: fpapi.h:21
ssize_t retval
Definition: libasync.c:338
int _micpower_ntv_enum_events(unsigned int *EventCode, int modifier)
char units[PAPI_MIN_STR_LEN]
Definition: papi.h:970
#define PAPI_GRN_THR
Definition: fpapi.h:67
char * ptr
Definition: iozone.c:23586