|
PAPI
5.3.0.0
|
00001 /* 00002 * File: peu_libpfm4_events.c 00003 * Author: Vince Weaver vincent.weaver @ maine.edu 00004 * 00005 * Handle the libpfm4 event interface for the perf_event_uncore component 00006 */ 00007 00008 #include <string.h> 00009 00010 #include "papi.h" 00011 #include "papi_internal.h" 00012 #include "papi_vector.h" 00013 00014 #include "papi_libpfm4_events.h" 00015 #include "peu_libpfm4_events.h" 00016 00017 #include "perfmon/pfmlib.h" 00018 #include "perfmon/pfmlib_perf_event.h" 00019 00020 #define NATIVE_EVENT_CHUNK 1024 00021 00034 static int find_existing_event(char *name, 00035 struct native_event_table_t *event_table) { 00036 00037 int i,event=PAPI_ENOEVNT; 00038 00039 SUBDBG("Looking for %s in %d events\n", 00040 name,event_table->num_native_events); 00041 00042 _papi_hwi_lock( NAMELIB_LOCK ); 00043 00044 for(i=0;i<event_table->num_native_events;i++) { 00045 00046 if (!strcmp(name,event_table->native_events[i].allocated_name)) { 00047 SUBDBG("Found %s (%#x)\n", 00048 event_table->native_events[i].allocated_name, 00049 event_table->native_events[i].libpfm4_idx); 00050 event=i; 00051 break; 00052 } 00053 } 00054 _papi_hwi_unlock( NAMELIB_LOCK ); 00055 00056 if (event<0) { SUBDBG("%s not allocated yet\n",name); } 00057 00058 return event; 00059 } 00060 00073 static struct native_event_t *find_existing_event_by_number(int eventnum, 00074 struct native_event_table_t *event_table) { 00075 00076 struct native_event_t *temp_event=NULL; 00077 00078 _papi_hwi_lock( NAMELIB_LOCK ); 00079 00080 temp_event=&(event_table->native_events[eventnum]); 00081 00082 _papi_hwi_unlock( NAMELIB_LOCK ); 00083 00084 SUBDBG("Found %p for %#x\n",temp_event,eventnum); 00085 00086 return temp_event; 00087 } 00088 00089 static int pmu_is_present_and_right_type(pfm_pmu_info_t *pinfo, int type) { 00090 00091 if (!pinfo->is_present) return 0; 00092 00093 if ((pinfo->type==PFM_PMU_TYPE_UNCORE) && (type&PMU_TYPE_UNCORE)) return 1; 00094 if ((pinfo->type==PFM_PMU_TYPE_CORE) && (type&PMU_TYPE_CORE)) return 1; 00095 if ((pinfo->type==PFM_PMU_TYPE_OS_GENERIC) && (type&PMU_TYPE_OS)) return 1; 00096 00097 return 0; 00098 } 00099 00100 00112 static int find_event(char *name, int pmu_type) { 00113 00114 int ret, actual_idx; 00115 pfm_pmu_info_t pinfo; 00116 pfm_event_info_t event_info; 00117 00118 SUBDBG("Looking for %s\n",name); 00119 00120 actual_idx=pfm_find_event(name); 00121 if (actual_idx<0) { 00122 return PFM_ERR_NOTFOUND; 00123 } 00124 00125 memset(&event_info,0,sizeof(pfm_event_info_t)); 00126 ret=pfm_get_event_info(actual_idx, PFM_OS_PERF_EVENT, &event_info); 00127 if (ret<0) { 00128 return PFM_ERR_NOTFOUND; 00129 } 00130 00131 memset(&pinfo,0,sizeof(pfm_pmu_info_t)); 00132 pfm_get_pmu_info(event_info.pmu, &pinfo); 00133 if (pmu_is_present_and_right_type(&pinfo,pmu_type)) { 00134 return actual_idx; 00135 } 00136 00137 return PFM_ERR_NOTFOUND; 00138 } 00139 00140 00152 static int find_event_no_aliases(char *name, int pmu_type) { 00153 00154 int j,i, ret; 00155 pfm_pmu_info_t pinfo; 00156 pfm_event_info_t event_info; 00157 char full_name[BUFSIZ]; 00158 00159 SUBDBG("Looking for %s\n",name); 00160 00161 pfm_for_all_pmus(j) { 00162 00163 memset(&pinfo,0,sizeof(pfm_pmu_info_t)); 00164 pfm_get_pmu_info(j, &pinfo); 00165 if (!pmu_is_present_and_right_type(&pinfo,pmu_type)) { 00166 continue; 00167 } 00168 00169 SUBDBG("Looking in pmu %d\n",j); 00170 i = pinfo.first_event; 00171 while(1) { 00172 memset(&event_info,0,sizeof(pfm_event_info_t)); 00173 ret=pfm_get_event_info(i, PFM_OS_PERF_EVENT, &event_info); 00174 if (ret<0) break; 00175 00176 sprintf(full_name,"%s::%s",pinfo.name,event_info.name); 00177 00178 if (!strcmp(name,full_name)) { 00179 SUBDBG("FOUND %s %s %#x\n",name,full_name,i); 00180 return i; 00181 } 00182 00183 if (!strcmp(name,event_info.name)) { 00184 SUBDBG("FOUND %s %s %#x\n",name,event_info.name,i); 00185 return i; 00186 } 00187 i=pfm_get_event_next(i); 00188 } 00189 } 00190 return PFM_ERR_NOTFOUND; 00191 } 00192 00193 00205 static int find_next_no_aliases(int code, int pmu_type) { 00206 00207 int current_pmu=0,current_event=0; 00208 pfm_err_t ret; 00209 pfm_pmu_info_t pinfo; 00210 pfm_event_info_t event_info; 00211 00212 /* Clear the structures, as libpfm4 requires it */ 00213 memset(&event_info,0,sizeof(pfm_event_info_t)); 00214 00215 ret=pfm_get_event_info(code, PFM_OS_PERF_EVENT, &event_info); 00216 if (ret!=PFM_SUCCESS) { 00217 return ret; 00218 } 00219 00220 current_pmu=event_info.pmu; 00221 current_event=pfm_get_event_next(code); 00222 00223 SUBDBG("Current is %#x guessing next is %#x\n",code,current_event); 00224 00225 while(1) { 00226 00227 memset(&event_info,0,sizeof(pfm_event_info_t)); 00228 ret=pfm_get_event_info(current_event, PFM_OS_PERF_EVENT, &event_info); 00229 if (ret==PFM_SUCCESS) { 00230 SUBDBG("Returning %#x\n",current_event); 00231 return current_event; 00232 } 00233 00234 /* next event not found, so try moving to next PMU */ 00235 00236 while(1) { 00237 00238 current_pmu++; 00239 SUBDBG("Incrementing PMU: %#x\n",current_pmu); 00240 00241 /* Off the end, so done iterating */ 00242 if (current_pmu>PFM_PMU_MAX) { 00243 return PFM_ERR_NOTFOUND; 00244 } 00245 00246 memset(&pinfo,0,sizeof(pfm_pmu_info_t)); 00247 pfm_get_pmu_info(current_pmu, &pinfo); 00248 if (pmu_is_present_and_right_type(&pinfo,pmu_type)) break; 00249 } 00250 00251 current_event=pinfo.first_event; 00252 00253 } 00254 00255 } 00256 00271 static struct native_event_t *allocate_native_event(char *name, 00272 int event_idx, 00273 struct native_event_table_t *event_table) { 00274 00275 int new_event; 00276 00277 pfm_err_t ret; 00278 unsigned int i; 00279 char *base_start; 00280 pfm_event_info_t info; 00281 pfm_pmu_info_t pinfo; 00282 char base[BUFSIZ],pmuplusbase[BUFSIZ]; 00283 char fullname[BUFSIZ]; 00284 00285 pfm_perf_encode_arg_t perf_arg; 00286 00287 struct perf_event_attr perf_attr; 00288 00289 /* get the event name from libpfm */ 00290 memset(&info,0,sizeof(pfm_event_info_t)); 00291 ret = pfm_get_event_info(event_idx, PFM_OS_PERF_EVENT, &info); 00292 if (ret!=PFM_SUCCESS) { 00293 return NULL; 00294 } 00295 00296 /* get the PMU info */ 00297 memset(&pinfo,0,sizeof(pfm_pmu_info_t)); 00298 pfm_get_pmu_info(info.pmu, &pinfo); 00299 00300 /* calculate the base name, meaning strip off pmu identifier */ 00301 strncpy(base,name,BUFSIZ); 00302 i=0; 00303 base_start=base; 00304 while(i<strlen(base)) { 00305 if (base[i]==':') { 00306 if (base[i+1]==':') { 00307 i++; 00308 base_start=&base[i+1]; 00309 } 00310 else { 00311 base[i]=0; 00312 } 00313 } 00314 i++; 00315 } 00316 00317 /* add the event */ 00318 _papi_hwi_lock( NAMELIB_LOCK ); 00319 00320 new_event=event_table->num_native_events; 00321 00322 event_table->native_events[new_event].base_name=strdup(base_start); 00323 00324 sprintf(fullname,"%s::%s",pinfo.name,info.name); 00325 event_table->native_events[new_event].pmu_plus_name=strdup(fullname); 00326 00327 sprintf(pmuplusbase,"%s::%s",pinfo.name,base_start); 00328 00329 event_table->native_events[new_event].component=0; 00330 event_table->native_events[new_event].pmu=strdup(pinfo.name); 00331 00332 event_table->native_events[new_event].libpfm4_idx= 00333 find_event_no_aliases(pmuplusbase,event_table->pmu_type); 00334 00335 SUBDBG("Using %#x as index instead of %#x for %s\n", 00336 event_table->native_events[new_event].libpfm4_idx, 00337 event_idx,pmuplusbase); 00338 00339 event_table->native_events[new_event].allocated_name=strdup(name); 00340 00341 /* is this needed? */ 00342 event_table->native_events[new_event].users=0; 00343 00344 00345 /* use name of the event to get the perf_event encoding */ 00346 00347 /* clear the attribute structure */ 00348 memset(&perf_arg,0,sizeof(pfm_perf_encode_arg_t)); 00349 00350 /* clear out the perf_attr struct */ 00351 memset(&perf_attr,0,sizeof(struct perf_event_attr)); 00352 perf_arg.attr=&perf_attr; 00353 00354 ret = pfm_get_os_event_encoding(name, 00355 PFM_PLM0 | PFM_PLM3, 00356 PFM_OS_PERF_EVENT, 00357 &perf_arg); 00358 if (ret==PFM_SUCCESS) { 00359 00360 event_table->native_events[new_event].config=perf_arg.attr->config; 00361 event_table->native_events[new_event].config1=perf_arg.attr->config1; 00362 event_table->native_events[new_event].type=perf_arg.attr->type; 00363 00364 SUBDBG( "pe_event: config 0x%"PRIx64" config1 0x%"PRIx64 00365 " type 0x%"PRIx32"\n", 00366 perf_arg.attr->config, 00367 perf_arg.attr->config1, 00368 perf_arg.attr->type); 00369 00370 SUBDBG("Creating event %s with perfidx %#x\n", 00371 name, event_table->native_events[new_event].libpfm4_idx); 00372 00373 event_table->num_native_events++; 00374 00375 /* If we've allocated too many native events, then allocate more room */ 00376 if (event_table->num_native_events >= 00377 event_table->allocated_native_events) { 00378 00379 SUBDBG("Allocating more room for native events (%d %ld)\n", 00380 (event_table->allocated_native_events+NATIVE_EVENT_CHUNK), 00381 (long)sizeof(struct native_event_t) * 00382 (event_table->allocated_native_events+NATIVE_EVENT_CHUNK)); 00383 00384 event_table->native_events=realloc(event_table->native_events, 00385 sizeof(struct native_event_t) * 00386 (event_table->allocated_native_events+NATIVE_EVENT_CHUNK)); 00387 event_table->allocated_native_events+=NATIVE_EVENT_CHUNK; 00388 } 00389 } 00390 _papi_hwi_unlock( NAMELIB_LOCK ); 00391 00392 if (event_table->native_events==NULL) { 00393 return NULL; 00394 } 00395 00396 return &event_table->native_events[new_event]; 00397 00398 } 00399 00414 static int find_max_umask(struct native_event_t *current_event) { 00415 00416 pfm_event_attr_info_t ainfo; 00417 char *b; 00418 int a, ret, max =0; 00419 pfm_event_info_t info; 00420 char event_string[BUFSIZ],*ptr; 00421 char temp_string[BUFSIZ]; 00422 00423 SUBDBG("Trying to find max umask in %s\n",current_event->allocated_name); 00424 00425 strcpy(event_string,current_event->allocated_name); 00426 00427 /* Skip leading :: delimited PMU name and point to first umask */ 00428 if (strstr(event_string,"::")) { 00429 ptr=strstr(event_string,"::"); 00430 ptr+=2; 00431 b=strtok(ptr,":"); 00432 } 00433 else { 00434 b=strtok(event_string,":"); 00435 } 00436 00437 if (!b) { 00438 SUBDBG("No colon!\n"); 00439 return PFM_ERR_UMASK; /* Must be this value!! */ 00440 } 00441 00442 memset(&info,0,sizeof(pfm_event_info_t)); 00443 ret = pfm_get_event_info(current_event->libpfm4_idx, 00444 PFM_OS_PERF_EVENT, &info); 00445 if (ret!=PFM_SUCCESS) { 00446 SUBDBG("get_event_info failed\n"); 00447 return PFM_ERR_NOTFOUND; 00448 } 00449 00450 /* skip first */ 00451 b=strtok(NULL,":"); 00452 if (!b) { 00453 SUBDBG("Skipping first failed\n"); 00454 return PFM_ERR_UMASK; /* Must be this value!! */ 00455 } 00456 00457 while(b) { 00458 a=0; 00459 while(1) { 00460 00461 SUBDBG("get_event_attr %#x %d %p\n",current_event->libpfm4_idx,a,&ainfo); 00462 00463 memset(&ainfo,0,sizeof(pfm_event_attr_info_t)); 00464 00465 ret = pfm_get_event_attr_info(current_event->libpfm4_idx, a, 00466 PFM_OS_PERF_EVENT, &ainfo); 00467 00468 if (ret != PFM_SUCCESS) { 00469 SUBDBG("get_event_attr failed %s\n",pfm_strerror(ret)); 00470 return ret; 00471 } 00472 00473 SUBDBG("Trying %s with %s\n",ainfo.name,b); 00474 00475 if (ainfo.type == PFM_ATTR_MOD_BOOL) { 00476 sprintf(temp_string,"%s=0",ainfo.name); 00477 if (!strcasecmp(temp_string, b)) { 00478 SUBDBG("Found %s %d\n",b,a); 00479 if (a>max) max=a; 00480 goto found_attr; 00481 } 00482 } 00483 else if (ainfo.type == PFM_ATTR_MOD_INTEGER) { 00484 sprintf(temp_string,"%s=0",ainfo.name); 00485 if (!strcasecmp(temp_string, b)) { 00486 SUBDBG("Found %s %d\n",b,a); 00487 if (a>max) max=a; 00488 goto found_attr; 00489 } 00490 } 00491 else { 00492 if (!strcasecmp(ainfo.name, b)) { 00493 SUBDBG("Found %s %d\n",b,a); 00494 if (a>max) max=a; 00495 goto found_attr; 00496 } 00497 } 00498 a++; 00499 } 00500 00501 SUBDBG("attr=%s not found for event %s\n", b, info.name); 00502 00503 return PFM_ERR_ATTR; 00504 00505 found_attr: 00506 00507 b=strtok(NULL,":"); 00508 } 00509 00510 SUBDBG("Found max %d\n", max); 00511 00512 return max; 00513 } 00514 00515 00516 00525 static int 00526 get_event_first_active(int pmu_type) 00527 { 00528 int pidx, pmu_idx, ret; 00529 00530 pfm_pmu_info_t pinfo; 00531 00532 pmu_idx=0; 00533 00534 while(pmu_idx<PFM_PMU_MAX) { 00535 00536 /* clear the PMU structure (required by libpfm4) */ 00537 memset(&pinfo,0,sizeof(pfm_pmu_info_t)); 00538 ret=pfm_get_pmu_info(pmu_idx, &pinfo); 00539 00540 if ((ret==PFM_SUCCESS) && pmu_is_present_and_right_type(&pinfo,pmu_type)) { 00541 00542 pidx=pinfo.first_event; 00543 00544 SUBDBG("First event in %s is %d\n",pinfo.name,pidx); 00545 00546 if (pidx<0) { 00547 /* For some reason no events available */ 00548 /* despite the PMU being active. */ 00549 /* This can happen, for example with ix86arch */ 00550 /* inside of VMware */ 00551 } 00552 else { 00553 return pidx; 00554 } 00555 } 00556 00557 pmu_idx++; 00558 00559 } 00560 00561 return PAPI_ENOEVNT; 00562 00563 } 00564 00565 00566 00581 static int 00582 convert_libpfm4_to_string( int code, char **event_name) 00583 { 00584 00585 int ret; 00586 pfm_event_info_t gete; 00587 pfm_pmu_info_t pinfo; 00588 char name[BUFSIZ]; 00589 00590 SUBDBG("ENTER %#x\n",code); 00591 00592 /* Clear structures, as wanted by libpfm4 */ 00593 memset( &gete, 0, sizeof (pfm_event_info_t) ); 00594 00595 ret=pfm_get_event_info(code, PFM_OS_PERF_EVENT, &gete); 00596 if (ret!=PFM_SUCCESS) { 00597 return ret; 00598 } 00599 00600 memset( &pinfo, 0, sizeof(pfm_pmu_info_t) ); 00601 ret=pfm_get_pmu_info(gete.pmu, &pinfo); 00602 if (ret!=PFM_SUCCESS) { 00603 return ret; 00604 } 00605 00606 sprintf(name,"%s::%s",pinfo.name,gete.name); 00607 *event_name=strdup(name); 00608 00609 SUBDBG("Found name: %s\n",*event_name); 00610 00611 return PFM_SUCCESS; 00612 00613 } 00614 00615 00630 static int convert_pfmidx_to_native(int code, unsigned int *PapiEventCode, 00631 struct native_event_table_t *event_table) { 00632 00633 int ret; 00634 char *name=NULL; 00635 00636 ret=convert_libpfm4_to_string( code, &name); 00637 if (ret!=PFM_SUCCESS) { 00638 return _papi_libpfm4_error(ret); 00639 } 00640 00641 SUBDBG("Converted %#x to %s\n",code,name); 00642 00643 ret=_peu_libpfm4_ntv_name_to_code(name,PapiEventCode,event_table); 00644 00645 SUBDBG("Converted %s to event %#x\n",name,*PapiEventCode); 00646 00647 if (name) free(name); 00648 00649 return ret; 00650 00651 } 00652 00653 00672 static int find_next_umask(struct native_event_t *current_event, 00673 int current,char *umask_name) { 00674 00675 char temp_string[BUFSIZ]; 00676 pfm_event_info_t event_info; 00677 pfm_event_attr_info_t ainfo; 00678 int num_masks=0; 00679 pfm_err_t ret; 00680 int i; 00681 00682 /* get number of attributes */ 00683 00684 memset(&event_info, 0, sizeof(event_info)); 00685 ret=pfm_get_event_info(current_event->libpfm4_idx, 00686 PFM_OS_PERF_EVENT, &event_info); 00687 if (ret!=PFM_SUCCESS) { 00688 return ret; 00689 } 00690 00691 SUBDBG("%d possible attributes for event %s\n", 00692 event_info.nattrs, 00693 event_info.name); 00694 00695 pfm_for_each_event_attr(i, &event_info) { 00696 00697 ainfo.size = sizeof(ainfo); 00698 00699 ret = pfm_get_event_attr_info(event_info.idx, i, PFM_OS_PERF_EVENT, 00700 &ainfo); 00701 if (ret != PFM_SUCCESS) { 00702 SUBDBG("Not found\n"); 00703 return PFM_ERR_NOTFOUND; 00704 } 00705 00706 if (ainfo.type == PFM_ATTR_UMASK) { 00707 SUBDBG("nm %d looking for %d\n",num_masks,current); 00708 if (num_masks==current+1) { 00709 SUBDBG("Found attribute %d: %s type: %d\n", 00710 i,ainfo.name,ainfo.type); 00711 00712 sprintf(temp_string,"%s",ainfo.name); 00713 strncpy(umask_name,temp_string,BUFSIZ); 00714 00715 return current+1; 00716 } 00717 num_masks++; 00718 } 00719 00720 if (ainfo.type == PFM_ATTR_MOD_BOOL) { 00721 SUBDBG("nm %d looking for %d\n",num_masks,current); 00722 00723 if (num_masks==current+1) { 00724 SUBDBG("Found attribute %d: %s type: %d\n", 00725 i,ainfo.name,ainfo.type); 00726 00727 sprintf(temp_string,"%s=0",ainfo.name); 00728 strncpy(umask_name,temp_string,BUFSIZ); 00729 00730 return current+1; 00731 } 00732 num_masks++; 00733 } 00734 00735 if (ainfo.type == PFM_ATTR_MOD_INTEGER) { 00736 SUBDBG("nm %d looking for %d\n",num_masks,current); 00737 if (num_masks==current+1) { 00738 SUBDBG("Found attribute %d: %s type: %d\n", 00739 i,ainfo.name,ainfo.type); 00740 00741 sprintf(temp_string,"%s=0",ainfo.name); 00742 strncpy(umask_name,temp_string,BUFSIZ); 00743 00744 return current+1; 00745 } 00746 num_masks++; 00747 } 00748 } 00749 00750 return PFM_ERR_ATTR; 00751 00752 } 00753 00754 00755 00756 /***********************************************************/ 00757 /* Exported functions */ 00758 /***********************************************************/ 00759 00774 int 00775 _peu_libpfm4_ntv_name_to_code( char *name, unsigned int *event_code, 00776 struct native_event_table_t *event_table) 00777 { 00778 00779 int actual_idx; 00780 struct native_event_t *our_event; 00781 int event_num; 00782 00783 SUBDBG( "Converting %s\n", name); 00784 00785 event_num=find_existing_event(name,event_table); 00786 00787 if (event_num<0) { 00788 00789 /* event currently doesn't exist, so try to find it */ 00790 /* using libpfm4 */ 00791 00792 SUBDBG("Using pfm to look up event %s\n",name); 00793 00794 actual_idx=find_event(name, event_table->pmu_type); 00795 if (actual_idx<0) { 00796 return _papi_libpfm4_error(actual_idx); 00797 } 00798 00799 SUBDBG("Using %#x as the index\n",actual_idx); 00800 00801 /* We were found in libpfm4, so allocate our copy of the event */ 00802 00803 our_event=allocate_native_event(name,actual_idx,event_table); 00804 if (our_event==NULL) return PAPI_ENOEVNT; 00805 00806 event_num=find_existing_event(name,event_table); 00807 } 00808 00809 if (event_num>=0) { 00810 *event_code=event_num; 00811 SUBDBG("Found code: %#x\n",*event_code); 00812 return PAPI_OK; 00813 } 00814 00815 /* Failure here means allocate_native_event failed */ 00816 00817 SUBDBG("Event %s not found\n",name); 00818 00819 return PAPI_ENOEVNT; 00820 00821 } 00822 00823 00841 int 00842 _peu_libpfm4_ntv_code_to_name(unsigned int EventCode, 00843 char *ntv_name, int len, 00844 struct native_event_table_t *event_table) 00845 { 00846 00847 struct native_event_t *our_event; 00848 00849 SUBDBG("ENTER %#x\n",EventCode); 00850 00851 our_event=find_existing_event_by_number(EventCode,event_table); 00852 if (our_event==NULL) { 00853 return PAPI_ENOEVNT; 00854 } 00855 00856 strncpy(ntv_name,our_event->allocated_name,len); 00857 00858 if (strlen(our_event->allocated_name) > (unsigned)len) { 00859 return PAPI_EBUF; 00860 } 00861 00862 return PAPI_OK; 00863 } 00864 00865 00888 int 00889 _peu_libpfm4_ntv_code_to_descr( unsigned int EventCode, 00890 char *ntv_descr, int len, 00891 struct native_event_table_t *event_table) 00892 { 00893 int ret,a,first_mask=1; 00894 char *eventd, *tmp=NULL; 00895 pfm_event_info_t gete; 00896 00897 pfm_event_attr_info_t ainfo; 00898 char *b; 00899 char event_string[BUFSIZ],*ptr; 00900 char temp_string[BUFSIZ]; 00901 00902 struct native_event_t *our_event; 00903 00904 SUBDBG("ENTER %#x\n",EventCode); 00905 00906 our_event=find_existing_event_by_number(EventCode,event_table); 00907 if (our_event==NULL) { 00908 return PAPI_ENOEVNT; 00909 } 00910 00911 SUBDBG("Getting info on %#x\n",our_event->libpfm4_idx); 00912 00913 /* libpfm requires the structure be zeroed */ 00914 memset( &gete, 0, sizeof ( gete ) ); 00915 00916 ret=pfm_get_event_info(our_event->libpfm4_idx, PFM_OS_PERF_EVENT, &gete); 00917 if (ret<0) { 00918 SUBDBG("Return=%d\n",ret); 00919 return _papi_libpfm4_error(ret); 00920 } 00921 00922 eventd=strdup(gete.desc); 00923 00924 tmp = ( char * ) malloc( strlen( eventd ) + 1 ); 00925 if ( tmp == NULL ) { 00926 free( eventd ); 00927 return PAPI_ENOMEM; 00928 } 00929 00930 tmp[0] = '\0'; 00931 strcat( tmp, eventd ); 00932 free( eventd ); 00933 00934 /* Handle Umasks */ 00935 00936 /* attributes concactinated onto end of descr separated by ", masks" */ 00937 /* then comma separated */ 00938 00939 strcpy(event_string,our_event->allocated_name); 00940 00941 /* Point to first umask */ 00942 00943 /* Skip the pmu name :: if one exists */ 00944 if (strstr(event_string,"::")) { 00945 ptr=strstr(event_string,"::"); 00946 ptr+=2; 00947 b=strtok(ptr,":"); 00948 } 00949 else { 00950 b=strtok(event_string,":"); 00951 } 00952 00953 /* if no umask, then done */ 00954 if (!b) { 00955 SUBDBG("No colon!\n"); /* no umask */ 00956 goto descr_in_tmp; 00957 } 00958 00959 /* skip first */ 00960 b=strtok(NULL,":"); 00961 if (!b) { 00962 SUBDBG("Skipping first failed\n"); 00963 goto descr_in_tmp; 00964 } 00965 00966 /* loop through all umasks, seeing which match */ 00967 while(b) { 00968 a=0; 00969 while(1) { 00970 00971 SUBDBG("get_event_attr %#x %p\n",our_event->libpfm4_idx,&ainfo); 00972 00973 memset(&ainfo,0,sizeof(pfm_event_attr_info_t)); 00974 00975 ret = pfm_get_event_attr_info(our_event->libpfm4_idx, a, 00976 PFM_OS_PERF_EVENT, &ainfo); 00977 if (ret != PFM_SUCCESS) { 00978 free( tmp ); 00979 SUBDBG("get_event_attr failed %s\n",pfm_strerror(ret)); 00980 return _papi_libpfm4_error(ret); 00981 } 00982 00983 /* Plain UMASK case */ 00984 if (ainfo.type == PFM_ATTR_UMASK) { 00985 00986 SUBDBG("Trying %s with %s\n",ainfo.name,b); 00987 00988 if (!strcasecmp(ainfo.name, b)) { 00989 int new_length; 00990 00991 SUBDBG("Found %s\n",b); 00992 new_length=strlen(ainfo.desc); 00993 00994 if (first_mask) { 00995 tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(", masks:")); 00996 strcat(tmp,", masks:"); 00997 first_mask=0; 00998 } 00999 else { 01000 tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(",")); 01001 strcat(tmp,","); 01002 } 01003 strcat(tmp,ainfo.desc); 01004 01005 goto found_attr; 01006 } 01007 } 01008 01009 /* Boolean Case */ 01010 if (ainfo.type == PFM_ATTR_MOD_BOOL) { 01011 01012 sprintf(temp_string,"%s=0",ainfo.name); 01013 01014 SUBDBG("Trying %s with %s\n",temp_string,b); 01015 01016 if (!strcasecmp(temp_string, b)) { 01017 int new_length; 01018 01019 SUBDBG("Found %s\n",b); 01020 new_length=strlen(ainfo.desc); 01021 01022 if (first_mask) { 01023 tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(", masks:")); 01024 strcat(tmp,", masks:"); 01025 first_mask=0; 01026 } 01027 else { 01028 tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(",")); 01029 strcat(tmp,","); 01030 } 01031 strcat(tmp,ainfo.desc); 01032 01033 goto found_attr; 01034 } 01035 } 01036 01037 /* Integer Case */ 01038 if (ainfo.type == PFM_ATTR_MOD_INTEGER) { 01039 01040 sprintf(temp_string,"%s=0",ainfo.name); 01041 01042 SUBDBG("Trying %s with %s\n",temp_string,b); 01043 01044 if (!strcasecmp(temp_string, b)) { 01045 int new_length; 01046 01047 SUBDBG("Found %s\n",b); 01048 new_length=strlen(ainfo.desc); 01049 01050 if (first_mask) { 01051 tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(", masks:")); 01052 strcat(tmp,", masks:"); 01053 first_mask=0; 01054 } 01055 else { 01056 tmp=realloc(tmp,strlen(tmp)+new_length+1+strlen(",")); 01057 strcat(tmp,","); 01058 } 01059 strcat(tmp,ainfo.desc); 01060 01061 goto found_attr; 01062 } 01063 } 01064 01065 a++; 01066 } 01067 01068 SUBDBG("attr=%s not found for event %s\n", b, ainfo.name); 01069 01070 return PAPI_EATTR; 01071 01072 found_attr: 01073 01074 b=strtok(NULL,":"); 01075 } 01076 01077 /* We are done and the description to copy is in tmp */ 01078 descr_in_tmp: 01079 strncpy( ntv_descr, tmp, ( size_t ) len ); 01080 if ( ( int ) strlen( tmp ) > len - 1 ) 01081 ret = PAPI_EBUF; 01082 else 01083 ret = PAPI_OK; 01084 free( tmp ); 01085 01086 SUBDBG("PFM4 Code: %#x %s\n",EventCode,ntv_descr); 01087 01088 return ret; 01089 } 01090 01091 01092 int 01093 _peu_libpfm4_ntv_code_to_info(unsigned int EventCode, 01094 PAPI_event_info_t *info, 01095 struct native_event_table_t *event_table) 01096 { 01097 01098 01099 struct native_event_t *our_event; 01100 01101 SUBDBG("ENTER %#x\n",EventCode); 01102 01103 our_event=find_existing_event_by_number(EventCode,event_table); 01104 if (our_event==NULL) { 01105 return PAPI_ENOEVNT; 01106 } 01107 01108 strncpy(info->symbol, our_event->allocated_name, sizeof(info->symbol)); 01109 01110 if (strlen(our_event->allocated_name) > sizeof(info->symbol)) { 01111 return PAPI_EBUF; 01112 } 01113 01114 _peu_libpfm4_ntv_code_to_descr(EventCode,info->long_descr, 01115 sizeof(info->long_descr),event_table); 01116 01117 return PAPI_OK; 01118 } 01119 01120 01121 01138 int 01139 _peu_libpfm4_ntv_enum_events( unsigned int *PapiEventCode, 01140 int modifier, 01141 struct native_event_table_t *event_table) { 01142 01143 int code,ret; 01144 struct native_event_t *current_event; 01145 01146 SUBDBG("ENTER\n"); 01147 01148 /* return first event if so specified */ 01149 if ( modifier == PAPI_ENUM_FIRST ) { 01150 01151 unsigned int papi_event=0; 01152 01153 SUBDBG("ENUM_FIRST\n"); 01154 01155 code=get_event_first_active(event_table->pmu_type); 01156 SUBDBG("ENUM_FIRST code: %d\n",code); 01157 if (code < 0 ) { 01158 return code; 01159 } 01160 01161 /* convert the libpfm4 event to a PAPI event */ 01162 ret=convert_pfmidx_to_native(code, &papi_event,event_table); 01163 01164 *PapiEventCode=(unsigned int)papi_event; 01165 01166 SUBDBG("FOUND %#x (from %#x) ret=%d\n",*PapiEventCode,code,ret); 01167 01168 return ret; 01169 } 01170 01171 /* If we get this far, we're looking for a */ 01172 /* next-event. So gather info on the current one */ 01173 current_event=find_existing_event_by_number(*PapiEventCode, 01174 event_table); 01175 if (current_event==NULL) { 01176 SUBDBG("EVENTS %#x not found\n",*PapiEventCode); 01177 return PAPI_ENOEVNT; 01178 } 01179 01180 01181 /* Handle looking for the next event */ 01182 01183 if ( modifier == PAPI_ENUM_EVENTS ) { 01184 01185 unsigned int papi_event=0; 01186 01187 SUBDBG("PAPI_ENUM_EVENTS %#x\n",*PapiEventCode); 01188 01189 code=current_event->libpfm4_idx; 01190 01191 ret=find_next_no_aliases(code,event_table->pmu_type); 01192 SUBDBG("find_next_no_aliases() Returned %#x\n",ret); 01193 if (ret<0) { 01194 return ret; 01195 } 01196 01197 /* Convert libpfm4 event code to PAPI event code */ 01198 ret=convert_pfmidx_to_native(ret, &papi_event, event_table); 01199 if (ret<0) { 01200 SUBDBG("Couldn't convert to native %d %s\n", 01201 ret,PAPI_strerror(ret)); 01202 return ret; 01203 } 01204 01205 *PapiEventCode=(unsigned int)papi_event; 01206 01207 SUBDBG("Returning PAPI_OK\n"); 01208 01209 return ret; 01210 } 01211 01212 /* We don't handle PAPI_NTV_ENUM_UMASK_COMBOS */ 01213 if ( modifier == PAPI_NTV_ENUM_UMASK_COMBOS ) { 01214 return PAPI_ENOIMPL; 01215 } 01216 01217 /* Enumerate PAPI_NTV_ENUM_UMASKS (umasks on an event) */ 01218 if ( modifier == PAPI_NTV_ENUM_UMASKS ) { 01219 01220 int max_umask,next_umask; 01221 char umask_string[BUFSIZ],new_name[BUFSIZ]; 01222 01223 SUBDBG("Finding maximum mask in event %s\n", 01224 current_event->allocated_name); 01225 01226 max_umask=find_max_umask(current_event); 01227 SUBDBG("Found max %d\n",max_umask); 01228 01229 if (max_umask<0) { 01230 if (max_umask==PFM_ERR_UMASK) { 01231 max_umask=-1; /* needed for find_next_umask() to work */ 01232 /* indicates the event as passed had no */ 01233 /* umask in it. */ 01234 } 01235 else { 01236 return _papi_libpfm4_error(max_umask); 01237 } 01238 } 01239 01240 next_umask=find_next_umask(current_event,max_umask, 01241 umask_string); 01242 01243 SUBDBG("Found next %d\n",next_umask); 01244 01245 if (next_umask>=0) { 01246 01247 unsigned int papi_event; 01248 01249 sprintf(new_name,"%s:%s",current_event->base_name, 01250 umask_string); 01251 01252 SUBDBG("Found new name %s\n",new_name); 01253 01254 ret=_peu_libpfm4_ntv_name_to_code(new_name,&papi_event, 01255 event_table); 01256 if (ret!=PAPI_OK) { 01257 return PAPI_ENOEVNT; 01258 } 01259 01260 *PapiEventCode=(unsigned int)papi_event; 01261 SUBDBG("found code %#x\n",*PapiEventCode); 01262 01263 return PAPI_OK; 01264 } 01265 01266 SUBDBG("couldn't find umask\n"); 01267 01268 return _papi_libpfm4_error(next_umask); 01269 01270 } 01271 01272 /* An unknown enumeration method was indicated */ 01273 01274 return PAPI_ENOIMPL; 01275 } 01276 01287 int 01288 _peu_libpfm4_shutdown(struct native_event_table_t *event_table) { 01289 01290 int i; 01291 01292 APIDBG("Entry\n"); 01293 01294 /* clean out and free the native events structure */ 01295 _papi_hwi_lock( NAMELIB_LOCK ); 01296 01297 /* Only free if we're the last user */ 01298 01299 /* free memory allocated with strdup */ 01300 for( i=0; i<event_table->num_native_events; i++) { 01301 free(event_table->native_events[i].base_name); 01302 free(event_table->native_events[i].pmu_plus_name); 01303 free(event_table->native_events[i].pmu); 01304 free(event_table->native_events[i].allocated_name); 01305 } 01306 01307 memset(event_table->native_events,0, 01308 sizeof(struct native_event_t)*event_table->allocated_native_events); 01309 event_table->num_native_events=0; 01310 event_table->allocated_native_events=0; 01311 free(event_table->native_events); 01312 01313 _papi_hwi_unlock( NAMELIB_LOCK ); 01314 01315 return PAPI_OK; 01316 } 01317 01329 int 01330 _peu_libpfm4_init(papi_vector_t *my_vector, 01331 struct native_event_table_t *event_table, 01332 int pmu_type) { 01333 01334 int detected_pmus=0; 01335 int i; 01336 pfm_err_t retval = PFM_SUCCESS; 01337 unsigned int ncnt; 01338 pfm_pmu_info_t pinfo; 01339 01340 /* allocate the native event structure */ 01341 01342 event_table->num_native_events=0; 01343 event_table->pmu_type=pmu_type; 01344 01345 event_table->native_events=calloc(NATIVE_EVENT_CHUNK, 01346 sizeof(struct native_event_t)); 01347 if (event_table->native_events==NULL) { 01348 return PAPI_ENOMEM; 01349 } 01350 event_table->allocated_native_events=NATIVE_EVENT_CHUNK; 01351 01352 /* Count number of present PMUs */ 01353 detected_pmus=0; 01354 ncnt=0; 01355 01356 my_vector->cmp_info.num_cntrs=0; 01357 01358 SUBDBG("Detected pmus:\n"); 01359 for(i=0;i<PFM_PMU_MAX;i++) { 01360 memset(&pinfo,0,sizeof(pfm_pmu_info_t)); 01361 retval=pfm_get_pmu_info(i, &pinfo); 01362 if (retval!=PFM_SUCCESS) { 01363 continue; 01364 } 01365 01366 if (pmu_is_present_and_right_type(&pinfo,pmu_type)) { 01367 SUBDBG("\t%d %s %s %d\n",i,pinfo.name,pinfo.desc,pinfo.type); 01368 01369 detected_pmus++; 01370 ncnt+=pinfo.nevents; 01371 01372 my_vector->cmp_info.num_cntrs += pinfo.num_cntrs+ 01373 pinfo.num_fixed_cntrs; 01374 } 01375 } 01376 SUBDBG("%d native events detected on %d pmus\n",ncnt,detected_pmus); 01377 01378 my_vector->cmp_info.num_native_events = ncnt; 01379 01380 SUBDBG( "num_counters: %d\n", my_vector->cmp_info.num_cntrs ); 01381 01382 return PAPI_OK; 01383 } 01384 01385 01400 int 01401 _peu_libpfm4_setup_counters( struct perf_event_attr *attr, 01402 int event, 01403 struct native_event_table_t *event_table) { 01404 01405 struct native_event_t *our_event; 01406 01407 our_event=find_existing_event_by_number(event,event_table); 01408 if (our_event==NULL) { 01409 return PAPI_ENOEVNT; 01410 } 01411 01412 attr->config=our_event->config; 01413 attr->config1=our_event->config1; 01414 attr->config2=our_event->config2; 01415 attr->type=our_event->type; 01416 01417 SUBDBG( "pe_event: config 0x%"PRIx64 01418 " config1 0x%"PRIx64 01419 " type 0x%"PRIx32"\n", 01420 attr->config, 01421 attr->config1, 01422 attr->type); 01423 01424 return PAPI_OK; 01425 }