PAPI  5.4.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  ( void ) cntl;
358 
359  if ( PAPI_DOM_ALL != domain )
360  return PAPI_EINVAL;
361 
362  return PAPI_OK;
363 }
364 
365 
366  int
368 {
369  ( void ) ctx;
370  ( void ) ctl;
371 
372  return PAPI_OK;
373 }
374 
375 
376 /*
377  * Native Event functions
378  */
379  int
380 _micpower_ntv_enum_events( unsigned int *EventCode, int modifier )
381 {
382 
383  int index;
384 
385  switch ( modifier ) {
386 
387  case PAPI_ENUM_FIRST:
388 
389  if (num_events==0) {
390  return PAPI_ENOEVNT;
391  }
392  *EventCode = 0;
393 
394  return PAPI_OK;
395 
396 
397  case PAPI_ENUM_EVENTS:
398 
399  index = *EventCode&PAPI_NATIVE_AND_MASK;
400 
401  if ( index < num_events - 1 ) {
402  *EventCode = *EventCode + 1;
403  return PAPI_OK;
404  } else {
405  return PAPI_ENOEVNT;
406  }
407  break;
408 
409  default:
410  return PAPI_EINVAL;
411  }
412  return PAPI_EINVAL;
413 }
414 
415 /*
416  *
417  */
418  int
419 _micpower_ntv_code_to_name( unsigned int EventCode, char *name, int len )
420 {
421  int index = EventCode&PAPI_NATIVE_AND_MASK;
422 
423  if ( index >= 0 && index < num_events ) {
424  strncpy( name, _micpower_native_events[index].name, len );
425  return PAPI_OK;
426  }
427  return PAPI_ENOEVNT;
428 }
429 
430 /*
431  *
432  */
433  int
434 _micpower_ntv_code_to_descr( unsigned int EventCode, char *name, int len )
435 {
436  int index = EventCode&PAPI_NATIVE_AND_MASK;
437 
438  if ( index >= 0 && index < num_events ) {
439  strncpy( name, _micpower_native_events[index].description, len );
440  return PAPI_OK;
441  }
442  return PAPI_ENOEVNT;
443 }
444 
445  int
446 _micpower_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info)
447 {
448 
449  int index = EventCode&PAPI_NATIVE_AND_MASK;
450 
451  if ( ( index < 0) || (index >= num_events )) return PAPI_ENOEVNT;
452 
453  strncpy( info->symbol, _micpower_native_events[index].name,
454  sizeof(info->symbol));
455 
456  strncpy( info->long_descr, _micpower_native_events[index].description,
457  sizeof(info->long_descr));
458 
459  strncpy( info->units, _micpower_native_events[index].units,
460  sizeof(info->units));
461 
462 
463  return PAPI_OK;
464 }
465 
466 
467 
468 /*
469  *
470  */
471 papi_vector_t _micpower_vector = {
472  .cmp_info = {
473  /* default component information (unspecified values are initialized to 0) */
474  .name = "micpower",
475  .short_name = "micpower",
476  .description = "Component for reading power on Intel Xeon Phi (MIC)",
477  .version = "5.1",
478  .num_mpx_cntrs = MICPOWER_NUMBER_OF_NATIVE_EVENTS,
480  .default_domain = PAPI_DOM_ALL,
481  .available_domains = PAPI_DOM_ALL,
482  .default_granularity = PAPI_GRN_SYS,
483  .available_granularities = PAPI_GRN_SYS,
484  .hardware_intr_sig = PAPI_INT_SIGNAL,
485 
486  /* component specific cmp_info initializations */
487  .fast_real_timer = 0,
488  .fast_virtual_timer = 0,
489  .attach = 0,
490  .attach_must_ptrace = 0,
491  }
492  ,
493 
494  /* sizes of framework-opaque component-private structures */
495  .size = {
496  .context = sizeof ( MICPOWER_context_t ),
497  .control_state = sizeof ( MICPOWER_control_state_t ),
498  .reg_value = sizeof ( MICPOWER_register_t ),
499  .reg_alloc = sizeof ( MICPOWER_reg_alloc_t ),
500  }
501  ,
502  /* function pointers in this component */
503  .init_thread = _micpower_init_thread,
504  .init_component = _micpower_init_component,
505  .init_control_state = _micpower_init_control_state,
506  .start = _micpower_start,
507  .stop = _micpower_stop,
508  .read = _micpower_read,
509  .shutdown_thread = _micpower_shutdown_thread,
510  .shutdown_component = _micpower_shutdown_component,
511  .ctl = _micpower_ctl,
512 
513  .update_control_state = _micpower_update_control_state,
514  .set_domain = _micpower_set_domain,
515  .reset = _micpower_reset,
516 
517  .ntv_enum_events = _micpower_ntv_enum_events,
518  .ntv_code_to_name = _micpower_ntv_code_to_name,
519  .ntv_code_to_descr = _micpower_ntv_code_to_descr,
520  .ntv_code_to_info = _micpower_ntv_code_to_info,
521 };
char name[PAPI_MAX_STR_LEN]
Definition: papi.h:626
#define PAPI_ENOEVNT
Definition: papi.h:258
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)
static int num_events
char long_descr[PAPI_HUGE_STR_LEN]
Definition: papi.h:966
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:963
#define PAPI_DOM_ALL
Definition: papi.h:301
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
fclose(thread_wqfd)
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)
char events[MAX_EVENTS][BUFSIZ]
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:633
int i
Definition: fileop.c:140
int _micpower_shutdown_component()
long long counts[MICPOWER_MAX_COUNTERS]
static int cidx
Definition: event_info.c:40
int _micpower_shutdown_thread(hwd_context_t *ctx)
#define PAPI_ESYS
Definition: papi.h:253
static int native
Definition: event_info.c:39
static FILE * fp
char units[PAPI_MIN_STR_LEN]
#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)
static MICPOWER_native_event_entry_t _micpower_native_events[]
#define PAPI_ENOCMP
Definition: papi.h:268
unsigned int selector
long long PAPI_get_real_usec(void)
Definition: papi.c:6190
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_MAX_STR_LEN
Definition: papi.h:463
#define PAPI_GRN_SYS
Definition: papi.h:364
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:972
char * ptr
Definition: iozone.c:23586