aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/pmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/pmu.c')
-rw-r--r--tools/perf/util/pmu.c87
1 files changed, 71 insertions, 16 deletions
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 80fb1593913a..57e38fdf0b34 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -12,6 +12,7 @@
12#include <dirent.h> 12#include <dirent.h>
13#include <api/fs/fs.h> 13#include <api/fs/fs.h>
14#include <locale.h> 14#include <locale.h>
15#include <regex.h>
15#include "util.h" 16#include "util.h"
16#include "pmu.h" 17#include "pmu.h"
17#include "parse-events.h" 18#include "parse-events.h"
@@ -537,17 +538,45 @@ static bool pmu_is_uncore(const char *name)
537} 538}
538 539
539/* 540/*
541 * PMU CORE devices have different name other than cpu in sysfs on some
542 * platforms. looking for possible sysfs files to identify as core device.
543 */
544static int is_pmu_core(const char *name)
545{
546 struct stat st;
547 char path[PATH_MAX];
548 const char *sysfs = sysfs__mountpoint();
549
550 if (!sysfs)
551 return 0;
552
553 /* Look for cpu sysfs (x86 and others) */
554 scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu", sysfs);
555 if ((stat(path, &st) == 0) &&
556 (strncmp(name, "cpu", strlen("cpu")) == 0))
557 return 1;
558
559 /* Look for cpu sysfs (specific to arm) */
560 scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s/cpus",
561 sysfs, name);
562 if (stat(path, &st) == 0)
563 return 1;
564
565 return 0;
566}
567
568/*
540 * Return the CPU id as a raw string. 569 * Return the CPU id as a raw string.
541 * 570 *
542 * Each architecture should provide a more precise id string that 571 * Each architecture should provide a more precise id string that
543 * can be use to match the architecture's "mapfile". 572 * can be use to match the architecture's "mapfile".
544 */ 573 */
545char * __weak get_cpuid_str(void) 574char * __weak get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
546{ 575{
547 return NULL; 576 return NULL;
548} 577}
549 578
550static char *perf_pmu__getcpuid(void) 579static char *perf_pmu__getcpuid(struct perf_pmu *pmu)
551{ 580{
552 char *cpuid; 581 char *cpuid;
553 static bool printed; 582 static bool printed;
@@ -556,7 +585,7 @@ static char *perf_pmu__getcpuid(void)
556 if (cpuid) 585 if (cpuid)
557 cpuid = strdup(cpuid); 586 cpuid = strdup(cpuid);
558 if (!cpuid) 587 if (!cpuid)
559 cpuid = get_cpuid_str(); 588 cpuid = get_cpuid_str(pmu);
560 if (!cpuid) 589 if (!cpuid)
561 return NULL; 590 return NULL;
562 591
@@ -567,22 +596,45 @@ static char *perf_pmu__getcpuid(void)
567 return cpuid; 596 return cpuid;
568} 597}
569 598
570struct pmu_events_map *perf_pmu__find_map(void) 599struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu)
571{ 600{
572 struct pmu_events_map *map; 601 struct pmu_events_map *map;
573 char *cpuid = perf_pmu__getcpuid(); 602 char *cpuid = perf_pmu__getcpuid(pmu);
574 int i; 603 int i;
575 604
605 /* on some platforms which uses cpus map, cpuid can be NULL for
606 * PMUs other than CORE PMUs.
607 */
608 if (!cpuid)
609 return NULL;
610
576 i = 0; 611 i = 0;
577 for (;;) { 612 for (;;) {
613 regex_t re;
614 regmatch_t pmatch[1];
615 int match;
616
578 map = &pmu_events_map[i++]; 617 map = &pmu_events_map[i++];
579 if (!map->table) { 618 if (!map->table) {
580 map = NULL; 619 map = NULL;
581 break; 620 break;
582 } 621 }
583 622
584 if (!strcmp(map->cpuid, cpuid)) 623 if (regcomp(&re, map->cpuid, REG_EXTENDED) != 0) {
624 /* Warn unable to generate match particular string. */
625 pr_info("Invalid regular expression %s\n", map->cpuid);
585 break; 626 break;
627 }
628
629 match = !regexec(&re, cpuid, 1, pmatch, 0);
630 regfree(&re);
631 if (match) {
632 size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
633
634 /* Verify the entire string matched. */
635 if (match_len == strlen(cpuid))
636 break;
637 }
586 } 638 }
587 free(cpuid); 639 free(cpuid);
588 return map; 640 return map;
@@ -593,13 +645,14 @@ struct pmu_events_map *perf_pmu__find_map(void)
593 * to the current running CPU. Then, add all PMU events from that table 645 * to the current running CPU. Then, add all PMU events from that table
594 * as aliases. 646 * as aliases.
595 */ 647 */
596static void pmu_add_cpu_aliases(struct list_head *head, const char *name) 648static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
597{ 649{
598 int i; 650 int i;
599 struct pmu_events_map *map; 651 struct pmu_events_map *map;
600 struct pmu_event *pe; 652 struct pmu_event *pe;
653 const char *name = pmu->name;
601 654
602 map = perf_pmu__find_map(); 655 map = perf_pmu__find_map(pmu);
603 if (!map) 656 if (!map)
604 return; 657 return;
605 658
@@ -608,7 +661,6 @@ static void pmu_add_cpu_aliases(struct list_head *head, const char *name)
608 */ 661 */
609 i = 0; 662 i = 0;
610 while (1) { 663 while (1) {
611 const char *pname;
612 664
613 pe = &map->table[i++]; 665 pe = &map->table[i++];
614 if (!pe->name) { 666 if (!pe->name) {
@@ -617,9 +669,13 @@ static void pmu_add_cpu_aliases(struct list_head *head, const char *name)
617 break; 669 break;
618 } 670 }
619 671
620 pname = pe->pmu ? pe->pmu : "cpu"; 672 if (!is_pmu_core(name)) {
621 if (strncmp(pname, name, strlen(pname))) 673 /* check for uncore devices */
622 continue; 674 if (pe->pmu == NULL)
675 continue;
676 if (strncmp(pe->pmu, name, strlen(pe->pmu)))
677 continue;
678 }
623 679
624 /* need type casts to override 'const' */ 680 /* need type casts to override 'const' */
625 __perf_pmu__new_alias(head, NULL, (char *)pe->name, 681 __perf_pmu__new_alias(head, NULL, (char *)pe->name,
@@ -661,21 +717,20 @@ static struct perf_pmu *pmu_lookup(const char *name)
661 if (pmu_aliases(name, &aliases)) 717 if (pmu_aliases(name, &aliases))
662 return NULL; 718 return NULL;
663 719
664 pmu_add_cpu_aliases(&aliases, name);
665 pmu = zalloc(sizeof(*pmu)); 720 pmu = zalloc(sizeof(*pmu));
666 if (!pmu) 721 if (!pmu)
667 return NULL; 722 return NULL;
668 723
669 pmu->cpus = pmu_cpumask(name); 724 pmu->cpus = pmu_cpumask(name);
670 725 pmu->name = strdup(name);
726 pmu->type = type;
671 pmu->is_uncore = pmu_is_uncore(name); 727 pmu->is_uncore = pmu_is_uncore(name);
728 pmu_add_cpu_aliases(&aliases, pmu);
672 729
673 INIT_LIST_HEAD(&pmu->format); 730 INIT_LIST_HEAD(&pmu->format);
674 INIT_LIST_HEAD(&pmu->aliases); 731 INIT_LIST_HEAD(&pmu->aliases);
675 list_splice(&format, &pmu->format); 732 list_splice(&format, &pmu->format);
676 list_splice(&aliases, &pmu->aliases); 733 list_splice(&aliases, &pmu->aliases);
677 pmu->name = strdup(name);
678 pmu->type = type;
679 list_add_tail(&pmu->list, &pmus); 734 list_add_tail(&pmu->list, &pmus);
680 735
681 pmu->default_config = perf_pmu__get_default_config(pmu); 736 pmu->default_config = perf_pmu__get_default_config(pmu);