|
PAPI
5.0.1.0
|
00001 00016 #include <stdio.h> 00017 #include <unistd.h> 00018 #include <dirent.h> 00019 #include <fcntl.h> 00020 #include <string.h> 00021 #include <stdint.h> 00022 00023 /* Headers required by PAPI */ 00024 #include "papi.h" 00025 #include "papi_internal.h" 00026 #include "papi_vector.h" 00027 #include "papi_memory.h" 00028 00029 00030 /* 00031 * Platform specific RAPL Domains. 00032 * Note that PP1 RAPL Domain is supported on 062A only 00033 * And DRAM RAPL Domain is supported on 062D only 00034 */ 00035 00036 00037 /* RAPL defines */ 00038 #define MSR_RAPL_POWER_UNIT 0x606 00039 00040 /* Package */ 00041 #define MSR_PKG_RAPL_POWER_LIMIT 0x610 00042 #define MSR_PKG_ENERGY_STATUS 0x611 00043 #define MSR_PKG_PERF_STATUS 0x613 00044 #define MSR_PKG_POWER_INFO 0x614 00045 00046 /* PP0 */ 00047 #define MSR_PP0_POWER_LIMIT 0x638 00048 #define MSR_PP0_ENERGY_STATUS 0x639 00049 #define MSR_PP0_POLICY 0x63A 00050 #define MSR_PP0_PERF_STATUS 0x63B 00051 00052 /* PP1 */ 00053 #define MSR_PP1_POWER_LIMIT 0x640 00054 #define MSR_PP1_ENERGY_STATUS 0x641 00055 #define MSR_PP1_POLICY 0x642 00056 00057 /* DRAM */ 00058 #define MSR_DRAM_POWER_LIMIT 0x618 00059 #define MSR_DRAM_ENERGY_STATUS 0x619 00060 #define MSR_DRAM_PERF_STATUS 0x61B 00061 #define MSR_DRAM_POWER_INFO 0x61C 00062 00063 /* RAPL bitsmasks */ 00064 #define POWER_UNIT_OFFSET 0 00065 #define POWER_UNIT_MASK 0x0f 00066 00067 #define ENERGY_UNIT_OFFSET 0x08 00068 #define ENERGY_UNIT_MASK 0x1f 00069 00070 #define TIME_UNIT_OFFSET 0x10 00071 #define TIME_UNIT_MASK 0x0f 00072 00073 /* RAPL POWER UNIT MASKS */ 00074 #define POWER_INFO_UNIT_MASK 0x7fff 00075 #define THERMAL_SHIFT 0 00076 #define MINIMUM_POWER_SHIFT 16 00077 #define MAXIMUM_POWER_SHIFT 32 00078 #define MAXIMUM_TIME_WINDOW_SHIFT 48 00079 00080 00081 typedef struct _rapl_register 00082 { 00083 unsigned int selector; 00084 } _rapl_register_t; 00085 00086 typedef struct _rapl_native_event_entry 00087 { 00088 char name[PAPI_MAX_STR_LEN]; 00089 char units[PAPI_MIN_STR_LEN]; 00090 char description[PAPI_MAX_STR_LEN]; 00091 int fd_offset; 00092 int msr; 00093 int type; 00094 int return_type; 00095 _rapl_register_t resources; 00096 } _rapl_native_event_entry_t; 00097 00098 typedef struct _rapl_reg_alloc 00099 { 00100 _rapl_register_t ra_bits; 00101 } _rapl_reg_alloc_t; 00102 00103 /* actually 32? But setting this to be safe? */ 00104 #define RAPL_MAX_COUNTERS 64 00105 00106 typedef struct _rapl_control_state 00107 { 00108 int being_measured[RAPL_MAX_COUNTERS]; 00109 long long count[RAPL_MAX_COUNTERS]; 00110 int need_difference[RAPL_MAX_COUNTERS]; 00111 long long lastupdate; 00112 } _rapl_control_state_t; 00113 00114 00115 typedef struct _rapl_context 00116 { 00117 long long start_count[RAPL_MAX_COUNTERS]; 00118 _rapl_control_state_t state; 00119 } _rapl_context_t; 00120 00121 00122 papi_vector_t _rapl_vector; 00123 00124 struct fd_array_t { 00125 int fd; 00126 int open; 00127 }; 00128 00129 static _rapl_native_event_entry_t * rapl_native_events=NULL; 00130 static int num_events = 0; 00131 struct fd_array_t *fd_array=NULL; 00132 static int num_packages=0,num_cpus=0; 00133 00134 int power_divisor,energy_divisor,time_divisor; 00135 00136 00137 #define PACKAGE_ENERGY 0 00138 #define PACKAGE_THERMAL 1 00139 #define PACKAGE_MINIMUM 2 00140 #define PACKAGE_MAXIMUM 3 00141 #define PACKAGE_TIME_WINDOW 4 00142 00143 00144 /***************************************************************************/ 00145 /****** BEGIN FUNCTIONS USED INTERNALLY SPECIFIC TO THIS COMPONENT *******/ 00146 /***************************************************************************/ 00147 00148 00149 static long long read_msr(int fd, int which) { 00150 00151 uint64_t data; 00152 00153 if ( fd<0 || pread(fd, &data, sizeof data, which) != sizeof data ) { 00154 perror("rdmsr:pread"); 00155 exit(127); 00156 } 00157 00158 return (long long)data; 00159 } 00160 00161 static int open_fd(int offset) { 00162 00163 int fd=-1; 00164 char filename[BUFSIZ]; 00165 00166 if (fd_array[offset].open==0) { 00167 sprintf(filename,"/dev/cpu/%d/msr",offset); 00168 fd = open(filename, O_RDONLY); 00169 if (fd>=0) { 00170 fd_array[offset].fd=fd; 00171 fd_array[offset].open=1; 00172 } 00173 } 00174 else { 00175 fd=fd_array[offset].fd; 00176 } 00177 00178 return fd; 00179 } 00180 00181 static long long read_rapl_energy(int index) { 00182 00183 int fd; 00184 long long result; 00185 00186 union { 00187 long long ll; 00188 double fp; 00189 } return_val; 00190 00191 fd=open_fd(rapl_native_events[index].fd_offset); 00192 result=read_msr(fd,rapl_native_events[index].msr); 00193 00194 if (rapl_native_events[index].type==PACKAGE_ENERGY) { 00195 00196 return_val.ll = (long long)(((double)result/energy_divisor)*1e9); 00197 } 00198 00199 if (rapl_native_events[index].type==PACKAGE_THERMAL) { 00200 return_val.fp = (double) 00201 ((result>>THERMAL_SHIFT)&POWER_INFO_UNIT_MASK) / 00202 (double)power_divisor; 00203 } 00204 00205 if (rapl_native_events[index].type==PACKAGE_MINIMUM) { 00206 return_val.fp = (double) 00207 ((result>>MINIMUM_POWER_SHIFT)&POWER_INFO_UNIT_MASK)/ 00208 (double)power_divisor; 00209 } 00210 00211 if (rapl_native_events[index].type==PACKAGE_MAXIMUM) { 00212 return_val.fp = (double) 00213 ((result>>MAXIMUM_POWER_SHIFT)&POWER_INFO_UNIT_MASK)/ 00214 (double)power_divisor; 00215 } 00216 00217 if (rapl_native_events[index].type==PACKAGE_TIME_WINDOW) { 00218 return_val.fp = (double) 00219 ((result>>MAXIMUM_TIME_WINDOW_SHIFT)&POWER_INFO_UNIT_MASK)/ 00220 (double)time_divisor; 00221 } 00222 00223 return return_val.ll; 00224 00225 } 00226 00227 static int 00228 get_kernel_nr_cpus() 00229 { 00230 FILE *fff; 00231 int num_read, nr_cpus = 1; 00232 fff=fopen("/sys/devices/system/cpu/kernel_max","r"); 00233 if (fff==NULL) return nr_cpus; 00234 num_read=fscanf(fff,"%d",&nr_cpus); 00235 fclose(fff); 00236 if (num_read==1) { 00237 nr_cpus++; 00238 } else { 00239 nr_cpus = 1; 00240 } 00241 return nr_cpus; 00242 } 00243 00244 /************************* PAPI Functions **********************************/ 00245 00246 00247 /* 00248 * This is called whenever a thread is initialized 00249 */ 00250 int 00251 _rapl_init_thread( hwd_context_t *ctx ) 00252 { 00253 ( void ) ctx; 00254 00255 return PAPI_OK; 00256 } 00257 00258 00259 00260 /* 00261 * Called when PAPI process is initialized (i.e. PAPI_library_init) 00262 */ 00263 int 00264 _rapl_init_component( int cidx ) 00265 { 00266 int i,j,fd; 00267 FILE *fff; 00268 char filename[BUFSIZ]; 00269 00270 int package_avail, dram_avail, pp0_avail, pp1_avail; 00271 00272 long long result; 00273 int package; 00274 00275 const PAPI_hw_info_t *hw_info; 00276 00277 int nr_cpus = get_kernel_nr_cpus(); 00278 int packages[nr_cpus]; 00279 int cpu_to_use[nr_cpus]; 00280 00281 /* Fill with sentinel values */ 00282 for (i=0; i<nr_cpus; ++i) { 00283 packages[i] = -1; 00284 cpu_to_use[i] = -1; 00285 } 00286 00287 00288 /* check if Intel processor */ 00289 hw_info=&(_papi_hwi_system_info.hw_info); 00290 00291 /* Ugh can't use PAPI_get_hardware_info() if 00292 PAPI library not done initializing yet */ 00293 00294 if (hw_info->vendor!=PAPI_VENDOR_INTEL) { 00295 strncpy(_rapl_vector.cmp_info.disabled_reason, 00296 "Not an Intel processor",PAPI_MAX_STR_LEN); 00297 return PAPI_ENOSUPP; 00298 } 00299 00300 /* check if SandyBridge */ 00301 00302 if (hw_info->cpuid_family==6) { 00303 if (hw_info->cpuid_model==42) { 00304 /* SandyBridge */ 00305 package_avail=1; 00306 pp0_avail=1; 00307 pp1_avail=1; 00308 dram_avail=0; 00309 } 00310 else if (hw_info->cpuid_model==45) { 00311 /* SandyBridge-EP */ 00312 package_avail=1; 00313 pp0_avail=1; 00314 pp1_avail=0; 00315 dram_avail=1; 00316 } 00317 else if (hw_info->cpuid_model==58) { 00318 /* IvyBridge */ 00319 package_avail=1; 00320 pp0_avail=1; 00321 pp1_avail=1; 00322 dram_avail=0; 00323 } 00324 else { 00325 /* not a supported model */ 00326 strncpy(_rapl_vector.cmp_info.disabled_reason, 00327 "Not a SandyBridge processor", 00328 PAPI_MAX_STR_LEN); 00329 return PAPI_ENOIMPL; 00330 } 00331 } 00332 else { 00333 /* Not a family 6 machine */ 00334 strncpy(_rapl_vector.cmp_info.disabled_reason, 00335 "Not a SandyBridge processor",PAPI_MAX_STR_LEN); 00336 return PAPI_ENOIMPL; 00337 } 00338 00339 00340 /* Detect how many packages */ 00341 j=0; 00342 while(1) { 00343 int num_read; 00344 00345 sprintf(filename, 00346 "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",j); 00347 fff=fopen(filename,"r"); 00348 if (fff==NULL) break; 00349 num_read=fscanf(fff,"%d",&package); 00350 fclose(fff); 00351 if (num_read!=1) { 00352 fprintf(stderr,"error reading %s\n",filename); 00353 } 00354 00355 /* Check if a new package */ 00356 if (package < nr_cpus) { 00357 if (packages[package] == -1) { 00358 SUBDBG("Found package %d out of total %d\n",package,num_packages); 00359 packages[package]=package; 00360 cpu_to_use[package]=j; 00361 num_packages++; 00362 } 00363 } else { 00364 SUBDBG("Package outside of allowed range\n"); 00365 strncpy(_rapl_vector.cmp_info.disabled_reason, 00366 "Package outside of allowed range",PAPI_MAX_STR_LEN); 00367 return PAPI_ESYS; 00368 } 00369 00370 j++; 00371 } 00372 num_cpus=j; 00373 00374 if (num_packages==0) { 00375 SUBDBG("Can't access /dev/cpu/*/msr\n"); 00376 strncpy(_rapl_vector.cmp_info.disabled_reason, 00377 "Can't access /dev/cpu/*/msr",PAPI_MAX_STR_LEN); 00378 return PAPI_ESYS; 00379 } 00380 00381 SUBDBG("Found %d packages with %d cpus\n",num_packages,num_cpus); 00382 00383 /* Init fd_array */ 00384 00385 fd_array=papi_calloc(sizeof(struct fd_array_t),num_cpus); 00386 if (fd_array==NULL) return PAPI_ENOMEM; 00387 00388 fd=open_fd(cpu_to_use[0]); 00389 if (fd<0) { 00390 strncpy(_rapl_vector.cmp_info.disabled_reason, 00391 "Can't open fd for cpu0",PAPI_MAX_STR_LEN); 00392 return PAPI_ESYS; 00393 } 00394 00395 /* Calculate the units used */ 00396 result=read_msr(fd,MSR_RAPL_POWER_UNIT); 00397 00398 /* units are 0.5^UNIT_VALUE */ 00399 /* which is the same as 1/(2^UNIT_VALUE) */ 00400 00401 power_divisor=1<<((result>>POWER_UNIT_OFFSET)&POWER_UNIT_MASK); 00402 energy_divisor=1<<((result>>ENERGY_UNIT_OFFSET)&ENERGY_UNIT_MASK); 00403 time_divisor=1<<((result>>TIME_UNIT_OFFSET)&TIME_UNIT_MASK); 00404 00405 SUBDBG("Power units = %.3fW\n",1.0/power_divisor); 00406 SUBDBG("Energy units = %.8fJ\n",1.0/energy_divisor); 00407 SUBDBG("Time units = %.8fs\n",1.0/time_divisor); 00408 00409 00410 /* Allocate space for events */ 00411 00412 num_events= (package_avail*num_packages) + 00413 (pp0_avail*num_packages) + 00414 (pp1_avail*num_packages) + 00415 (dram_avail*num_packages) + 00416 (4*num_packages); 00417 00418 rapl_native_events = (_rapl_native_event_entry_t*) 00419 papi_calloc(sizeof(_rapl_native_event_entry_t),num_events); 00420 00421 00422 i=0; 00423 00424 /* Create events for package power info */ 00425 00426 for(j=0;j<num_packages;j++) { 00427 sprintf(rapl_native_events[i].name, 00428 "THERMAL_SPEC:PACKAGE%d",j); 00429 strncpy(rapl_native_events[i].units,"W",PAPI_MIN_STR_LEN); 00430 sprintf(rapl_native_events[i].description, 00431 "Thermal specification package %d",j); 00432 rapl_native_events[i].fd_offset=cpu_to_use[j]; 00433 rapl_native_events[i].msr=MSR_PKG_POWER_INFO; 00434 rapl_native_events[i].resources.selector = i + 1; 00435 rapl_native_events[i].type=PACKAGE_THERMAL; 00436 rapl_native_events[i].return_type=PAPI_DATATYPE_FP64; 00437 i++; 00438 } 00439 00440 for(j=0;j<num_packages;j++) { 00441 sprintf(rapl_native_events[i].name, 00442 "MINIMUM_POWER:PACKAGE%d",j); 00443 strncpy(rapl_native_events[i].units,"W",PAPI_MIN_STR_LEN); 00444 sprintf(rapl_native_events[i].description, 00445 "Minimum power for package %d",j); 00446 rapl_native_events[i].fd_offset=cpu_to_use[j]; 00447 rapl_native_events[i].msr=MSR_PKG_POWER_INFO; 00448 rapl_native_events[i].resources.selector = i + 1; 00449 rapl_native_events[i].type=PACKAGE_MINIMUM; 00450 rapl_native_events[i].return_type=PAPI_DATATYPE_FP64; 00451 00452 i++; 00453 } 00454 00455 for(j=0;j<num_packages;j++) { 00456 sprintf(rapl_native_events[i].name, 00457 "MAXIMUM_POWER:PACKAGE%d",j); 00458 strncpy(rapl_native_events[i].units,"W",PAPI_MIN_STR_LEN); 00459 sprintf(rapl_native_events[i].description, 00460 "Maximum power for package %d",j); 00461 rapl_native_events[i].fd_offset=cpu_to_use[j]; 00462 rapl_native_events[i].msr=MSR_PKG_POWER_INFO; 00463 rapl_native_events[i].resources.selector = i + 1; 00464 rapl_native_events[i].type=PACKAGE_MAXIMUM; 00465 rapl_native_events[i].return_type=PAPI_DATATYPE_FP64; 00466 00467 i++; 00468 } 00469 00470 for(j=0;j<num_packages;j++) { 00471 sprintf(rapl_native_events[i].name, 00472 "MAXIMUM_TIME_WINDOW:PACKAGE%d",j); 00473 strncpy(rapl_native_events[i].units,"s",PAPI_MIN_STR_LEN); 00474 sprintf(rapl_native_events[i].description, 00475 "Maximum time window for package %d",j); 00476 rapl_native_events[i].fd_offset=cpu_to_use[j]; 00477 rapl_native_events[i].msr=MSR_PKG_POWER_INFO; 00478 rapl_native_events[i].resources.selector = i + 1; 00479 rapl_native_events[i].type=PACKAGE_TIME_WINDOW; 00480 rapl_native_events[i].return_type=PAPI_DATATYPE_FP64; 00481 00482 i++; 00483 } 00484 00485 /* Create Events for energy measurements */ 00486 00487 if (package_avail) { 00488 for(j=0;j<num_packages;j++) { 00489 sprintf(rapl_native_events[i].name, 00490 "PACKAGE_ENERGY:PACKAGE%d",j); 00491 strncpy(rapl_native_events[i].units,"nJ",PAPI_MIN_STR_LEN); 00492 sprintf(rapl_native_events[i].description, 00493 "Energy used by chip package %d",j); 00494 rapl_native_events[i].fd_offset=cpu_to_use[j]; 00495 rapl_native_events[i].msr=MSR_PKG_ENERGY_STATUS; 00496 rapl_native_events[i].resources.selector = i + 1; 00497 rapl_native_events[i].type=PACKAGE_ENERGY; 00498 rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64; 00499 00500 i++; 00501 } 00502 } 00503 00504 if (pp1_avail) { 00505 for(j=0;j<num_packages;j++) { 00506 sprintf(rapl_native_events[i].name, 00507 "PP1_ENERGY:PACKAGE%d",j); 00508 strncpy(rapl_native_events[i].units,"nJ",PAPI_MIN_STR_LEN); 00509 sprintf(rapl_native_events[i].description, 00510 "Energy used by Power Plane 1 (Often GPU) on package %d",j); 00511 rapl_native_events[i].fd_offset=cpu_to_use[j]; 00512 rapl_native_events[i].msr=MSR_PP1_ENERGY_STATUS; 00513 rapl_native_events[i].resources.selector = i + 1; 00514 rapl_native_events[i].type=PACKAGE_ENERGY; 00515 rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64; 00516 00517 i++; 00518 } 00519 } 00520 00521 if (dram_avail) { 00522 for(j=0;j<num_packages;j++) { 00523 sprintf(rapl_native_events[i].name, 00524 "DRAM_ENERGY:PACKAGE%d",j); 00525 strncpy(rapl_native_events[i].units,"nJ",PAPI_MIN_STR_LEN); 00526 sprintf(rapl_native_events[i].description, 00527 "Energy used by DRAM on package %d",j); 00528 rapl_native_events[i].fd_offset=cpu_to_use[j]; 00529 rapl_native_events[i].msr=MSR_DRAM_ENERGY_STATUS; 00530 rapl_native_events[i].resources.selector = i + 1; 00531 rapl_native_events[i].type=PACKAGE_ENERGY; 00532 rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64; 00533 00534 i++; 00535 } 00536 } 00537 00538 if (pp0_avail) { 00539 for(j=0;j<num_packages;j++) { 00540 00541 sprintf(rapl_native_events[i].name, 00542 "PP0_ENERGY:PACKAGE%d",j); 00543 strncpy(rapl_native_events[i].units,"nJ",PAPI_MIN_STR_LEN); 00544 sprintf(rapl_native_events[i].description, 00545 "Energy used by all cores in package %d",j); 00546 rapl_native_events[i].fd_offset=cpu_to_use[j]; 00547 rapl_native_events[i].msr=MSR_PP0_ENERGY_STATUS; 00548 rapl_native_events[i].resources.selector = i + 1; 00549 rapl_native_events[i].type=PACKAGE_ENERGY; 00550 rapl_native_events[i].return_type=PAPI_DATATYPE_UINT64; 00551 00552 i++; 00553 } 00554 } 00555 00556 /* Export the total number of events available */ 00557 _rapl_vector.cmp_info.num_native_events = num_events; 00558 00559 _rapl_vector.cmp_info.num_cntrs = num_events; 00560 _rapl_vector.cmp_info.num_mpx_cntrs = num_events; 00561 00562 00563 /* Export the component id */ 00564 _rapl_vector.cmp_info.CmpIdx = cidx; 00565 00566 return PAPI_OK; 00567 } 00568 00569 00570 /* 00571 * Control of counters (Reading/Writing/Starting/Stopping/Setup) 00572 * functions 00573 */ 00574 int 00575 _rapl_init_control_state( hwd_control_state_t *ctl) 00576 { 00577 00578 _rapl_control_state_t* control = (_rapl_control_state_t*) ctl; 00579 int i; 00580 00581 for(i=0;i<RAPL_MAX_COUNTERS;i++) { 00582 control->being_measured[i]=0; 00583 } 00584 00585 return PAPI_OK; 00586 } 00587 00588 int 00589 _rapl_start( hwd_context_t *ctx, hwd_control_state_t *ctl) 00590 { 00591 _rapl_context_t* context = (_rapl_context_t*) ctx; 00592 _rapl_control_state_t* control = (_rapl_control_state_t*) ctl; 00593 long long now = PAPI_get_real_usec(); 00594 int i; 00595 00596 for( i = 0; i < RAPL_MAX_COUNTERS; i++ ) { 00597 if ((control->being_measured[i]) && (control->need_difference[i])) { 00598 context->start_count[i]=read_rapl_energy(i); 00599 } 00600 } 00601 00602 control->lastupdate = now; 00603 00604 return PAPI_OK; 00605 } 00606 00607 int 00608 _rapl_read( hwd_context_t *ctx, hwd_control_state_t *ctl, 00609 long long **events, int flags) 00610 { 00611 (void) flags; 00612 (void) events; 00613 00614 _rapl_context_t* context = (_rapl_context_t*) ctx; 00615 _rapl_control_state_t* control = (_rapl_control_state_t*) ctl; 00616 long long now = PAPI_get_real_usec(); 00617 int i; 00618 long long temp; 00619 00620 /* Only read the values from the kernel if enough time has passed */ 00621 /* since the last read. Otherwise return cached values. */ 00622 00623 if ( now - control->lastupdate > 60000000 ) { 00624 printf("Warning! Over 60s since last read, potential overflow!\n"); 00625 } 00626 00627 for( i = 0; i < RAPL_MAX_COUNTERS; i++ ) { 00628 if (control->being_measured[i]) { 00629 00630 if (control->need_difference[i]) { 00631 00632 temp=read_rapl_energy(i); 00633 control->count[i]=temp - context->start_count[i]; 00634 /* overflow */ 00635 if (control->count[i] < 0 ) { 00636 printf("Error! overflow!\n"); 00637 } 00638 } 00639 else { 00640 control->count[i]=read_rapl_energy(i); 00641 } 00642 00643 } 00644 } 00645 00646 control->lastupdate = now; 00647 00648 /* Pass back a pointer to our results */ 00649 *events = control->count; 00650 00651 return PAPI_OK; 00652 } 00653 00654 int 00655 _rapl_stop( hwd_context_t *ctx, hwd_control_state_t *ctl ) 00656 { 00657 00658 /* read values */ 00659 _rapl_context_t* context = (_rapl_context_t*) ctx; 00660 _rapl_control_state_t* control = (_rapl_control_state_t*) ctl; 00661 long long now = PAPI_get_real_usec(); 00662 int i; 00663 long long temp; 00664 00665 00666 if ( now - control->lastupdate > 60000000 ) { 00667 printf("Warning! Over 60s since last read, potential overflow!\n"); 00668 } 00669 00670 for( i = 0; i < RAPL_MAX_COUNTERS; i++ ) { 00671 if (control->being_measured[i]) { 00672 00673 if (control->need_difference[i]) { 00674 00675 temp=read_rapl_energy(i); 00676 control->count[i]=temp - context->start_count[i]; 00677 /* overflow */ 00678 if (control->count[i] < 0 ) { 00679 printf("Error! overflow!\n"); 00680 } 00681 00682 } 00683 else { 00684 control->count[i]=read_rapl_energy(i); 00685 } 00686 } 00687 } 00688 00689 control->lastupdate = now; 00690 00691 return PAPI_OK; 00692 } 00693 00694 /* Shutdown a thread */ 00695 int 00696 _rapl_shutdown_thread( hwd_context_t *ctx ) 00697 { 00698 ( void ) ctx; 00699 return PAPI_OK; 00700 } 00701 00702 00703 /* 00704 * Clean up what was setup in rapl_init_component(). 00705 */ 00706 int 00707 _rapl_shutdown_component( void ) 00708 { 00709 int i; 00710 00711 if (rapl_native_events) papi_free(rapl_native_events); 00712 if (fd_array) { 00713 for(i=0;i<num_cpus;i++) { 00714 if (fd_array[i].open) close(fd_array[i].fd); 00715 } 00716 papi_free(fd_array); 00717 } 00718 00719 return PAPI_OK; 00720 } 00721 00722 00723 /* This function sets various options in the component 00724 * The valid codes being passed in are PAPI_SET_DEFDOM, 00725 * PAPI_SET_DOMAIN, PAPI_SETDEFGRN, PAPI_SET_GRANUL * and PAPI_SET_INHERIT 00726 */ 00727 int 00728 _rapl_ctl( hwd_context_t *ctx, int code, _papi_int_option_t *option ) 00729 { 00730 ( void ) ctx; 00731 ( void ) code; 00732 ( void ) option; 00733 00734 printf("CTL\n"); 00735 00736 return PAPI_OK; 00737 } 00738 00739 00740 int 00741 _rapl_update_control_state( hwd_control_state_t *ctl, 00742 NativeInfo_t *native, int count, 00743 hwd_context_t *ctx ) 00744 { 00745 int i, index; 00746 ( void ) ctx; 00747 00748 _rapl_control_state_t* control = (_rapl_control_state_t*) ctl; 00749 00750 /* Ugh, what is this native[] stuff all about ?*/ 00751 /* Mostly remap stuff in papi_internal */ 00752 00753 for(i=0;i<RAPL_MAX_COUNTERS;i++) { 00754 control->being_measured[i]=0; 00755 } 00756 00757 for( i = 0; i < count; i++ ) { 00758 index=native[i].ni_event&PAPI_NATIVE_AND_MASK; 00759 native[i].ni_position=rapl_native_events[index].resources.selector - 1; 00760 control->being_measured[index]=1; 00761 00762 /* Only need to subtract if it's a PACKAGE_ENERGY type */ 00763 control->need_difference[index]= 00764 (rapl_native_events[index].type==PACKAGE_ENERGY); 00765 } 00766 00767 return PAPI_OK; 00768 } 00769 00770 00771 /* 00772 * This function has to set the bits needed to count different domains 00773 * In particular: PAPI_DOM_USER, PAPI_DOM_KERNEL PAPI_DOM_OTHER 00774 * By default return PAPI_EINVAL if none of those are specified 00775 * and PAPI_OK with success 00776 * PAPI_DOM_USER is only user context is counted 00777 * PAPI_DOM_KERNEL is only the Kernel/OS context is counted 00778 * PAPI_DOM_OTHER is Exception/transient mode (like user TLB misses) 00779 * PAPI_DOM_ALL is all of the domains 00780 */ 00781 int 00782 _rapl_set_domain( hwd_control_state_t *ctl, int domain ) 00783 { 00784 ( void ) ctl; 00785 (void) domain; 00786 00787 /* In theory we only support system-wide mode */ 00788 /* How to best handle that? */ 00789 00790 return PAPI_OK; 00791 } 00792 00793 00794 int 00795 _rapl_reset( hwd_context_t *ctx, hwd_control_state_t *ctl ) 00796 { 00797 ( void ) ctx; 00798 ( void ) ctl; 00799 00800 return PAPI_OK; 00801 } 00802 00803 00804 /* 00805 * Native Event functions 00806 */ 00807 int 00808 _rapl_ntv_enum_events( unsigned int *EventCode, int modifier ) 00809 { 00810 00811 int index; 00812 00813 switch ( modifier ) { 00814 00815 case PAPI_ENUM_FIRST: 00816 00817 if (num_events==0) { 00818 return PAPI_ENOEVNT; 00819 } 00820 *EventCode = 0; 00821 00822 return PAPI_OK; 00823 00824 00825 case PAPI_ENUM_EVENTS: 00826 00827 index = *EventCode & PAPI_NATIVE_AND_MASK; 00828 00829 if ( index < num_events - 1 ) { 00830 *EventCode = *EventCode + 1; 00831 return PAPI_OK; 00832 } else { 00833 return PAPI_ENOEVNT; 00834 } 00835 break; 00836 00837 default: 00838 return PAPI_EINVAL; 00839 } 00840 00841 return PAPI_EINVAL; 00842 } 00843 00844 /* 00845 * 00846 */ 00847 int 00848 _rapl_ntv_code_to_name( unsigned int EventCode, char *name, int len ) 00849 { 00850 00851 int index = EventCode & PAPI_NATIVE_AND_MASK; 00852 00853 if ( index >= 0 && index < num_events ) { 00854 strncpy( name, rapl_native_events[index].name, len ); 00855 return PAPI_OK; 00856 } 00857 00858 return PAPI_ENOEVNT; 00859 } 00860 00861 /* 00862 * 00863 */ 00864 int 00865 _rapl_ntv_code_to_descr( unsigned int EventCode, char *name, int len ) 00866 { 00867 int index = EventCode; 00868 00869 if ( index >= 0 && index < num_events ) { 00870 strncpy( name, rapl_native_events[index].description, len ); 00871 return PAPI_OK; 00872 } 00873 return PAPI_ENOEVNT; 00874 } 00875 00876 int 00877 _rapl_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info) 00878 { 00879 00880 int index = EventCode; 00881 00882 if ( ( index < 0) || (index >= num_events )) return PAPI_ENOEVNT; 00883 00884 strncpy( info->symbol, rapl_native_events[index].name, 00885 sizeof(info->symbol)); 00886 00887 strncpy( info->long_descr, rapl_native_events[index].description, 00888 sizeof(info->symbol)); 00889 00890 strncpy( info->units, rapl_native_events[index].units, 00891 sizeof(info->units)); 00892 00893 info->data_type = rapl_native_events[index].return_type; 00894 00895 return PAPI_OK; 00896 } 00897 00898 00899 00900 papi_vector_t _rapl_vector = { 00901 .cmp_info = { /* (unspecified values are initialized to 0) */ 00902 .name = "rapl", 00903 .short_name = "rapl", 00904 .description = "Linux SandyBridge RAPL energy measurements", 00905 .version = "4.2.1", 00906 .default_domain = PAPI_DOM_USER, 00907 .default_granularity = PAPI_GRN_THR, 00908 .available_granularities = PAPI_GRN_THR, 00909 .hardware_intr_sig = PAPI_INT_SIGNAL, 00910 .available_domains = PAPI_DOM_USER | PAPI_DOM_KERNEL, 00911 }, 00912 00913 /* sizes of framework-opaque component-private structures */ 00914 .size = { 00915 .context = sizeof ( _rapl_context_t ), 00916 .control_state = sizeof ( _rapl_control_state_t ), 00917 .reg_value = sizeof ( _rapl_register_t ), 00918 .reg_alloc = sizeof ( _rapl_reg_alloc_t ), 00919 }, 00920 /* function pointers in this component */ 00921 .init_thread = _rapl_init_thread, 00922 .init_component = _rapl_init_component, 00923 .init_control_state = _rapl_init_control_state, 00924 .start = _rapl_start, 00925 .stop = _rapl_stop, 00926 .read = _rapl_read, 00927 .shutdown_thread = _rapl_shutdown_thread, 00928 .shutdown_component = _rapl_shutdown_component, 00929 .ctl = _rapl_ctl, 00930 00931 .update_control_state = _rapl_update_control_state, 00932 .set_domain = _rapl_set_domain, 00933 .reset = _rapl_reset, 00934 00935 .ntv_enum_events = _rapl_ntv_enum_events, 00936 .ntv_code_to_name = _rapl_ntv_code_to_name, 00937 .ntv_code_to_descr = _rapl_ntv_code_to_descr, 00938 .ntv_code_to_info = _rapl_ntv_code_to_info, 00939 };