|
PAPI
5.0.1.0
|
00001 /* 00002 * File: papi_libpfm4_events.c 00003 * Author: Vince Weaver vweaver1 @ eecs.utk.edu 00004 * based heavily on existing papi_libpfm3_events.c 00005 */ 00006 00007 #include <string.h> 00008 00009 #include "papi.h" 00010 #include "papi_internal.h" 00011 #include "papi_vector.h" 00012 00013 #include "papi_libpfm4_events.h" 00014 00015 #include "perfmon/pfmlib.h" 00016 #include "perfmon/pfmlib_perf_event.h" 00017 00018 #define NATIVE_EVENT_CHUNK 1024 00019 00020 struct native_event_t { 00021 int component; 00022 char *pmu; 00023 int libpfm4_idx; 00024 char *allocated_name; 00025 char *base_name; 00026 char *pmu_plus_name; 00027 int users; 00028 long long config; 00029 long long config1; 00030 long long config2; 00031 int type; 00032 }; 00033 00034 static struct native_event_t *native_events; 00035 00036 static int num_native_events=0; 00037 static int allocated_native_events=0; 00038 00039 static pfm_pmu_info_t default_pmu; 00040 00041 00052 static int find_existing_event(char *name) { 00053 00054 int i,event=PAPI_ENOEVNT; 00055 00056 SUBDBG("Looking for %s in %d events\n",name,num_native_events); 00057 00058 _papi_hwi_lock( NAMELIB_LOCK ); 00059 00060 for(i=0;i<num_native_events;i++) { 00061 00062 if (!strcmp(name,native_events[i].allocated_name)) { 00063 SUBDBG("Found %s (%x)\n", 00064 native_events[i].allocated_name, 00065 native_events[i].libpfm4_idx); 00066 event=i; 00067 break; 00068 } 00069 } 00070 _papi_hwi_unlock( NAMELIB_LOCK ); 00071 00072 if (event<0) { SUBDBG("%s not allocated yet\n",name); } 00073 00074 return event; 00075 } 00076 00087 static struct native_event_t *find_existing_event_by_number(int eventnum) { 00088 00089 struct native_event_t *temp_event=NULL; 00090 00091 _papi_hwi_lock( NAMELIB_LOCK ); 00092 00093 temp_event=&native_events[eventnum]; 00094 00095 _papi_hwi_unlock( NAMELIB_LOCK ); 00096 00097 SUBDBG("Found %p for %x\n",temp_event,eventnum); 00098 00099 return temp_event; 00100 } 00101 00102 00113 static int find_event_no_aliases(char *name) { 00114 00115 int j,i, ret; 00116 pfm_pmu_info_t pinfo; 00117 pfm_event_info_t event_info; 00118 char full_name[BUFSIZ]; 00119 00120 SUBDBG("Looking for %s\n",name); 00121 00122 pfm_for_all_pmus(j) { 00123 00124 memset(&pinfo,0,sizeof(pfm_pmu_info_t)); 00125 pfm_get_pmu_info(j, &pinfo); 00126 if (!pinfo.is_present) { 00127 continue; 00128 } 00129 00130 SUBDBG("Looking in pmu %d\n",j); 00131 i = pinfo.first_event; 00132 while(1) { 00133 memset(&event_info,0,sizeof(pfm_event_info_t)); 00134 ret=pfm_get_event_info(i, PFM_OS_PERF_EVENT, &event_info); 00135 if (ret<0) break; 00136 00137 sprintf(full_name,"%s::%s",pinfo.name,event_info.name); 00138 00139 if (!strcmp(name,full_name)) { 00140 SUBDBG("FOUND %s %s %x\n",name,full_name,i); 00141 return i; 00142 } 00143 00144 if (!strcmp(name,event_info.name)) { 00145 SUBDBG("FOUND %s %s %x\n",name,event_info.name,i); 00146 return i; 00147 } 00148 i=pfm_get_event_next(i); 00149 } 00150 } 00151 return PFM_ERR_NOTFOUND; 00152 } 00153 00165 static int find_next_no_aliases(int code) { 00166 00167 int current_pmu=0,current_event=0; 00168 pfm_err_t ret; 00169 pfm_pmu_info_t pinfo; 00170 pfm_event_info_t event_info; 00171 00172 /* Clear the structures, as libpfm4 requires it */ 00173 memset(&event_info,0,sizeof(pfm_event_info_t)); 00174 00175 ret=pfm_get_event_info(code, PFM_OS_PERF_EVENT, &event_info); 00176 if (ret!=PFM_SUCCESS) { 00177 return ret; 00178 } 00179 00180 current_pmu=event_info.pmu; 00181 current_event=pfm_get_event_next(code); 00182 00183 SUBDBG("Current is %x guessing next is %x\n",code,current_event); 00184 00185 while(1) { 00186 00187 memset(&event_info,0,sizeof(pfm_event_info_t)); 00188 ret=pfm_get_event_info(current_event, PFM_OS_PERF_EVENT, &event_info); 00189 if (ret==PFM_SUCCESS) { 00190 SUBDBG("Returning %x\n",current_event); 00191 return current_event; 00192 } 00193 00194 /* next event not found, so try moving to next PMU */ 00195 00196 while(1) { 00197 00198 current_pmu++; 00199 SUBDBG("Incrementing PMU: %x\n",current_pmu); 00200 00201 /* Off the end, so done iterating */ 00202 if (current_pmu>PFM_PMU_MAX) { 00203 return PFM_ERR_NOTFOUND; 00204 } 00205 00206 memset(&pinfo,0,sizeof(pfm_pmu_info_t)); 00207 pfm_get_pmu_info(current_pmu, &pinfo); 00208 if (pinfo.is_present) break; 00209 } 00210 00211 current_event=pinfo.first_event; 00212 00213 } 00214 00215 } 00216 00229 static struct native_event_t *allocate_native_event(char *name, 00230 int event_idx) { 00231 00232 int new_event; 00233 00234 pfm_err_t ret; 00235 unsigned int i; 00236 char *base_start; 00237 pfm_event_info_t info; 00238 pfm_pmu_info_t pinfo; 00239 char base[BUFSIZ],pmuplusbase[BUFSIZ]; 00240 char fullname[BUFSIZ]; 00241 00242 pfm_perf_encode_arg_t perf_arg; 00243 00244 struct perf_event_attr perf_attr; 00245 00246 /* get the event name from libpfm */ 00247 memset(&info,0,sizeof(pfm_event_info_t)); 00248 ret = pfm_get_event_info(event_idx, PFM_OS_PERF_EVENT, &info); 00249 if (ret!=PFM_SUCCESS) { 00250 return NULL; 00251 } 00252 00253 /* get the PMU info */ 00254 memset(&pinfo,0,sizeof(pfm_pmu_info_t)); 00255 pfm_get_pmu_info(info.pmu, &pinfo); 00256 00257 /* calculate the base name, meaning strip off pmu identifier */ 00258 strncpy(base,name,BUFSIZ); 00259 i=0; 00260 base_start=base; 00261 while(i<strlen(base)) { 00262 if (base[i]==':') { 00263 if (base[i+1]==':') { 00264 i++; 00265 base_start=&base[i+1]; 00266 } 00267 else { 00268 base[i]=0; 00269 } 00270 } 00271 i++; 00272 } 00273 00274 /* add the event */ 00275 _papi_hwi_lock( NAMELIB_LOCK ); 00276 00277 new_event=num_native_events; 00278 00279 native_events[new_event].base_name=strdup(base_start); 00280 00281 sprintf(fullname,"%s::%s",pinfo.name,info.name); 00282 native_events[new_event].pmu_plus_name=strdup(fullname); 00283 00284 sprintf(pmuplusbase,"%s::%s",pinfo.name,base_start); 00285 00286 native_events[new_event].component=0; 00287 native_events[new_event].pmu=strdup(pinfo.name); 00288 00289 native_events[new_event].libpfm4_idx=find_event_no_aliases(pmuplusbase); 00290 00291 SUBDBG("Using %x as index instead of %x for %s\n", 00292 native_events[new_event].libpfm4_idx,event_idx,pmuplusbase); 00293 00294 native_events[new_event].allocated_name=strdup(name); 00295 00296 /* is this needed? */ 00297 native_events[new_event].users=0; 00298 00299 00300 /* use name of the event to get the perf_event encoding */ 00301 00302 /* clear the attribute structure */ 00303 memset(&perf_arg,0,sizeof(pfm_perf_encode_arg_t)); 00304 00305 /* clear out the perf_attr struct */ 00306 memset(&perf_attr,0,sizeof(struct perf_event_attr)); 00307 perf_arg.attr=&perf_attr; 00308 00309 ret = pfm_get_os_event_encoding(name, 00310 PFM_PLM0 | PFM_PLM3, 00311 PFM_OS_PERF_EVENT, 00312 &perf_arg); 00313 if (ret!=PFM_SUCCESS) { 00314 /* should do something! */ 00315 } 00316 00317 native_events[new_event].config=perf_arg.attr->config; 00318 native_events[new_event].config1=perf_arg.attr->config1; 00319 native_events[new_event].type=perf_arg.attr->type; 00320 00321 SUBDBG( "pe_event: config 0x%"PRIx64" config1 0x%"PRIx64" type 0x%"PRIx32"\n", 00322 perf_arg.attr->config, 00323 perf_arg.attr->config1, 00324 perf_arg.attr->type); 00325 00326 SUBDBG("Creating event %s with perfidx %x\n", 00327 name, 00328 native_events[new_event].libpfm4_idx); 00329 00330 num_native_events++; 00331 00332 /* If we've allocated too many native events, then allocate more room */ 00333 if (num_native_events >= allocated_native_events) { 00334 00335 SUBDBG("Allocating more room for native events (%d %ld)\n", 00336 (allocated_native_events+NATIVE_EVENT_CHUNK), 00337 (long)sizeof(struct native_event_t) * 00338 (allocated_native_events+NATIVE_EVENT_CHUNK)); 00339 00340 native_events=realloc(native_events, 00341 sizeof(struct native_event_t) * 00342 (allocated_native_events+NATIVE_EVENT_CHUNK)); 00343 allocated_native_events+=NATIVE_EVENT_CHUNK; 00344 } 00345 00346 _papi_hwi_unlock( NAMELIB_LOCK ); 00347 00348 if (native_events==NULL) { 00349 return NULL; 00350 } 00351 00352 return &native_events[new_event]; 00353 00354 } 00355 00370 static int find_max_umask(struct native_event_t *current_event) { 00371 00372 pfm_event_attr_info_t ainfo; 00373 char *b; 00374 int a, ret, max =0; 00375 pfm_event_info_t info; 00376 char event_string[BUFSIZ],*ptr; 00377 char temp_string[BUFSIZ]; 00378 00379 SUBDBG("Trying to find max umask in %s\n",current_event->allocated_name); 00380 00381 strcpy(event_string,current_event->allocated_name); 00382 00383 /* Skip leading :: delimited PMU name and point to first umask */ 00384 if (strstr(event_string,"::")) { 00385 ptr=strstr(event_string,"::"); 00386 ptr+=2; 00387 b=strtok(ptr,":"); 00388 } 00389 else { 00390 b=strtok(event_string,":"); 00391 } 00392 00393 if (!b) { 00394 SUBDBG("No colon!\n"); 00395 return PFM_ERR_UMASK; /* Must be this value!! */ 00396 } 00397 00398 memset(&info,0,sizeof(pfm_event_info_t)); 00399 ret = pfm_get_event_info(current_event->libpfm4_idx, 00400 PFM_OS_PERF_EVENT, &info); 00401 if (ret!=PFM_SUCCESS) { 00402 SUBDBG("get_event_info failed\n"); 00403 return PFM_ERR_NOTFOUND; 00404 } 00405 00406 /* skip first */ 00407 b=strtok(NULL,":"); 00408 if (!b) { 00409 SUBDBG("Skipping first failed\n"); 00410 return PFM_ERR_UMASK; /* Must be this value!! */ 00411 } 00412 00413 while(b) { 00414 a=0; 00415 while(1) { 00416 00417 SUBDBG("get_event_attr %x %d %p\n",current_event->libpfm4_idx,a,&ainfo); 00418 00419 memset(&ainfo,0,sizeof(pfm_event_attr_info_t)); 00420 00421 ret = pfm_get_event_attr_info(current_event->libpfm4_idx, a, 00422 PFM_OS_PERF_EVENT, &ainfo); 00423 00424 if (ret != PFM_SUCCESS) { 00425 SUBDBG("get_event_attr failed %s\n",pfm_strerror(ret)); 00426 return ret; 00427 } 00428 00429 SUBDBG("Trying %s with %s\n",ainfo.name,b); 00430 00431 if (ainfo.type == PFM_ATTR_MOD_BOOL) { 00432 sprintf(temp_string,"%s=0",ainfo.name); 00433 if (!strcasecmp(temp_string, b)) { 00434 SUBDBG("Found %s %d\n",b,a); 00435 if (a>max) max=a; 00436 goto found_attr; 00437 } 00438 } 00439 else if (ainfo.type == PFM_ATTR_MOD_INTEGER) { 00440 sprintf(temp_string,"%s=0",ainfo.name); 00441 if (!strcasecmp(temp_string, b)) { 00442 SUBDBG("Found %s %d\n",b,a); 00443 if (a>max) max=a; 00444 goto found_attr; 00445 } 00446 } 00447 else { 00448 if (!strcasecmp(ainfo.name, b)) { 00449 SUBDBG("Found %s %d\n",b,a); 00450 if (a>max) max=a; 00451 goto found_attr; 00452 } 00453 } 00454 a++; 00455 } 00456 00457 SUBDBG("attr=%s not found for event %s\n", b, info.name); 00458 00459 return PFM_ERR_ATTR; 00460 00461 found_attr: 00462 00463 b=strtok(NULL,":"); 00464 } 00465 00466 SUBDBG("Found max %d\n", max); 00467 00468 return max; 00469 } 00470 00471 00472 00481 static int 00482 get_event_first_active(void) 00483 { 00484 int pidx, pmu_idx, ret; 00485 00486 pfm_pmu_info_t pinfo; 00487 00488 pmu_idx=0; 00489 00490 while(pmu_idx<PFM_PMU_MAX) { 00491 00492 /* clear the PMU structure (required by libpfm4) */ 00493 memset(&pinfo,0,sizeof(pfm_pmu_info_t)); 00494 ret=pfm_get_pmu_info(pmu_idx, &pinfo); 00495 00496 if ((ret==PFM_SUCCESS) && pinfo.is_present) { 00497 00498 pidx=pinfo.first_event; 00499 00500 SUBDBG("First event in %s is %d\n",pinfo.name,pidx); 00501 00502 if (pidx<0) { 00503 /* For some reason no events available */ 00504 /* despite the PMU being active. */ 00505 /* This can happen, for example with ix86arch */ 00506 /* inside of VMware */ 00507 } 00508 else { 00509 return pidx; 00510 } 00511 } 00512 00513 pmu_idx++; 00514 00515 } 00516 00517 return PAPI_ENOEVNT; 00518 00519 } 00520 00521 00522 00537 static int 00538 convert_libpfm4_to_string( int code, char **event_name) 00539 { 00540 00541 int ret; 00542 pfm_event_info_t gete; 00543 pfm_pmu_info_t pinfo; 00544 char name[BUFSIZ]; 00545 00546 SUBDBG("ENTER %x\n",code); 00547 00548 /* Clear structures, as wanted by libpfm4 */ 00549 memset( &gete, 0, sizeof (pfm_event_info_t) ); 00550 00551 ret=pfm_get_event_info(code, PFM_OS_PERF_EVENT, &gete); 00552 if (ret!=PFM_SUCCESS) { 00553 return ret; 00554 } 00555 00556 memset( &pinfo, 0, sizeof(pfm_pmu_info_t) ); 00557 ret=pfm_get_pmu_info(gete.pmu, &pinfo); 00558 if (ret!=PFM_SUCCESS) { 00559 return ret; 00560 } 00561 00562 /* Only prepend PMU name if not on the "default" PMU */ 00563 00564 if (pinfo.pmu == default_pmu.pmu) { 00565 *event_name=strdup(gete.name); 00566 } 00567 else { 00568 sprintf(name,"%s::%s",pinfo.name,gete.name); 00569 *event_name=strdup(name); 00570 } 00571 00572 SUBDBG("Found name: %s\n",*event_name); 00573 00574 return PFM_SUCCESS; 00575 00576 } 00577 00578 00591 static int convert_pfmidx_to_native(int code, unsigned int *PapiEventCode) { 00592 00593 int ret; 00594 char *name=NULL; 00595 00596 ret=convert_libpfm4_to_string( code, &name); 00597 if (ret!=PFM_SUCCESS) { 00598 return _papi_libpfm4_error(ret); 00599 } 00600 00601 SUBDBG("Converted %x to %s\n",code,name); 00602 00603 ret=_papi_libpfm4_ntv_name_to_code(name,PapiEventCode); 00604 00605 SUBDBG("Converted %s to event %x\n",name,*PapiEventCode); 00606 00607 if (name) free(name); 00608 00609 return ret; 00610 00611 } 00612 00613 00632 static int find_next_umask(struct native_event_t *current_event, 00633 int current,char *umask_name) { 00634 00635 char temp_string[BUFSIZ]; 00636 pfm_event_info_t event_info; 00637 pfm_event_attr_info_t ainfo; 00638 int num_masks=0; 00639 pfm_err_t ret; 00640 int i; 00641 00642 /* get number of attributes */ 00643 00644 memset(&event_info, 0, sizeof(event_info)); 00645 ret=pfm_get_event_info(current_event->libpfm4_idx, 00646 PFM_OS_PERF_EVENT, &event_info); 00647 if (ret!=PFM_SUCCESS) { 00648 return ret; 00649 } 00650 00651 SUBDBG("%d possible attributes for event %s\n", 00652 event_info.nattrs, 00653 event_info.name); 00654 00655 pfm_for_each_event_attr(i, &event_info) { 00656 00657 ainfo.size = sizeof(ainfo); 00658 00659 ret = pfm_get_event_attr_info(event_info.idx, i, PFM_OS_PERF_EVENT, 00660 &ainfo); 00661 if (ret != PFM_SUCCESS) { 00662 SUBDBG("Not found\n"); 00663 return PFM_ERR_NOTFOUND; 00664 } 00665 00666 if (ainfo.type == PFM_ATTR_UMASK) { 00667 SUBDBG("nm %d looking for %d\n",num_masks,current); 00668 if (num_masks==current+1) { 00669 SUBDBG("Found attribute %d: %s type: %d\n", 00670 i,ainfo.name,ainfo.type); 00671 00672 sprintf(temp_string,"%s",ainfo.name); 00673 strncpy(umask_name,temp_string,BUFSIZ); 00674 00675 return current+1; 00676 } 00677 num_masks++; 00678 } 00679 00680 if (ainfo.type == PFM_ATTR_MOD_BOOL) { 00681 SUBDBG("nm %d looking for %d\n",num_masks,current); 00682 00683 if (num_masks==current+1) { 00684 SUBDBG("Found attribute %d: %s type: %d\n", 00685 i,ainfo.name,ainfo.type); 00686 00687 sprintf(temp_string,"%s=0",ainfo.name); 00688 strncpy(umask_name,temp_string,BUFSIZ); 00689 00690 return current+1; 00691 } 00692 num_masks++; 00693 } 00694 00695 if (ainfo.type == PFM_ATTR_MOD_INTEGER) { 00696 SUBDBG("nm %d looking for %d\n",num_masks,current); 00697 if (num_masks==current+1) { 00698 SUBDBG("Found attribute %d: %s type: %d\n", 00699 i,ainfo.name,ainfo.type); 00700 00701 sprintf(temp_string,"%s=0",ainfo.name); 00702 strncpy(umask_name,temp_string,BUFSIZ); 00703 00704 return current+1; 00705 } 00706 num_masks++; 00707 } 00708 } 00709 00710 return PFM_ERR_ATTR; 00711 00712 } 00713 00714 00715 00716 /***********************************************************/ 00717 /* Exported functions */ 00718 /***********************************************************/ 00719 00720 00731 int 00732 _papi_libpfm4_error( int pfm_error ) { 00733 00734 switch ( pfm_error ) { 00735 case PFM_SUCCESS: return PAPI_OK; /* success */ 00736 case PFM_ERR_NOTSUPP: return PAPI_ENOSUPP; /* function not supported */ 00737 case PFM_ERR_INVAL: return PAPI_EINVAL; /* invalid parameters */ 00738 case PFM_ERR_NOINIT: return PAPI_ENOINIT; /* library not initialized */ 00739 case PFM_ERR_NOTFOUND: return PAPI_ENOEVNT; /* event not found */ 00740 case PFM_ERR_FEATCOMB: return PAPI_ECOMBO; /* invalid combination of features */ 00741 case PFM_ERR_UMASK: return PAPI_EATTR; /* invalid or missing unit mask */ 00742 case PFM_ERR_NOMEM: return PAPI_ENOMEM; /* out of memory */ 00743 case PFM_ERR_ATTR: return PAPI_EATTR; /* invalid event attribute */ 00744 case PFM_ERR_ATTR_VAL: return PAPI_EATTR; /* invalid event attribute value */ 00745 case PFM_ERR_ATTR_SET: return PAPI_EATTR; /* attribute value already set */ 00746 case PFM_ERR_TOOMANY: return PAPI_ECOUNT; /* too many parameters */ 00747 case PFM_ERR_TOOSMALL: return PAPI_ECOUNT; /* parameter is too small */ 00748 default: return PAPI_EINVAL; 00749 } 00750 } 00751 00764 int 00765 _papi_libpfm4_ntv_name_to_code( char *name, unsigned int *event_code ) 00766 { 00767 00768 int actual_idx; 00769 struct native_event_t *our_event; 00770 int event_num; 00771 00772 SUBDBG( "Converting %s\n", name); 00773 00774 event_num=find_existing_event(name); 00775 00776 if (event_num<0) { 00777 00778 /* event currently doesn't exist, so try to find it */ 00779 /* using libpfm4 */ 00780 00781 SUBDBG("Using pfm to look up event %s\n",name); 00782 actual_idx=pfm_find_event(name); 00783 if (actual_idx<0) { 00784 return _papi_libpfm4_error(actual_idx); 00785 } 00786 00787 SUBDBG("Using %x as the index\n",actual_idx); 00788 00789 /* We were found in libpfm4, so allocate our copy of the event */ 00790 00791 our_event=allocate_native_event(name,actual_idx); 00792 if (our_event==NULL) return PAPI_ENOEVNT; 00793 00794 event_num=find_existing_event(name); 00795 } 00796 00797 if (event_num>=0) { 00798 *event_code=event_num; 00799 SUBDBG("Found code: %x\n",*event_code); 00800 return PAPI_OK; 00801 } 00802 00803 /* Failure here means allocate_native_event failed */ 00804 00805 SUBDBG("Event %s not found\n",name); 00806 00807 return PAPI_ENOEVNT; 00808 00809 } 00810 00811 00827 int 00828 _papi_libpfm4_ntv_code_to_name(unsigned int EventCode, char *ntv_name, int len) 00829 { 00830 00831 struct native_event_t *our_event; 00832 00833 SUBDBG("ENTER %x\n",EventCode); 00834 00835 our_event=find_existing_event_by_number(EventCode); 00836 if (our_event==NULL) { 00837 return PAPI_ENOEVNT; 00838 } 00839 00840 strncpy(ntv_name,our_event->allocated_name,len); 00841 00842 if (strlen(our_event->allocated_name) > (unsigned)len) { 00843 return PAPI_EBUF; 00844 } 00845 00846 return PAPI_OK; 00847 } 00848 00849 00870 int 00871 _papi_libpfm4_ntv_code_to_descr( unsigned int EventCode, 00872 char *ntv_descr, int len ) 00873 { 00874 int ret,a,first_mask=1; 00875 char *eventd, *tmp=NULL; 00876 pfm_event_info_t gete; 00877 00878 pfm_event_attr_info_t ainfo; 00879 char *b; 00880 char event_string[BUFSIZ],*ptr; 00881 char temp_string[BUFSIZ]; 00882 00883 struct native_event_t *our_event; 00884 00885 SUBDBG("ENTER %x\n",EventCode); 00886 00887 our_event=find_existing_event_by_number(EventCode); 00888 if (our_event==NULL) { 00889 return PAPI_ENOEVNT; 00890 } 00891 00892 SUBDBG("Getting info on %x\n",our_event->libpfm4_idx); 00893 00894 /* libpfm requires the structure be zeroed */ 00895 memset( &gete, 0, sizeof ( gete ) ); 00896 00897 ret=pfm_get_event_info(our_event->libpfm4_idx, PFM_OS_PERF_EVENT, &gete); 00898 if (ret<0) { 00899 SUBDBG("Return=%d\n",ret); 00900 return _papi_libpfm4_error(ret); 00901 } 00902 00903 eventd=strdup(gete.desc); 00904 00905 tmp = ( char * ) malloc( strlen( eventd ) + 1 ); 00906 if ( tmp == NULL ) { 00907 free( eventd ); 00908 return PAPI_ENOMEM; 00909 } 00910 00911 tmp[0] = '\0'; 00912 strcat( tmp, eventd ); 00913 free( eventd ); 00914 00915 /* Handle Umasks */ 00916 00917 /* attributes concactinated onto end of descr separated by ", masks" */ 00918 /* then comma separated */ 00919 00920 strcpy(event_string,our_event->allocated_name); 00921 00922 /* Point to first umask */ 00923 00924 /* Skip the pmu name :: if one exists */ 00925 if (strstr(event_string,"::")) { 00926 ptr=strstr(event_string,"::"); 00927 ptr+=2; 00928 b=strtok(ptr,":"); 00929 } 00930 else { 00931 b=strtok(event_string,":"); 00932 } 00933 00934 /* if no umask, then done */ 00935 if (!b) { 00936 SUBDBG("No colon!\n"); /* no umask */ 00937 goto descr_in_tmp; 00938 } 00939 00940 /* skip first */ 00941 b=strtok(NULL,":"); 00942 if (!b) { 00943 SUBDBG("Skipping first failed\n"); 00944 goto descr_in_tmp; 00945 } 00946 00947 /* loop through all umasks, seeing which match */ 00948 while(b) { 00949 a=0; 00950 while(1) { 00951 00952 SUBDBG("get_event_attr %x %p\n",our_event->libpfm4_idx,&ainfo); 00953 00954 memset(&ainfo,0,sizeof(pfm_event_attr_info_t)); 00955 00956 ret = pfm_get_event_attr_info(our_event->libpfm4_idx, a, 00957 PFM_OS_PERF_EVENT, &ainfo); 00958 if (ret != PFM_SUCCESS) { 00959 SUBDBG("get_event_attr failed %s\n",pfm_strerror(ret)); 00960 return _papi_libpfm4_error(ret); 00961 } 00962 00963 /* Plain UMASK case */ 00964 if (ainfo.type == PFM_ATTR_UMASK) { 00965 00966 SUBDBG("Trying %s with %s\n",ainfo.name,b); 00967 00968 if (!strcasecmp(ainfo.name, b)) { 00969 int new_length; 00970 00971 SUBDBG("Found %s\n",b); 00972 new_length=strlen(ainfo.desc); 00973 00974 if (first_mask) { 00975 tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(", masks:")); 00976 strcat(tmp,", masks:"); 00977 first_mask=0; 00978 } 00979 else { 00980 tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(",")); 00981 strcat(tmp,","); 00982 } 00983 strcat(tmp,ainfo.desc); 00984 00985 goto found_attr; 00986 } 00987 } 00988 00989 /* Boolean Case */ 00990 if (ainfo.type == PFM_ATTR_MOD_BOOL) { 00991 00992 sprintf(temp_string,"%s=0",ainfo.name); 00993 00994 SUBDBG("Trying %s with %s\n",temp_string,b); 00995 00996 if (!strcasecmp(temp_string, b)) { 00997 int new_length; 00998 00999 SUBDBG("Found %s\n",b); 01000 new_length=strlen(ainfo.desc); 01001 01002 if (first_mask) { 01003 tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(", masks:")); 01004 strcat(tmp,", masks:"); 01005 first_mask=0; 01006 } 01007 else { 01008 tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(",")); 01009 strcat(tmp,","); 01010 } 01011 strcat(tmp,ainfo.desc); 01012 01013 goto found_attr; 01014 } 01015 } 01016 01017 /* Integer Case */ 01018 if (ainfo.type == PFM_ATTR_MOD_INTEGER) { 01019 01020 sprintf(temp_string,"%s=0",ainfo.name); 01021 01022 SUBDBG("Trying %s with %s\n",temp_string,b); 01023 01024 if (!strcasecmp(temp_string, b)) { 01025 int new_length; 01026 01027 SUBDBG("Found %s\n",b); 01028 new_length=strlen(ainfo.desc); 01029 01030 if (first_mask) { 01031 tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(", masks:")); 01032 strcat(tmp,", masks:"); 01033 first_mask=0; 01034 } 01035 else { 01036 tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(",")); 01037 strcat(tmp,","); 01038 } 01039 strcat(tmp,ainfo.desc); 01040 01041 goto found_attr; 01042 } 01043 } 01044 01045 a++; 01046 } 01047 01048 SUBDBG("attr=%s not found for event %s\n", b, ainfo.name); 01049 01050 return PAPI_EATTR; 01051 01052 found_attr: 01053 01054 b=strtok(NULL,":"); 01055 } 01056 01057 /* We are done and the description to copy is in tmp */ 01058 descr_in_tmp: 01059 strncpy( ntv_descr, tmp, ( size_t ) len ); 01060 if ( ( int ) strlen( tmp ) > len - 1 ) 01061 ret = PAPI_EBUF; 01062 else 01063 ret = PAPI_OK; 01064 free( tmp ); 01065 01066 SUBDBG("PFM4 Code: %x %s\n",EventCode,ntv_descr); 01067 01068 return ret; 01069 } 01070 01071 01072 int 01073 _papi_libpfm4_ntv_code_to_info(unsigned int EventCode, PAPI_event_info_t *info) 01074 { 01075 01076 01077 struct native_event_t *our_event; 01078 01079 SUBDBG("ENTER %x\n",EventCode); 01080 01081 our_event=find_existing_event_by_number(EventCode); 01082 if (our_event==NULL) { 01083 return PAPI_ENOEVNT; 01084 } 01085 01086 strncpy(info->symbol, our_event->allocated_name, sizeof(info->symbol)); 01087 01088 if (strlen(our_event->allocated_name) > sizeof(info->symbol)) { 01089 return PAPI_EBUF; 01090 } 01091 01092 _papi_libpfm4_ntv_code_to_descr(EventCode,info->long_descr, 01093 sizeof(info->long_descr)); 01094 01095 return PAPI_OK; 01096 } 01097 01098 01099 01114 int 01115 _papi_libpfm4_ntv_enum_events( unsigned int *PapiEventCode, int modifier ) 01116 { 01117 int code,ret; 01118 struct native_event_t *current_event; 01119 01120 SUBDBG("ENTER\n"); 01121 01122 /* return first event if so specified */ 01123 if ( modifier == PAPI_ENUM_FIRST ) { 01124 01125 unsigned int papi_event=0; 01126 01127 SUBDBG("ENUM_FIRST\n"); 01128 01129 code=get_event_first_active(); 01130 SUBDBG("ENUM_FIRST code: %d\n",code); 01131 if (code < 0 ) { 01132 return code; 01133 } 01134 01135 /* convert the libpfm4 event to a PAPI event */ 01136 ret=convert_pfmidx_to_native(code, &papi_event); 01137 01138 *PapiEventCode=(unsigned int)papi_event; 01139 01140 SUBDBG("FOUND %x (from %x) ret=%d\n",*PapiEventCode,code,ret); 01141 01142 return ret; 01143 } 01144 01145 /* If we get this far, we're looking for a */ 01146 /* next-event. So gather info on the current one */ 01147 current_event=find_existing_event_by_number(*PapiEventCode); 01148 if (current_event==NULL) { 01149 SUBDBG("EVENTS %x not found\n",*PapiEventCode); 01150 return PAPI_ENOEVNT; 01151 } 01152 01153 01154 /* Handle looking for the next event */ 01155 01156 if ( modifier == PAPI_ENUM_EVENTS ) { 01157 01158 unsigned int papi_event=0; 01159 01160 SUBDBG("PAPI_ENUM_EVENTS %x\n",*PapiEventCode); 01161 01162 code=current_event->libpfm4_idx; 01163 01164 ret=find_next_no_aliases(code); 01165 SUBDBG("find_next_no_aliases() Returned %x\n",ret); 01166 if (ret<0) { 01167 return ret; 01168 } 01169 01170 /* Convert libpfm4 event code to PAPI event code */ 01171 ret=convert_pfmidx_to_native(ret, &papi_event); 01172 if (ret<0) { 01173 SUBDBG("Couldn't convert to native %d %s\n", 01174 ret,PAPI_strerror(ret)); 01175 return ret; 01176 } 01177 01178 *PapiEventCode=(unsigned int)papi_event; 01179 01180 SUBDBG("Returning PAPI_OK\n"); 01181 01182 return ret; 01183 } 01184 01185 /* We don't handle PAPI_NTV_ENUM_UMASK_COMBOS */ 01186 if ( modifier == PAPI_NTV_ENUM_UMASK_COMBOS ) { 01187 return PAPI_ENOIMPL; 01188 } 01189 01190 /* Enumerate PAPI_NTV_ENUM_UMASKS (umasks on an event) */ 01191 if ( modifier == PAPI_NTV_ENUM_UMASKS ) { 01192 01193 int max_umask,next_umask; 01194 char umask_string[BUFSIZ],new_name[BUFSIZ]; 01195 01196 SUBDBG("Finding maximum mask in event %s\n", 01197 current_event->allocated_name); 01198 01199 max_umask=find_max_umask(current_event); 01200 SUBDBG("Found max %d\n",max_umask); 01201 01202 if (max_umask<0) { 01203 if (max_umask==PFM_ERR_UMASK) { 01204 max_umask=-1; /* needed for find_next_umask() to work */ 01205 /* indicates the event as passed had no */ 01206 /* umask in it. */ 01207 } 01208 else { 01209 return _papi_libpfm4_error(max_umask); 01210 } 01211 } 01212 01213 next_umask=find_next_umask(current_event,max_umask, 01214 umask_string); 01215 01216 SUBDBG("Found next %d\n",next_umask); 01217 01218 if (next_umask>=0) { 01219 01220 unsigned int papi_event; 01221 01222 sprintf(new_name,"%s:%s",current_event->base_name, 01223 umask_string); 01224 01225 SUBDBG("Found new name %s\n",new_name); 01226 01227 ret=_papi_libpfm4_ntv_name_to_code(new_name,&papi_event); 01228 if (ret!=PAPI_OK) { 01229 return PAPI_ENOEVNT; 01230 } 01231 01232 *PapiEventCode=(unsigned int)papi_event; 01233 SUBDBG("found code %x\n",*PapiEventCode); 01234 01235 return PAPI_OK; 01236 } 01237 01238 SUBDBG("couldn't find umask\n"); 01239 01240 return _papi_libpfm4_error(next_umask); 01241 01242 } 01243 01244 /* An unknown enumeration method was indicated */ 01245 01246 return PAPI_ENOIMPL; 01247 } 01248 01256 int 01257 _papi_libpfm4_shutdown(void) { 01258 01259 int i; 01260 01261 SUBDBG("shutdown\n"); 01262 01263 /* clean out and free the native events structure */ 01264 _papi_hwi_lock( NAMELIB_LOCK ); 01265 01266 /* free memory allocate with strdup */ 01267 for( i=0; i<num_native_events; i++) { 01268 free(native_events[i].base_name); 01269 free(native_events[i].pmu_plus_name); 01270 free(native_events[i].pmu); 01271 free(native_events[i].allocated_name); 01272 } 01273 01274 memset(native_events,0, 01275 sizeof(struct native_event_t)*allocated_native_events); 01276 num_native_events=0; 01277 allocated_native_events=0; 01278 free(native_events); 01279 _papi_hwi_unlock( NAMELIB_LOCK ); 01280 01281 return PAPI_OK; 01282 } 01283 01284 01293 int 01294 _papi_libpfm4_init(papi_vector_t *my_vector, int cidx) { 01295 01296 int detected_pmus=0, found_default=0; 01297 int i, version; 01298 pfm_err_t retval; 01299 unsigned int ncnt; 01300 pfm_pmu_info_t pinfo; 01301 01302 /* The following checks the version of the PFM library 01303 against the version PAPI linked to... */ 01304 if ( ( retval = pfm_initialize( ) ) != PFM_SUCCESS ) { 01305 PAPIERROR( "pfm_initialize(): %s", pfm_strerror( retval ) ); 01306 return PAPI_ESYS; 01307 } 01308 01309 /* get the libpfm4 version */ 01310 SUBDBG( "pfm_get_version()\n"); 01311 if ( (version=pfm_get_version( )) < 0 ) { 01312 PAPIERROR( "pfm_get_version(): %s", pfm_strerror( retval ) ); 01313 return PAPI_ESYS; 01314 } 01315 01316 /* Set the version */ 01317 sprintf( my_vector->cmp_info.support_version, "%d.%d", 01318 PFM_MAJ_VERSION( version ), PFM_MIN_VERSION( version ) ); 01319 01320 /* Complain if the compiled-against version doesn't match current version */ 01321 if ( PFM_MAJ_VERSION( version ) != PFM_MAJ_VERSION( LIBPFM_VERSION ) ) { 01322 PAPIERROR( "Version mismatch of libpfm: compiled %x vs. installed %x\n", 01323 PFM_MAJ_VERSION( LIBPFM_VERSION ), 01324 PFM_MAJ_VERSION( version ) ); 01325 return PAPI_ESYS; 01326 } 01327 01328 /* allocate the native event structure */ 01329 01330 num_native_events=0; 01331 01332 native_events=calloc(NATIVE_EVENT_CHUNK,sizeof(struct native_event_t)); 01333 if (native_events==NULL) { 01334 return PAPI_ENOMEM; 01335 } 01336 allocated_native_events=NATIVE_EVENT_CHUNK; 01337 01338 /* Count number of present PMUs */ 01339 detected_pmus=0; 01340 ncnt=0; 01341 01342 /* need to init pinfo or pfmlib might complain */ 01343 memset(&default_pmu, 0, sizeof(pfm_pmu_info_t)); 01344 /* init default pmu */ 01345 retval=pfm_get_pmu_info(0, &default_pmu); 01346 01347 SUBDBG("Detected pmus:\n"); 01348 for(i=0;i<PFM_PMU_MAX;i++) { 01349 memset(&pinfo,0,sizeof(pfm_pmu_info_t)); 01350 retval=pfm_get_pmu_info(i, &pinfo); 01351 if (retval!=PFM_SUCCESS) { 01352 continue; 01353 } 01354 if (pinfo.is_present) { 01355 SUBDBG("\t%d %s %s %d\n",i,pinfo.name,pinfo.desc,pinfo.type); 01356 01357 detected_pmus++; 01358 ncnt+=pinfo.nevents; 01359 01360 /* Choose default PMU */ 01361 if ( (pinfo.type==PFM_PMU_TYPE_CORE) && 01362 strcmp(pinfo.name,"ix86arch")) { 01363 01364 SUBDBG("\t %s is default\n",pinfo.name); 01365 memcpy(&default_pmu,&pinfo,sizeof(pfm_pmu_info_t)); 01366 found_default++; 01367 } 01368 } 01369 } 01370 SUBDBG("%d native events detected on %d pmus\n",ncnt,detected_pmus); 01371 01372 if (!found_default) { 01373 PAPIERROR("Could not find default PMU\n"); 01374 return PAPI_ECMP; 01375 } 01376 01377 if (found_default>1) { 01378 PAPIERROR("Found too many default PMUs!\n"); 01379 return PAPI_ECMP; 01380 } 01381 01382 my_vector->cmp_info.num_native_events = ncnt; 01383 01384 my_vector->cmp_info.num_cntrs = default_pmu.num_cntrs+ 01385 default_pmu.num_fixed_cntrs; 01386 01387 SUBDBG( "num_counters: %d\n", my_vector->cmp_info.num_cntrs ); 01388 01389 /* Setup presets */ 01390 retval = _papi_load_preset_table( (char *)default_pmu.name, 01391 default_pmu.pmu, cidx ); 01392 if ( retval ) { 01393 return retval; 01394 } 01395 01396 return PAPI_OK; 01397 } 01398 01399 01412 int 01413 _papi_libpfm4_setup_counters( struct perf_event_attr *attr, 01414 int event ) { 01415 01416 struct native_event_t *our_event; 01417 01418 our_event=find_existing_event_by_number(event); 01419 if (our_event==NULL) { 01420 return PAPI_ENOEVNT; 01421 } 01422 01423 attr->config=our_event->config; 01424 attr->config1=our_event->config1; 01425 attr->config2=our_event->config2; 01426 attr->type=our_event->type; 01427 01428 SUBDBG( "pe_event: config 0x%"PRIx64 01429 " config1 0x%"PRIx64 01430 " type 0x%"PRIx32"\n", 01431 attr->config, 01432 attr->config1, 01433 attr->type); 01434 01435 01436 return PAPI_OK; 01437 } 01438 01439 01440 01441 01442