For AMD64 there are revision ranges available for each event and mask. This patch adds a revision check. Now, unsupported events and masks are no longer reported. The functions pfm_amd64_get_event_name() and pfm_amd64_get_event_mask_name() return a NULL pointer instead of the name. Generic libpfm functions ignore those unsupported events or masks and pfm_get_event_mask_name() and pfm_get_event_mask_name() return PFMLIB_ERR_BADHOST in this case.
Signed-off-by: Robert Richter <robert.rich...@amd.com> --- lib/pfmlib_amd64.c | 33 ++++++++++++++++++++++++-- lib/pfmlib_amd64_priv.h | 1 + lib/pfmlib_common.c | 58 ++++++++++++++++++++++++++++++---------------- 3 files changed, 69 insertions(+), 23 deletions(-) diff --git a/lib/pfmlib_amd64.c b/lib/pfmlib_amd64.c index d2198bd..97259c7 100644 --- a/lib/pfmlib_amd64.c +++ b/lib/pfmlib_amd64.c @@ -86,6 +86,13 @@ static struct { pme_amd64_entry_t *events; } amd64_pmu; +pme_amd64_entry_t unsupported_event = { + .pme_name = "<unsupported>", + .pme_desc = "This event is not supported be this cpu revision.", + .pme_code = ~0, + .pme_flags = PFMLIB_AMD64_NOT_SUPP, +}; + pfm_pmu_support_t amd64_support; #define amd64_revision amd64_pmu.revision @@ -303,10 +310,24 @@ is_valid_rev(unsigned int flags, int revision) static inline pme_amd64_entry_t *pfm_amd64_get_event_entry(unsigned int index) { + /* + * Since there are no NULL pointer checks for the return + * value, &unsupported_event is returned instead. Function + * is_valid_index() may be used to validate the index. + */ + pme_amd64_entry_t *event; if (index >= amd64_event_count) - return NULL; + return &unsupported_event; + event = &amd64_events[index]; + if (!is_valid_rev(event->pme_flags, amd64_revision)) + return &unsupported_event; + return event; +} - return &amd64_events[index]; +static inline int +is_valid_index(unsigned int index) +{ + return (pfm_amd64_get_event_entry(index) != &unsupported_event); } /* @@ -641,6 +662,8 @@ pfm_amd64_get_hw_counter_width(unsigned int *width) static char * pfm_amd64_get_event_name(unsigned int i) { + if (!is_valid_index(i)) + return NULL; return pfm_amd64_get_event_entry(i)->pme_name; } @@ -660,7 +683,11 @@ pfm_amd64_get_event_desc(unsigned int ev, char **str) static char * pfm_amd64_get_event_mask_name(unsigned int ev, unsigned int midx) { - return pfm_amd64_get_event_entry(ev)->pme_umasks[midx].pme_uname; + pme_amd64_umask_t *umask; + umask = &pfm_amd64_get_event_entry(ev)->pme_umasks[midx]; + if (!is_valid_rev(umask->pme_uflags, amd64_revision)) + return NULL; + return umask->pme_uname; } static int diff --git a/lib/pfmlib_amd64_priv.h b/lib/pfmlib_amd64_priv.h index bda2dd9..148b5a2 100644 --- a/lib/pfmlib_amd64_priv.h +++ b/lib/pfmlib_amd64_priv.h @@ -94,6 +94,7 @@ static const char *amd64_cpu_strs[] = { #define PFMLIB_AMD64_UMASK_COMBO 0x1 /* unit mask can be combined */ #define PFMLIB_AMD64_FROM_REV(rev) ((rev)<<8) #define PFMLIB_AMD64_TILL_REV(rev) ((rev)<<16) +#define PFMLIB_AMD64_NOT_SUPP 0x1ff00 #define PFMLIB_AMD64_K8_REV_D PFMLIB_AMD64_FROM_REV(AMD64_K8_REV_D) #define PFMLIB_AMD64_K8_REV_E PFMLIB_AMD64_FROM_REV(AMD64_K8_REV_E) #define PFMLIB_AMD64_K8_REV_F PFMLIB_AMD64_FROM_REV(AMD64_K8_REV_F) diff --git a/lib/pfmlib_common.c b/lib/pfmlib_common.c index 8ca229d..6b9ff2a 100644 --- a/lib/pfmlib_common.c +++ b/lib/pfmlib_common.c @@ -333,6 +333,8 @@ pfm_find_event_byname(const char *n, unsigned int *idx) */ for(i=0; i < pfm_current->pme_count; i++) { e = pfm_current->get_event_name(i); + if (!e) + continue; if (!strncasecmp(e, n, len) && len == strlen(e)) goto found; @@ -435,13 +437,17 @@ pfm_do_find_event_mask(unsigned int ev, const char *str, unsigned int *mask_idx) unsigned int i, c, num_masks = 0; unsigned long mask_val = -1; char *endptr = NULL; + char *mask_name; num_masks = pfm_num_masks(ev); for (i = 0; i < num_masks; i++) { - if (!strcasecmp(pfm_current->get_event_mask_name(ev, i), str)) { - *mask_idx = i; - return PFMLIB_SUCCESS; - } + mask_name = pfm_current->get_event_mask_name(ev, i); + if (!mask_name) + continue; + if (strcasecmp(mask_name, str)) + continue; + *mask_idx = i; + return PFMLIB_SUCCESS; } /* don't give up yet; check for a exact numerical value */ mask_val = strtoul(str, &endptr, 0); @@ -557,6 +563,8 @@ pfm_get_event_name(unsigned int i, char *name, size_t maxlen) return PFMLIB_ERR_INVAL; str = pfm_current->get_event_name(i); + if (!str) + return PFMLIB_ERR_BADHOST; l = strlen(str); /* @@ -612,7 +620,7 @@ pfm_get_event_counters(unsigned int i, pfmlib_regmask_t *counters) int pfm_get_event_mask_name(unsigned int ev, unsigned int mask, char *name, size_t maxlen) { - char *n; + char *str; unsigned int num; size_t l, j; @@ -629,15 +637,14 @@ pfm_get_event_mask_name(unsigned int ev, unsigned int mask, char *name, size_t m if (mask >= num) return PFMLIB_ERR_INVAL; - n = pfm_current->get_event_mask_name(ev, mask); - if (n == NULL) - return PFMLIB_ERR_INVAL; - - l = strlen(n); + str = pfm_current->get_event_mask_name(ev, mask); + if (!str) + return PFMLIB_ERR_BADHOST; + l = strlen(str); if (l >= (maxlen-1)) return PFMLIB_ERR_FULL; - strcpy(name, n); + strcpy(name, str); /* * present nice uniform names @@ -887,6 +894,7 @@ pfm_get_max_event_name_len(size_t *len) { unsigned int i, j, num_masks; size_t max = 0, l; + char *str; if (PFMLIB_INITIALIZED() == 0) return PFMLIB_ERR_NOINIT; @@ -894,7 +902,10 @@ pfm_get_max_event_name_len(size_t *len) return PFMLIB_ERR_INVAL; for(i=0; i < pfm_current->pme_count; i++) { - l = strlen(pfm_current->get_event_name(i)); + str = pfm_current->get_event_name(i); + if (!str) + continue; + l = strlen(str); if (l > max) max = l; num_masks = pfm_num_masks(i); @@ -904,7 +915,10 @@ pfm_get_max_event_name_len(size_t *len) * which is inserted as the unit mask separator */ for (j = 0; j < num_masks; j++) { - l += 1 + strlen(pfm_current->get_event_mask_name(i, j)); + str = pfm_current->get_event_mask_name(i, j); + if (!str) + continue; + l += 1 + strlen(str); } if (l > max) max = l; } @@ -1001,7 +1015,7 @@ pfm_get_event_mask_code(unsigned int event_idx, unsigned int mask_idx, unsigned int pfm_get_full_event_name(pfmlib_event_t *e, char *name, size_t maxlen) { - char *n; + char *str; size_t l, j; int ret; @@ -1022,21 +1036,25 @@ pfm_get_full_event_name(pfmlib_event_t *e, char *name, size_t maxlen) */ *name = '\0'; - n = pfm_current->get_event_name(e->event); - l = strlen(n); + str = pfm_current->get_event_name(e->event); + if (!str) + return PFMLIB_ERR_BADHOST; + l = strlen(str); if (l > (maxlen-1)) return PFMLIB_ERR_FULL; - strcpy(name, n); + strcpy(name, str); maxlen -= l + 1; for(j=0; j < e->num_masks; j++) { - n = pfm_current->get_event_mask_name(e->event, e->unit_masks[j]); - l = strlen(n); + str = pfm_current->get_event_mask_name(e->event, e->unit_masks[j]); + if (!str) + continue; + l = strlen(str); if (l > (maxlen-1)) return PFMLIB_ERR_FULL; strcat(name, ":"); - strcat(name, n); + strcat(name, str); maxlen -= l + 1; } /* -- 1.6.1.2 ------------------------------------------------------------------------------ _______________________________________________ perfmon2-devel mailing list perfmon2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/perfmon2-devel