if (!strncmp(name, "uncore_", 7) &&
                            strncmp($1, "uncore_", 7))
                                name += 7;
-                       if (!fnmatch(pattern, name, 0)) {
+                       if (!perf_pmu__match(pattern, name, $1)) {
                                if (parse_events_copy_term_list(orig_terms, &terms))
                                        CLEANUP_YYABORT;
                                if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true, false))
 
 #include <linux/compiler.h>
 #include <linux/string.h>
 #include <linux/zalloc.h>
+#include <linux/ctype.h>
 #include <subcmd/pager.h>
 #include <sys/types.h>
 #include <errno.h>
 #include <locale.h>
 #include <regex.h>
 #include <perf/cpumap.h>
+#include <fnmatch.h>
 #include "debug.h"
 #include "evsel.h"
 #include "pmu.h"
        return perf_pmu__find_map(NULL);
 }
 
+static bool perf_pmu__valid_suffix(char *pmu_name, char *tok)
+{
+       char *p;
+
+       if (strncmp(pmu_name, tok, strlen(tok)))
+               return false;
+
+       p = pmu_name + strlen(tok);
+       if (*p == 0)
+               return true;
+
+       if (*p != '_')
+               return false;
+
+       ++p;
+       if (*p == 0 || !isdigit(*p))
+               return false;
+
+       return true;
+}
+
 bool pmu_uncore_alias_match(const char *pmu_name, const char *name)
 {
        char *tmp = NULL, *tok, *str;
         */
        for (; tok; name += strlen(tok), tok = strtok_r(NULL, ",", &tmp)) {
                name = strstr(name, tok);
-               if (!name) {
+               if (!name || !perf_pmu__valid_suffix((char *)name, tok)) {
                        res = false;
                        goto out;
                }
 
        return !list_empty(&perf_pmu__hybrid_pmus);
 }
+
+int perf_pmu__match(char *pattern, char *name, char *tok)
+{
+       if (fnmatch(pattern, name, 0))
+               return -1;
+
+       if (tok && !perf_pmu__valid_suffix(name, tok))
+               return -1;
+
+       return 0;
+}