|
PAPI
5.1.0.2
|
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 sybsystem rail; Power reading", 00095 .resources.selector = 14 00096 }, 00097 { .name = "vddq:cur", 00098 .units = "uA", 00099 .description = "Memory sybsystem rail; Current", 00100 .resources.selector = 15 00101 }, 00102 { .name = "vddq:volt", 00103 .units = "uV", 00104 .description = "Memory sybsystem 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 00159 for (i=0; i < MICPOWER_MAX_COUNTERS-9; i++) { 00160 retval&= fscanf(fp, "%lld", &counts[i]); 00161 } 00162 for (i=MICPOWER_MAX_COUNTERS-9; i < MICPOWER_MAX_COUNTERS; i+=3) { 00163 retval&= fscanf(fp, "%lld %lld %lld", &counts[i], &counts[i+1], &counts[i+2] ); 00164 } 00165 00166 return !retval; 00167 } 00168 00169 /***************************************************************************** 00170 ******************* BEGIN PAPI's COMPONENT REQUIRED FUNCTIONS ************* 00171 *****************************************************************************/ 00172 00173 /* 00174 * This is called whenever a thread is initialized 00175 */ 00176 int 00177 _micpower_init_thread( hwd_context_t *ctx ) 00178 { 00179 ( void ) ctx; 00180 return PAPI_OK; 00181 } 00182 00183 00184 00185 /* Initialize hardware counters, setup the function vector table 00186 * and get hardware information, this routine is called when the 00187 * PAPI process is initialized (IE PAPI_library_init) 00188 */ 00189 int 00190 _micpower_init_component( int cidx ) 00191 { 00192 if ( is_initialized ) 00193 return (PAPI_OK ); 00194 00195 is_initialized = 1; 00196 00197 /* Check that /sys/class/micras/power is readable */ 00198 if ( 0 != access( "/sys/class/micras/power", R_OK ) ) { 00199 strncpy(_micpower_vector.cmp_info.disabled_reason, 00200 "Cannot read /sys/class/micras/power",PAPI_MAX_STR_LEN); 00201 return PAPI_ENOCMP; 00202 } 00203 00204 00205 /* Export the total number of events available */ 00206 num_events = 00207 _micpower_vector.cmp_info.num_native_events = MICPOWER_NUMBER_OF_NATIVE_EVENTS; 00208 00209 /* Export the component id */ 00210 _micpower_vector.cmp_info.CmpIdx = cidx; 00211 00212 return PAPI_OK; 00213 } 00214 00215 00216 00217 00218 /* 00219 * Control of counters (Reading/Writing/Starting/Stopping/Setup) 00220 * functions 00221 */ 00222 int 00223 _micpower_init_control_state( hwd_control_state_t * ctl) 00224 { 00225 int retval = 0; 00226 MICPOWER_control_state_t *micpower_ctl = (MICPOWER_control_state_t *) ctl; 00227 00228 retval = read_sysfs_file(micpower_ctl->counts); 00229 00230 /* Set last access time for caching results */ 00231 micpower_ctl->lastupdate = PAPI_get_real_usec(); 00232 00233 return (retval)?PAPI_OK:PAPI_ESYS; 00234 } 00235 00236 int 00237 _micpower_start( hwd_context_t *ctx, hwd_control_state_t *ctl) 00238 { 00239 ( void ) ctx; 00240 ( void ) ctl; 00241 00242 return PAPI_OK; 00243 } 00244 00245 int 00246 _micpower_read( hwd_context_t *ctx, hwd_control_state_t *ctl, 00247 long long ** events, int flags) 00248 { 00249 (void) flags; 00250 (void) ctx; 00251 int retval = 0; 00252 00253 MICPOWER_control_state_t* control = (MICPOWER_control_state_t*) ctl; 00254 long long now = PAPI_get_real_usec(); 00255 00256 /* Only read the values from the kernel if enough time has passed */ 00257 /* since the last read. Otherwise return cached values. */ 00258 00259 if ( now - control->lastupdate > REFRESH_LAT ) { 00260 retval = read_sysfs_file(control->counts); 00261 control->lastupdate = now; 00262 } 00263 00264 /* Pass back a pointer to our results */ 00265 *events = control->counts; 00266 00267 return (retval)?PAPI_OK:PAPI_ESYS; 00268 } 00269 00270 int 00271 _micpower_stop( hwd_context_t *ctx, hwd_control_state_t *ctl ) 00272 { 00273 (void) ctx; 00274 int retval = 0; 00275 /* read values */ 00276 MICPOWER_control_state_t* control = (MICPOWER_control_state_t*) ctl; 00277 00278 retval = read_sysfs_file(control->counts); 00279 control->lastupdate = PAPI_get_real_usec(); 00280 return (retval)?PAPI_OK:PAPI_ESYS; 00281 } 00282 00283 /* Shutdown a thread */ 00284 int 00285 _micpower_shutdown_thread( hwd_context_t * ctx ) 00286 { 00287 ( void ) ctx; 00288 return PAPI_OK; 00289 } 00290 00291 00292 /* 00293 * Clean up what was setup in micpower_init_component(). 00294 */ 00295 int 00296 _micpower_shutdown_component( ) 00297 { 00298 if ( is_initialized ) { 00299 is_initialized = 0; 00300 num_events = 0; 00301 } 00302 return PAPI_OK; 00303 } 00304 00305 00306 /* This function sets various options in the component 00307 * The valid codes being passed in are PAPI_SET_DEFDOM, 00308 * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT 00309 */ 00310 int 00311 _micpower_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option ) 00312 { 00313 ( void ) ctx; 00314 ( void ) code; 00315 ( void ) option; 00316 00317 return PAPI_OK; 00318 } 00319 00320 00321 int 00322 _micpower_update_control_state( hwd_control_state_t *ptr, 00323 NativeInfo_t * native, int count, 00324 hwd_context_t * ctx ) 00325 { 00326 int i, index; 00327 ( void ) ctx; 00328 ( void ) ptr; 00329 00330 for ( i = 0; i < count; i++ ) { 00331 index = native[i].ni_event; 00332 native[i].ni_position = _micpower_native_events[index].resources.selector - 1; 00333 } 00334 return PAPI_OK; 00335 } 00336 00337 00338 /* 00339 * This function has to set the bits needed to count different domains 00340 * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER 00341 * By default return PAPI_EINVAL if none of those are specified 00342 * and PAPI_OK with success 00343 * PAPI_DOM_USER is only user context is counted 00344 * PAPI_DOM_KERNEL is only the Kernel/OS context is counted 00345 * PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses) 00346 * PAPI_DOM_ALL is all of the domains 00347 */ 00348 int 00349 _micpower_set_domain( hwd_control_state_t * cntl, int domain ) 00350 { 00351 int found = 0; 00352 ( void ) cntl; 00353 00354 if ( PAPI_DOM_USER & domain ) 00355 found = 1; 00356 00357 if ( PAPI_DOM_KERNEL & domain ) 00358 found = 1; 00359 00360 if ( PAPI_DOM_OTHER & domain ) 00361 found = 1; 00362 00363 if ( !found ) 00364 return PAPI_EINVAL; 00365 00366 return PAPI_OK; 00367 } 00368 00369 00370 int 00371 _micpower_reset( hwd_context_t *ctx, hwd_control_state_t *ctl ) 00372 { 00373 ( void ) ctx; 00374 ( void ) ctl; 00375 00376 return PAPI_OK; 00377 } 00378 00379 00380 /* 00381 * Native Event functions 00382 */ 00383 int 00384 _micpower_ntv_enum_events( unsigned int *EventCode, int modifier ) 00385 { 00386 00387 int index; 00388 00389 switch ( modifier ) { 00390 00391 case PAPI_ENUM_FIRST: 00392 00393 if (num_events==0) { 00394 return PAPI_ENOEVNT; 00395 } 00396 *EventCode = 0; 00397 00398 return PAPI_OK; 00399 00400 00401 case PAPI_ENUM_EVENTS: 00402 00403 index = *EventCode; 00404 00405 if ( index < num_events - 1 ) { 00406 *EventCode = *EventCode + 1; 00407 return PAPI_OK; 00408 } else { 00409 return PAPI_ENOEVNT; 00410 } 00411 break; 00412 00413 default: 00414 return PAPI_EINVAL; 00415 } 00416 return PAPI_EINVAL; 00417 } 00418 00419 /* 00420 * 00421 */ 00422 int 00423 _micpower_ntv_code_to_name( unsigned int EventCode, char *name, int len ) 00424 { 00425 int index = EventCode; 00426 00427 if ( index >= 0 && index < num_events ) { 00428 strncpy( name, _micpower_native_events[index].name, len ); 00429 return PAPI_OK; 00430 } 00431 return PAPI_ENOEVNT; 00432 } 00433 00434 /* 00435 * 00436 */ 00437 int 00438 _micpower_ntv_code_to_descr( unsigned int EventCode, char *name, int len ) 00439 { 00440 int index = EventCode; 00441 00442 if ( index >= 0 && index < num_events ) { 00443 strncpy( name, _micpower_native_events[index].description, len ); 00444 return PAPI_OK; 00445 } 00446 return PAPI_ENOEVNT; 00447 } 00448 00449 int 00450 _micpower_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info) 00451 { 00452 00453 int index = EventCode; 00454 00455 if ( ( index < 0) || (index >= num_events )) return PAPI_ENOEVNT; 00456 00457 strncpy( info->symbol, _micpower_native_events[index].name, 00458 sizeof(info->symbol)); 00459 00460 strncpy( info->long_descr, _micpower_native_events[index].description, 00461 sizeof(info->long_descr)); 00462 00463 strncpy( info->units, _micpower_native_events[index].units, 00464 sizeof(info->units)); 00465 00466 00467 return PAPI_OK; 00468 } 00469 00470 00471 00472 /* 00473 * 00474 */ 00475 papi_vector_t _micpower_vector = { 00476 .cmp_info = { 00477 /* default component information (unspecified values are initialized to 0) */ 00478 .name = "mic-power", 00479 .short_name = "micpower", 00480 .description = "Component for reading power on Intel Xeon Phi (MIC)", 00481 .version = "5.1", 00482 .num_mpx_cntrs = MICPOWER_NUMBER_OF_NATIVE_EVENTS, 00483 .num_cntrs = MICPOWER_NUMBER_OF_NATIVE_EVENTS, 00484 .default_domain = PAPI_DOM_USER, 00485 //.available_domains = PAPI_DOM_USER, 00486 .default_granularity = PAPI_GRN_THR, 00487 .available_granularities = PAPI_GRN_THR, 00488 .hardware_intr_sig = PAPI_INT_SIGNAL, 00489 00490 /* component specific cmp_info initializations */ 00491 .fast_real_timer = 0, 00492 .fast_virtual_timer = 0, 00493 .attach = 0, 00494 .attach_must_ptrace = 0, 00495 .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL, 00496 } 00497 , 00498 00499 /* sizes of framework-opaque component-private structures */ 00500 .size = { 00501 .context = sizeof ( MICPOWER_context_t ), 00502 .control_state = sizeof ( MICPOWER_control_state_t ), 00503 .reg_value = sizeof ( MICPOWER_register_t ), 00504 .reg_alloc = sizeof ( MICPOWER_reg_alloc_t ), 00505 } 00506 , 00507 /* function pointers in this component */ 00508 .init_thread = _micpower_init_thread, 00509 .init_component = _micpower_init_component, 00510 .init_control_state = _micpower_init_control_state, 00511 .start = _micpower_start, 00512 .stop = _micpower_stop, 00513 .read = _micpower_read, 00514 .shutdown_thread = _micpower_shutdown_thread, 00515 .shutdown_component = _micpower_shutdown_component, 00516 .ctl = _micpower_ctl, 00517 00518 .update_control_state = _micpower_update_control_state, 00519 .set_domain = _micpower_set_domain, 00520 .reset = _micpower_reset, 00521 00522 .ntv_enum_events = _micpower_ntv_enum_events, 00523 .ntv_code_to_name = _micpower_ntv_code_to_name, 00524 .ntv_code_to_descr = _micpower_ntv_code_to_descr, 00525 .ntv_code_to_info = _micpower_ntv_code_to_info, 00526 };