1d3351e631
The 'perf record' and 'perf stat' commands have supported the option '-C/--cpus' to count or collect only on the list of CPUs provided. This option needs to be supported for hybrid as well. For hybrid support, it needs to check that the cpu list are available on hybrid PMU. One example for AlderLake, cpu0-7 is 'cpu_core', cpu8-11 is 'cpu_atom'. Before: # perf stat -e cpu_core/cycles/ -C11 -- sleep 1 Performance counter stats for 'CPU(s) 11': <not supported> cpu_core/cycles/ 1.006179431 seconds time elapsed The 'perf stat' command silently returned "<not supported>" without any helpful information. It should error out pointing out that that cpu11 was not 'cpu_core'. After: # perf stat -e cpu_core/cycles/ -C11 -- sleep 1 WARNING: 11 isn't a 'cpu_core', please use a CPU list in the 'cpu_core' range (0-7) failed to use cpu list 11 We also need to support the events without pmu prefix specified. # perf stat -e cycles -C11 -- sleep 1 WARNING: 11 isn't a 'cpu_core', please use a CPU list in the 'cpu_core' range (0-7) Performance counter stats for 'CPU(s) 11': 1,067,373 cpu_atom/cycles/ 1.005544738 seconds time elapsed The perf tool creates two cycles events automatically, cpu_core/cycles/ and cpu_atom/cycles/. It checks that cpu11 is not 'cpu_core', then shows a warning for cpu_core/cycles/ and only count the cpu_atom/cycles/. If part of cpus are 'cpu_core' and part of cpus are 'cpu_atom', for example, # perf stat -e cycles -C0,11 -- sleep 1 WARNING: use 0 in 'cpu_core' for 'cycles', skip other cpus in list. WARNING: use 11 in 'cpu_atom' for 'cycles', skip other cpus in list. Performance counter stats for 'CPU(s) 0,11': 1,914,704 cpu_core/cycles/ 2,036,983 cpu_atom/cycles/ 1.005815641 seconds time elapsed It now automatically selects cpu0 for cpu_core/cycles/, selects cpu11 for cpu_atom/cycles/, and output with some warnings. Some more complex examples, # perf stat -e cycles,instructions -C0,11 -- sleep 1 WARNING: use 0 in 'cpu_core' for 'cycles', skip other cpus in list. WARNING: use 11 in 'cpu_atom' for 'cycles', skip other cpus in list. WARNING: use 0 in 'cpu_core' for 'instructions', skip other cpus in list. WARNING: use 11 in 'cpu_atom' for 'instructions', skip other cpus in list. Performance counter stats for 'CPU(s) 0,11': 2,780,387 cpu_core/cycles/ 1,583,432 cpu_atom/cycles/ 3,957,277 cpu_core/instructions/ 1,167,089 cpu_atom/instructions/ 1.006005124 seconds time elapsed # perf stat -e cycles,cpu_atom/instructions/ -C0,11 -- sleep 1 WARNING: use 0 in 'cpu_core' for 'cycles', skip other cpus in list. WARNING: use 11 in 'cpu_atom' for 'cycles', skip other cpus in list. WARNING: use 11 in 'cpu_atom' for 'cpu_atom/instructions/', skip other cpus in list. Performance counter stats for 'CPU(s) 0,11': 3,290,301 cpu_core/cycles/ 1,953,073 cpu_atom/cycles/ 1,407,869 cpu_atom/instructions/ 1.006260912 seconds time elapsed Signed-off-by: Jin Yao <yao.jin@linux.intel.com> Acked-by: Jiri Olsa <jolsa@redhat.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jin Yao <yao.jin@intel.com> Cc: Kan Liang <kan.liang@intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Link: https //lore.kernel.org/r/20210723063433.7318-4-yao.jin@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
144 lines
4.4 KiB
C
144 lines
4.4 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __PMU_H
|
|
#define __PMU_H
|
|
|
|
#include <linux/bitmap.h>
|
|
#include <linux/compiler.h>
|
|
#include <linux/perf_event.h>
|
|
#include <linux/list.h>
|
|
#include <stdbool.h>
|
|
#include "parse-events.h"
|
|
#include "pmu-events/pmu-events.h"
|
|
|
|
struct evsel_config_term;
|
|
struct perf_cpu_map;
|
|
|
|
enum {
|
|
PERF_PMU_FORMAT_VALUE_CONFIG,
|
|
PERF_PMU_FORMAT_VALUE_CONFIG1,
|
|
PERF_PMU_FORMAT_VALUE_CONFIG2,
|
|
};
|
|
|
|
#define PERF_PMU_FORMAT_BITS 64
|
|
#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
|
|
#define CPUS_TEMPLATE_CPU "%s/bus/event_source/devices/%s/cpus"
|
|
|
|
struct perf_event_attr;
|
|
|
|
struct perf_pmu_caps {
|
|
char *name;
|
|
char *value;
|
|
struct list_head list;
|
|
};
|
|
|
|
struct perf_pmu {
|
|
char *name;
|
|
char *id;
|
|
__u32 type;
|
|
bool selectable;
|
|
bool is_uncore;
|
|
bool is_hybrid;
|
|
bool auxtrace;
|
|
int max_precise;
|
|
struct perf_event_attr *default_config;
|
|
struct perf_cpu_map *cpus;
|
|
struct list_head format; /* HEAD struct perf_pmu_format -> list */
|
|
struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */
|
|
struct list_head caps; /* HEAD struct perf_pmu_caps -> list */
|
|
struct list_head list; /* ELEM */
|
|
struct list_head hybrid_list;
|
|
};
|
|
|
|
extern struct perf_pmu perf_pmu__fake;
|
|
|
|
struct perf_pmu_info {
|
|
const char *unit;
|
|
const char *metric_expr;
|
|
const char *metric_name;
|
|
double scale;
|
|
bool per_pkg;
|
|
bool snapshot;
|
|
};
|
|
|
|
#define UNIT_MAX_LEN 31 /* max length for event unit name */
|
|
|
|
struct perf_pmu_alias {
|
|
char *name;
|
|
char *desc;
|
|
char *long_desc;
|
|
char *topic;
|
|
char *str;
|
|
struct list_head terms; /* HEAD struct parse_events_term -> list */
|
|
struct list_head list; /* ELEM */
|
|
char unit[UNIT_MAX_LEN+1];
|
|
double scale;
|
|
bool per_pkg;
|
|
bool snapshot;
|
|
bool deprecated;
|
|
char *metric_expr;
|
|
char *metric_name;
|
|
char *pmu_name;
|
|
};
|
|
|
|
struct perf_pmu *perf_pmu__find(const char *name);
|
|
struct perf_pmu *perf_pmu__find_by_type(unsigned int type);
|
|
void pmu_add_sys_aliases(struct list_head *head, struct perf_pmu *pmu);
|
|
int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
|
|
struct list_head *head_terms,
|
|
struct parse_events_error *error);
|
|
int perf_pmu__config_terms(const char *pmu_name, struct list_head *formats,
|
|
struct perf_event_attr *attr,
|
|
struct list_head *head_terms,
|
|
bool zero, struct parse_events_error *error);
|
|
__u64 perf_pmu__format_bits(struct list_head *formats, const char *name);
|
|
int perf_pmu__format_type(struct list_head *formats, const char *name);
|
|
int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
|
|
struct perf_pmu_info *info);
|
|
struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
|
|
struct list_head *head_terms);
|
|
void perf_pmu_error(struct list_head *list, char *name, char const *msg);
|
|
|
|
int perf_pmu__new_format(struct list_head *list, char *name,
|
|
int config, unsigned long *bits);
|
|
void perf_pmu__set_format(unsigned long *bits, long from, long to);
|
|
int perf_pmu__format_parse(char *dir, struct list_head *head);
|
|
void perf_pmu__del_formats(struct list_head *formats);
|
|
|
|
struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
|
|
|
|
bool is_pmu_core(const char *name);
|
|
void print_pmu_events(const char *event_glob, bool name_only, bool quiet,
|
|
bool long_desc, bool details_flag,
|
|
bool deprecated);
|
|
bool pmu_have_event(const char *pname, const char *name);
|
|
|
|
int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, ...) __scanf(3, 4);
|
|
|
|
int perf_pmu__test(void);
|
|
|
|
struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu);
|
|
void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu,
|
|
struct pmu_events_map *map);
|
|
|
|
struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu);
|
|
struct pmu_events_map *pmu_events_map__find(void);
|
|
bool pmu_uncore_alias_match(const char *pmu_name, const char *name);
|
|
void perf_pmu_free_alias(struct perf_pmu_alias *alias);
|
|
|
|
typedef int (*pmu_sys_event_iter_fn)(struct pmu_event *pe, void *data);
|
|
void pmu_for_each_sys_event(pmu_sys_event_iter_fn fn, void *data);
|
|
int perf_pmu__convert_scale(const char *scale, char **end, double *sval);
|
|
|
|
int perf_pmu__caps_parse(struct perf_pmu *pmu);
|
|
|
|
void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config,
|
|
char *name);
|
|
|
|
bool perf_pmu__has_hybrid(void);
|
|
int perf_pmu__match(char *pattern, char *name, char *tok);
|
|
|
|
int perf_pmu__cpus_match(struct perf_pmu *pmu, struct perf_cpu_map *cpus,
|
|
struct perf_cpu_map **mcpus_ptr,
|
|
struct perf_cpu_map **ucpus_ptr);
|
|
#endif /* __PMU_H */
|