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