|
PAPI
5.3.0.0
|
00001 #include <string.h> 00002 #include <unistd.h> 00003 00004 /* Headers required by PAPI */ 00005 #include "papi.h" 00006 #include "papi_internal.h" 00007 #include "papi_vector.h" 00008 #include "papi_memory.h" 00009 00010 #include "linux-micpower.h" 00011 00012 /* Intel says 00013 ---- 00014 The power measurements can be obtained from the host as well as the MIC card 00015 over a 50msec interval. The SMC is designed to sample power consumption only 00016 every 50mSecs. 00017 ---- 00018 **/ 00019 #define REFRESH_LAT 50000 00020 00021 #define INVALID_RESULT -1000000L 00022 #define MICPOWER_NUMBER_OF_NATIVE_EVENTS 16 00023 00024 papi_vector_t _micpower_vector; 00025 00026 static MICPOWER_native_event_entry_t _micpower_native_events[] = { 00027 { .name = "tot0", 00028 .units = "uW", 00029 .description = "Total power, win 0", 00030 .resources.selector = 1 00031 }, 00032 { .name = "tot1", 00033 .units = "uW", 00034 .description = "Total power, win 1", 00035 .resources.selector = 2 00036 }, 00037 { .name = "pcie", 00038 .units = "uW", 00039 .description = "PCI-E connector power", 00040 .resources.selector = 3 00041 }, 00042 { .name = "inst", 00043 .units = "uW", 00044 .description = "Instantaneous power", 00045 .resources.selector = 4 00046 }, 00047 { .name = "imax", 00048 .units = "uW", 00049 .description = "Max Instantaneous power", 00050 .resources.selector = 5 00051 }, 00052 { .name = "c2x3", 00053 .units = "uW", 00054 .description = "2x3 connector power", 00055 .resources.selector = 6 00056 }, 00057 { .name = "c2x4", 00058 .units = "uW", 00059 .description = "2x4 connector power", 00060 .resources.selector = 7 00061 }, 00062 { .name = "vccp:pwr", 00063 .units = "uW", 00064 .description = "Core rail; Power reading", 00065 .resources.selector = 8 00066 }, 00067 { .name = "vccp:cur", 00068 .units = "uA", 00069 .description = "Core rail; Current", 00070 .resources.selector = 9 00071 }, 00072 { .name = "vccp:volt", 00073 .units = "uV", 00074 .description = "Core rail; Voltage", 00075 .resources.selector = 10 00076 }, 00077 { .name = "vddg:pwr", 00078 .units = "uW", 00079 .description = "Uncore rail; Power reading", 00080 .resources.selector = 11 00081 }, 00082 { .name = "vddg:cur", 00083 .units = "uA", 00084 .description = "Uncore rail; Current", 00085 .resources.selector = 12 00086 }, 00087 { .name = "vddg:volt", 00088 .units = "uV", 00089 .description = "Uncore rail; Voltage", 00090 .resources.selector = 13 00091 }, 00092 { .name = "vddq:pwr", 00093 .units = "uW", 00094 .description = "Memory subsystem rail; Power reading", 00095 .resources.selector = 14 00096 }, 00097 { .name = "vddq:cur", 00098 .units = "uA", 00099 .description = "Memory subsystem rail; Current", 00100 .resources.selector = 15 00101 }, 00102 { .name = "vddq:volt", 00103 .units = "uV", 00104 .description = "Memory subsystem rail; Voltage", 00105 .resources.selector = 16 00106 } 00107 }; 00108 00109 static int num_events = 0; 00110 static int is_initialized = 0; 00111 00112 /***************************************************************************/ 00113 /****** BEGIN FUNCTIONS USED INTERNALLY SPECIFIC TO THIS COMPONENT *******/ 00114 /***************************************************************************/ 00115 00116 #if 0 00117 From Intel docs, power readings are exported via sysfs at 00118 /sys/class/micras/power 00119 00120 typedeftruct mr_rsp_pws { /* Power status */ 00121 uint32_t prr; /* Current reading, in uW */ 00122 uint8_t p_val; /* Valid bits, power */ 00123 } MrRspPws; 00124 00125 typedef struct mr_rsp_vrr { /* Voltage regulator status */ 00126 uint32_t pwr; /* Power reading, in uW */ 00127 uint32_t cur; /* Current, in uA */ 00128 uint32_t volt; /* Voltage, in uV */ 00129 uint8_t p_val; /* Valid bits, power */ 00130 uint8_t c_val; /* Valid bits, current */ 00131 uint8_t v_val; /* Valid bits, voltage */ 00132 } MrRspVrr; 00133 00134 00135 I am assuming for the purposes of this component that only 00136 the readings are exported. 00137 typedef struct mr_rsp_power { 00138 MrRspPws tot0; /* Total power, win 0 */ 00139 MrRspPws tot1; /* Total power, win 1 */ 00140 MrRspPws pcie; /* PCI-E connector power */ 00141 MrRspPws inst; /* Instantaneous power */ 00142 MrRspPws imax; /* Max Instantaneous power */ 00143 MrRspPws c2x3; /* 2x3 connector power */ 00144 MrRspPws c2x4; /* 2x4 connector power */ 00145 MrRspVrr vccp; /* Core rail */ 00146 MrRspVrr vddg; /* Uncore rail */ 00147 MrRspVrr vddq; /* Memory subsystem rail */ 00148 } MrRspPower; 00149 00150 #endif 00151 static int 00152 read_sysfs_file( long long* counts) 00153 { 00154 FILE* fp = NULL; 00155 int i; 00156 int retval = 1; 00157 fp = fopen( "/sys/class/micras/power", "r" ); 00158 if (!fp) 00159 return 0; 00160 00161 for (i=0; i < MICPOWER_MAX_COUNTERS-9; i++) { 00162 retval&= fscanf(fp, "%lld", &counts[i]); 00163 } 00164 for (i=MICPOWER_MAX_COUNTERS-9; i < MICPOWER_MAX_COUNTERS; i+=3) { 00165 retval&= fscanf(fp, "%lld %lld %lld", &counts[i], &counts[i+1], &counts[i+2] ); 00166 } 00167 00168 fclose(fp); 00169 return retval; 00170 } 00171 00172 /***************************************************************************** 00173 ******************* BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS ************* 00174 *****************************************************************************/ 00175 00176 /* 00177 * This is called whenever a thread is initialized 00178 */ 00179 int 00180 _micpower_init_thread( hwd_context_t *ctx ) 00181 { 00182 ( void ) ctx; 00183 return PAPI_OK; 00184 } 00185 00186 00187 00188 /* Initialize hardware counters, setup the function vector table 00189 * and get hardware information, this routine is called when the 00190 * PAPI process is initialized (IE PAPI_library_init) 00191 */ 00192 int 00193 _micpower_init_component( int cidx ) 00194 { 00195 if ( is_initialized ) 00196 return (PAPI_OK ); 00197 00198 is_initialized = 1; 00199 00200 /* Check that /sys/class/micras/power is readable */ 00201 if ( 0 != access( "/sys/class/micras/power", R_OK ) ) { 00202 strncpy(_micpower_vector.cmp_info.disabled_reason, 00203 "Cannot read /sys/class/micras/power",PAPI_MAX_STR_LEN); 00204 return PAPI_ENOCMP; 00205 } 00206 00207 00208 /* Export the total number of events available */ 00209 num_events = 00210 _micpower_vector.cmp_info.num_native_events = MICPOWER_NUMBER_OF_NATIVE_EVENTS; 00211 00212 /* Export the component id */ 00213 _micpower_vector.cmp_info.CmpIdx = cidx; 00214 00215 return PAPI_OK; 00216 } 00217 00218 00219 00220 00221 /* 00222 * Control of counters (Reading/Writing/Starting/Stopping/Setup) 00223 * functions 00224 */ 00225 int 00226 _micpower_init_control_state( hwd_control_state_t * ctl) 00227 { 00228 int retval = 0; 00229 MICPOWER_control_state_t *micpower_ctl = (MICPOWER_control_state_t *) ctl; 00230 00231 retval = read_sysfs_file(micpower_ctl->counts); 00232 00233 /* Set last access time for caching results */ 00234 micpower_ctl->lastupdate = PAPI_get_real_usec(); 00235 00236 return (retval)?PAPI_OK:PAPI_ESYS; 00237 } 00238 00239 int 00240 _micpower_start( hwd_context_t *ctx, hwd_control_state_t *ctl) 00241 { 00242 ( void ) ctx; 00243 ( void ) ctl; 00244 00245 return PAPI_OK; 00246 } 00247 00248 int 00249 _micpower_read( hwd_context_t *ctx, hwd_control_state_t *ctl, 00250 long long ** events, int flags) 00251 { 00252 (void) flags; 00253 (void) ctx; 00254 int retval = 1; 00255 00256 MICPOWER_control_state_t* control = (MICPOWER_control_state_t*) ctl; 00257 long long now = PAPI_get_real_usec(); 00258 00259 /* Only read the values from the kernel if enough time has passed */ 00260 /* since the last read. Otherwise return cached values. */ 00261 00262 if ( now - control->lastupdate > REFRESH_LAT ) { 00263 retval = read_sysfs_file(control->counts); 00264 control->lastupdate = now; 00265 } 00266 00267 /* Pass back a pointer to our results */ 00268 *events = control->counts; 00269 00270 return (retval)?PAPI_OK:PAPI_ESYS; 00271 } 00272 00273 int 00274 _micpower_stop( hwd_context_t *ctx, hwd_control_state_t *ctl ) 00275 { 00276 (void) ctx; 00277 int retval = 1; 00278 long long now = PAPI_get_real_usec(); 00279 /* read values */ 00280 MICPOWER_control_state_t* control = (MICPOWER_control_state_t*) ctl; 00281 00282 if ( now - control->lastupdate > REFRESH_LAT ) { 00283 retval = read_sysfs_file(control->counts); 00284 control->lastupdate = now; 00285 } 00286 return (retval)?PAPI_OK:PAPI_ESYS; 00287 } 00288 00289 /* Shutdown a thread */ 00290 int 00291 _micpower_shutdown_thread( hwd_context_t * ctx ) 00292 { 00293 ( void ) ctx; 00294 return PAPI_OK; 00295 } 00296 00297 00298 /* 00299 * Clean up what was setup in micpower_init_component(). 00300 */ 00301 int 00302 _micpower_shutdown_component( ) 00303 { 00304 if ( is_initialized ) { 00305 is_initialized = 0; 00306 num_events = 0; 00307 } 00308 return PAPI_OK; 00309 } 00310 00311 00312 /* This function sets various options in the component 00313 * The valid codes being passed in are PAPI_SET_DEFDOM, 00314 * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT 00315 */ 00316 int 00317 _micpower_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option ) 00318 { 00319 ( void ) ctx; 00320 ( void ) code; 00321 ( void ) option; 00322 00323 return PAPI_OK; 00324 } 00325 00326 00327 int 00328 _micpower_update_control_state( hwd_control_state_t *ptr, 00329 NativeInfo_t * native, int count, 00330 hwd_context_t * ctx ) 00331 { 00332 int i, index; 00333 ( void ) ctx; 00334 ( void ) ptr; 00335 00336 for ( i = 0; i < count; i++ ) { 00337 index = native[i].ni_event&PAPI_NATIVE_AND_MASK; 00338 native[i].ni_position = _micpower_native_events[index].resources.selector - 1; 00339 } 00340 return PAPI_OK; 00341 } 00342 00343 00344 /* 00345 * This function has to set the bits needed to count different domains 00346 * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER 00347 * By default return PAPI_EINVAL if none of those are specified 00348 * and PAPI_OK with success 00349 * PAPI_DOM_USER is only user context is counted 00350 * PAPI_DOM_KERNEL is only the Kernel/OS context is counted 00351 * PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses) 00352 * PAPI_DOM_ALL is all of the domains 00353 */ 00354 int 00355 _micpower_set_domain( hwd_control_state_t * cntl, int domain ) 00356 { 00357 int found = 0; 00358 ( void ) cntl; 00359 00360 if ( PAPI_DOM_USER & domain ) 00361 found = 1; 00362 00363 if ( PAPI_DOM_KERNEL & domain ) 00364 found = 1; 00365 00366 if ( PAPI_DOM_OTHER & domain ) 00367 found = 1; 00368 00369 if ( !found ) 00370 return PAPI_EINVAL; 00371 00372 return PAPI_OK; 00373 } 00374 00375 00376 int 00377 _micpower_reset( hwd_context_t *ctx, hwd_control_state_t *ctl ) 00378 { 00379 ( void ) ctx; 00380 ( void ) ctl; 00381 00382 return PAPI_OK; 00383 } 00384 00385 00386 /* 00387 * Native Event functions 00388 */ 00389 int 00390 _micpower_ntv_enum_events( unsigned int *EventCode, int modifier ) 00391 { 00392 00393 int index; 00394 00395 switch ( modifier ) { 00396 00397 case PAPI_ENUM_FIRST: 00398 00399 if (num_events==0) { 00400 return PAPI_ENOEVNT; 00401 } 00402 *EventCode = 0; 00403 00404 return PAPI_OK; 00405 00406 00407 case PAPI_ENUM_EVENTS: 00408 00409 index = *EventCode&PAPI_NATIVE_AND_MASK; 00410 00411 if ( index < num_events - 1 ) { 00412 *EventCode = *EventCode + 1; 00413 return PAPI_OK; 00414 } else { 00415 return PAPI_ENOEVNT; 00416 } 00417 break; 00418 00419 default: 00420 return PAPI_EINVAL; 00421 } 00422 return PAPI_EINVAL; 00423 } 00424 00425 /* 00426 * 00427 */ 00428 int 00429 _micpower_ntv_code_to_name( unsigned int EventCode, char *name, int len ) 00430 { 00431 int index = EventCode&PAPI_NATIVE_AND_MASK; 00432 00433 if ( index >= 0 && index < num_events ) { 00434 strncpy( name, _micpower_native_events[index].name, len ); 00435 return PAPI_OK; 00436 } 00437 return PAPI_ENOEVNT; 00438 } 00439 00440 /* 00441 * 00442 */ 00443 int 00444 _micpower_ntv_code_to_descr( unsigned int EventCode, char *name, int len ) 00445 { 00446 int index = EventCode&PAPI_NATIVE_AND_MASK; 00447 00448 if ( index >= 0 && index < num_events ) { 00449 strncpy( name, _micpower_native_events[index].description, len ); 00450 return PAPI_OK; 00451 } 00452 return PAPI_ENOEVNT; 00453 } 00454 00455 int 00456 _micpower_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info) 00457 { 00458 00459 int index = EventCode&PAPI_NATIVE_AND_MASK; 00460 00461 if ( ( index < 0) || (index >= num_events )) return PAPI_ENOEVNT; 00462 00463 strncpy( info->symbol, _micpower_native_events[index].name, 00464 sizeof(info->symbol)); 00465 00466 strncpy( info->long_descr, _micpower_native_events[index].description, 00467 sizeof(info->long_descr)); 00468 00469 strncpy( info->units, _micpower_native_events[index].units, 00470 sizeof(info->units)); 00471 00472 00473 return PAPI_OK; 00474 } 00475 00476 00477 00478 /* 00479 * 00480 */ 00481 papi_vector_t _micpower_vector = { 00482 .cmp_info = { 00483 /* default component information (unspecified values are initialized to 0) */ 00484 .name = "micpower", 00485 .short_name = "micpower", 00486 .description = "Component for reading power on Intel Xeon Phi (MIC)", 00487 .version = "5.1", 00488 .num_mpx_cntrs = MICPOWER_NUMBER_OF_NATIVE_EVENTS, 00489 .num_cntrs = MICPOWER_NUMBER_OF_NATIVE_EVENTS, 00490 .default_domain = PAPI_DOM_USER, 00491 //.available_domains = PAPI_DOM_USER, 00492 .default_granularity = PAPI_GRN_THR, 00493 .available_granularities = PAPI_GRN_THR, 00494 .hardware_intr_sig = PAPI_INT_SIGNAL, 00495 00496 /* component specific cmp_info initializations */ 00497 .fast_real_timer = 0, 00498 .fast_virtual_timer = 0, 00499 .attach = 0, 00500 .attach_must_ptrace = 0, 00501 .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL, 00502 } 00503 , 00504 00505 /* sizes of framework-opaque component-private structures */ 00506 .size = { 00507 .context = sizeof ( MICPOWER_context_t ), 00508 .control_state = sizeof ( MICPOWER_control_state_t ), 00509 .reg_value = sizeof ( MICPOWER_register_t ), 00510 .reg_alloc = sizeof ( MICPOWER_reg_alloc_t ), 00511 } 00512 , 00513 /* function pointers in this component */ 00514 .init_thread = _micpower_init_thread, 00515 .init_component = _micpower_init_component, 00516 .init_control_state = _micpower_init_control_state, 00517 .start = _micpower_start, 00518 .stop = _micpower_stop, 00519 .read = _micpower_read, 00520 .shutdown_thread = _micpower_shutdown_thread, 00521 .shutdown_component = _micpower_shutdown_component, 00522 .ctl = _micpower_ctl, 00523 00524 .update_control_state = _micpower_update_control_state, 00525 .set_domain = _micpower_set_domain, 00526 .reset = _micpower_reset, 00527 00528 .ntv_enum_events = _micpower_ntv_enum_events, 00529 .ntv_code_to_name = _micpower_ntv_code_to_name, 00530 .ntv_code_to_descr = _micpower_ntv_code_to_descr, 00531 .ntv_code_to_info = _micpower_ntv_code_to_info, 00532 };