Adding support to parse non architectural event aliases for given cpu. These aliases will be provided as 'events' directory like architectural ones provided by kernel.
Signed-off-by: Jiri Olsa <jo...@redhat.com> Cc: Arnaldo Carvalho de Melo <a...@redhat.com> Cc: Namhyung Kim <namhy...@kernel.org> Cc: Corey Ashford <cjash...@linux.vnet.ibm.com> Cc: Frederic Weisbecker <fweis...@gmail.com> Cc: Ingo Molnar <mi...@elte.hu> Cc: Namhyung Kim <namhy...@kernel.org> Cc: Paul Mackerras <pau...@samba.org> Cc: Peter Zijlstra <a.p.zijls...@chello.nl> --- tools/perf/arch/x86/Makefile | 7 +++ tools/perf/arch/x86/util/pmu.c | 98 ++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/pmu.c | 18 +++++--- tools/perf/util/pmu.h | 4 ++ 4 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 tools/perf/arch/x86/util/pmu.c diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile index 815841c..c175f65 100644 --- a/tools/perf/arch/x86/Makefile +++ b/tools/perf/arch/x86/Makefile @@ -6,3 +6,10 @@ ifndef NO_LIBUNWIND LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o endif LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o +LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/pmu.o + +$(OUTPUT)$(OUTPUT)arch/$(ARCH)/util/pmu.o: $(OUTPUT)arch/$(ARCH)/util/pmu.c $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ + '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \ + '-DPREFIX="$(prefix_SQ)"' \ + $< diff --git a/tools/perf/arch/x86/util/pmu.c b/tools/perf/arch/x86/util/pmu.c new file mode 100644 index 0000000..0938c70 --- /dev/null +++ b/tools/perf/arch/x86/util/pmu.c @@ -0,0 +1,98 @@ + +#include <linux/compiler.h> +#include <linux/kernel.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include "pmu.h" +#include "util.h" +#include "sysfs.h" + +static int intel_aliases(struct list_head *head, unsigned model) +{ + struct stat st; + char path[PATH_MAX]; + const char *model_str; + + switch (model) { + case 42: + model_str = "SandyBridge"; + break; + default: + /* unknown model.. plenty to cover ;-) */ + return 0; + } + + /* try local one first */ + scnprintf(path, PATH_MAX, "./arch/x86/events/intel/%s/", model_str); + + if (stat(path, &st) < 0) { + scnprintf(path, PATH_MAX, "%s/%s/events/x86/intel/%s/", + PREFIX, PERF_EXEC_PATH, model_str); + + if (stat(path, &st) < 0) + return -1; + } + + if (pmu_aliases_parse(path, head)) + return -1; + + return 0; +} + +static int cpu_specs(unsigned *vendor, unsigned *model) +{ + FILE *file; + struct stat st; + char path[PATH_MAX]; + int ret = 0; + + scnprintf(path, PATH_MAX, "%s/devices/system/cpu/modalias", + sysfs_find_mountpoint()); + + if (stat(path, &st) < 0) + return -ENOENT; + + file = fopen(path, "r"); + if (!file) + return -errno; + + if (2 != fscanf(file, "x86cpu:vendor:%X:family:%*X:model:%X:", + vendor, model)) + ret = -1; + + fclose(file); + return ret; +} + +static int cpu_aliases(struct list_head *head) +{ + unsigned vendol, model; + int ret; + + ret = cpu_specs(&vendol, &model); + if (ret) { + pr_info("failed to get cpu aliases"); + return 0; + } + + switch (vendol) { + /* Intel */ + case 0: + return intel_aliases(head, model); + default: + /* unknown vendor.. plenty to cover ;-) */ + return 0; + } + + return 0; +} + +int arch_pmu_aliases(char *name, struct list_head *head) +{ + if (!strcmp(name, "cpu")) + return cpu_aliases(head); + + return 0; +} diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 9bdc60c..626d9d7 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -114,7 +114,7 @@ static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file) * Process all the sysfs attributes located under the directory * specified in 'dir' parameter. */ -static int pmu_aliases_parse(char *dir, struct list_head *head) +int pmu_aliases_parse(char *dir, struct list_head *head) { struct dirent *evt_ent; DIR *event_dir; @@ -146,6 +146,13 @@ static int pmu_aliases_parse(char *dir, struct list_head *head) return ret; } +__attribute__((weak)) +int arch_pmu_aliases(char *name __maybe_unused, + struct list_head *head __maybe_unused) +{ + return 0; +} + /* * Reading the pmu event aliases definition, which should be located at: * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes. @@ -163,13 +170,12 @@ static int pmu_aliases(char *name, struct list_head *head) snprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s/events", sysfs, name); - if (stat(path, &st) < 0) - return 0; /* no error if 'events' does not exist */ - - if (pmu_aliases_parse(path, head)) + /* no error if 'events' does not exist */ + if (!stat(path, &st) && + pmu_aliases_parse(path, head)) return -1; - return 0; + return arch_pmu_aliases(name, head); } static int pmu_alias_terms(struct perf_pmu__alias *alias, diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index a313ed7..62da834 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -53,5 +53,9 @@ int perf_pmu__format_parse(char *dir, struct list_head *head); struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); +int pmu_aliases_parse(char *dir, struct list_head *head); + +int arch_pmu_aliases(char *name, struct list_head *head); + int perf_pmu__test(void); #endif /* __PMU_H */ -- 1.7.11.7 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/