2 #include <linux/list.h> 3 #include <linux/compiler.h> 13 #include <api/fs/fs.h> 32 #define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/" 45 struct dirent *evt_ent;
49 format_dir = opendir(dir);
53 while (!ret && (evt_ent = readdir(format_dir))) {
55 char *
name = evt_ent->d_name;
58 if (!strcmp(name,
".") || !strcmp(name,
".."))
61 snprintf(path,
PATH_MAX,
"%s/%s", dir, name);
64 file = fopen(path,
"r");
86 const char *sysfs = sysfs__mountpoint();
94 if (stat(path, &st) < 0)
111 lc = setlocale(LC_NUMERIC, NULL);
129 setlocale(LC_NUMERIC,
"C");
131 *sval = strtod(scale, end);
135 setlocale(LC_NUMERIC, lc);
148 snprintf(path,
PATH_MAX,
"%s/%s.scale", dir, name);
150 fd = open(path, O_RDONLY);
154 if (fstat(fd, &st) < 0)
157 sret = read(fd, scale,
sizeof(scale)-1);
161 if (scale[sret - 1] ==
'\n')
162 scale[sret - 1] =
'\0';
178 snprintf(path,
PATH_MAX,
"%s/%s.unit", dir, name);
180 fd = open(path, O_RDONLY);
190 if (alias->
unit[sret - 1] ==
'\n')
191 alias->
unit[sret - 1] =
'\0';
193 alias->
unit[sret] =
'\0';
198 alias->
unit[0] =
'\0';
208 snprintf(path,
PATH_MAX,
"%s/%s.per-pkg", dir, name);
210 fd = open(path, O_RDONLY);
226 snprintf(path,
PATH_MAX,
"%s/%s.snapshot", dir, name);
228 fd = open(path, O_RDONLY);
238 char *
desc,
char *val,
239 char *long_desc,
char *
topic,
240 char *unit,
char *perpkg,
248 alias =
malloc(
sizeof(*alias));
252 INIT_LIST_HEAD(&alias->
terms);
254 alias->
unit[0] =
'\0';
260 pr_err(
"Cannot parse alias %s: %d\n", val, ret);
265 alias->
name = strdup(name);
276 alias->
metric_expr = metric_expr ? strdup(metric_expr) : NULL;
277 alias->
metric_name = metric_name ? strdup(metric_name): NULL;
278 alias->
desc = desc ? strdup(desc) : NULL;
279 alias->
long_desc = long_desc ? strdup(long_desc) :
280 desc ? strdup(desc) : NULL;
281 alias->
topic = topic ? strdup(topic) : NULL;
285 snprintf(alias->
unit,
sizeof(alias->
unit),
"%s", unit);
287 alias->
per_pkg = perpkg && sscanf(perpkg,
"%d", &num) == 1 && num == 1;
288 alias->
str = strdup(val);
290 list_add_tail(&alias->
list, list);
300 ret = fread(buf, 1,
sizeof(buf), file);
315 if (len > 5 && !strcmp(name + len - 5,
".unit"))
317 if (len > 6 && !strcmp(name + len - 6,
".scale"))
319 if (len > 8 && !strcmp(name + len - 8,
".per-pkg"))
321 if (len > 9 && !strcmp(name + len - 9,
".snapshot"))
333 struct dirent *evt_ent;
336 event_dir = opendir(dir);
340 while ((evt_ent = readdir(event_dir))) {
342 char *
name = evt_ent->d_name;
345 if (!strcmp(name,
".") || !strcmp(name,
".."))
354 scnprintf(path,
PATH_MAX,
"%s/%s", dir, name);
356 file = fopen(path,
"r");
363 pr_debug(
"Cannot set up %s\n", name);
379 const char *sysfs = sysfs__mountpoint();
385 "%s/bus/event_source/devices/%s/events", sysfs, name);
387 if (stat(path, &st) < 0)
397 struct list_head *terms)
403 list_for_each_entry(term, &alias->
terms,
list) {
414 list_add_tail(&cloned->
list, &
list);
416 list_splice(&
list, terms);
431 const char *sysfs = sysfs__mountpoint();
439 if (stat(path, &st) < 0)
442 file = fopen(path,
"r");
446 if (1 != fscanf(file,
"%u", type))
459 const char *sysfs = sysfs__mountpoint();
471 while ((dent = readdir(dir))) {
472 if (!strcmp(dent->d_name,
".") || !strcmp(dent->d_name,
".."))
486 file = fopen(path,
"r");
499 #define CPUS_TEMPLATE_UNCORE "%s/bus/event_source/devices/%s/cpumask" 500 #define CPUS_TEMPLATE_CPU "%s/bus/event_source/devices/%s/cpus" 506 const char *sysfs = sysfs__mountpoint();
507 const char *templates[] = {
512 const char **
template;
517 for (
template = templates; *
template;
template++) {
518 snprintf(path,
PATH_MAX, *
template, sysfs, name);
531 const char *sysfs = sysfs__mountpoint();
549 const char *sysfs = sysfs__mountpoint();
555 scnprintf(path,
PATH_MAX,
"%s/bus/event_source/devices/%s/cpus",
557 if (stat(path, &st) == 0)
561 scnprintf(path,
PATH_MAX,
"%s/bus/event_source/devices/%s",
563 if (stat(path, &st) == 0 && !strncmp(name,
"cpum_", 5))
587 regmatch_t pmatch[1];
590 if (regcomp(&re, mapcpuid, REG_EXTENDED) != 0) {
592 pr_info(
"Invalid regular expression %s\n", mapcpuid);
596 match = !regexec(&re, cpuid, 1, pmatch, 0);
599 size_t match_len = (pmatch[0].rm_eo - pmatch[0].rm_so);
602 if (match_len == strlen(cpuid))
613 cpuid = getenv(
"PERF_CPUID");
615 cpuid = strdup(cpuid);
622 pr_debug(
"Using CPUID %s\n", cpuid);
678 pe = &map->
table[i++];
686 pname = pe->
pmu ? pe->
pmu :
"cpu";
687 if (strncmp(pname, name, strlen(pname)))
701 struct perf_event_attr * __weak
731 pmu =
zalloc(
sizeof(*pmu));
736 pmu->
name = strdup(name);
741 INIT_LIST_HEAD(&pmu->
format);
743 list_splice(&format, &pmu->
format);
744 list_splice(&aliases, &pmu->
aliases);
745 list_add_tail(&pmu->
list, &pmus);
756 list_for_each_entry(pmu, &pmus,
list)
757 if (!strcmp(pmu->
name, name))
771 pmu = list_prepare_entry(pmu, &pmus,
list);
773 list_for_each_entry_continue(pmu, &pmus,
list)
799 list_for_each_entry(format, formats,
list)
800 if (!strcmp(format->
name, name))
816 bits |= 1ULL << fbit;
828 unsigned long fbit, vbit;
832 if (!test_bit(fbit, format))
835 if (value & (1llu << vbit++))
836 *v |= (1llu << fbit);
838 *v &= ~(1llu << fbit);
861 struct list_head *head_terms,
866 list_for_each_entry(t, head_terms,
list) {
877 printf(
"Required parameter '%s' not specified\n", term->
config);
893 list_for_each_entry(format, formats,
list)
909 struct perf_event_attr *
attr,
911 struct list_head *head_terms,
935 printf(
"Invalid event/parameter '%s'\n", term->
config);
940 err->
str = strdup(
"unknown term");
947 switch (format->
value) {
970 err->
str = strdup(
"no value assigned for term");
977 if (strcmp(term->
val.
str,
"?")) {
979 pr_info(
"Invalid sysfs entry %s=%s\n",
984 err->
str = strdup(
"expected numeric value");
998 if (asprintf(&err->
str,
999 "value too big for format, maximum is %llu",
1000 (
unsigned long long)max_val) < 0)
1001 err->
str = strdup(
"value too big for format");
1015 struct perf_event_attr *
attr,
1016 struct list_head *head_terms,
1021 list_for_each_entry(term, head_terms,
list) {
1036 struct list_head *head_terms,
1041 attr->type = pmu->
type;
1062 if (strcasecmp(term->
config,
"event"))
1070 if (!strcasecmp(alias->
name, name))
1085 if ((info->
unit && alias->
unit[0]) ||
1125 list_for_each_entry_safe(term, h, head_terms,
list) {
1142 list_del(&term->
list);
1151 if (info->
unit == NULL)
1154 if (info->
scale == 0.0)
1161 int config,
unsigned long *bits)
1165 format =
zalloc(
sizeof(*format));
1169 format->
name = strdup(name);
1171 memcpy(format->bits, bits,
sizeof(format->bits));
1173 list_add_tail(&format->
list, list);
1185 for (b = from; b <= to; b++)
1200 int used = snprintf(buf, len,
"%s/%s", pmu->
name, alias->
name);
1202 list_for_each_entry(term, &alias->
terms,
list) {
1204 used += snprintf(buf + used,
sub_non_neg(len, used),
1217 buf[len - 1] =
'\0';
1225 snprintf(buf, len,
"%s OR %s/%s/", alias->
name, pmu->
name, alias->
name);
1241 const struct sevent *as = a;
1242 const struct sevent *bs = b;
1262 int wlen = strcspn(s,
" \t");
1264 if (column + wlen >= max && column > start) {
1265 printf(
"\n%*s", start,
"");
1266 column = start + corr;
1268 n = printf(
"%s%.*s", column > start ?
" " :
"", wlen, s);
1287 int columns = pager_get_columns();
1307 bool is_cpu = !strcmp(pmu->
name,
"cpu");
1309 if (event_glob != NULL &&
1317 if (is_cpu && !name_only && !alias->
desc)
1321 if (is_cpu && !name_only && !alias->
desc)
1325 aliases[j].
name = strdup(aliases[j].name);
1326 if (!aliases[j].name)
1332 aliases[j].
str = alias->
str;
1341 if (asprintf(&s,
"%s//", pmu->
name) < 0)
1343 aliases[j].
name = s;
1349 for (j = 0; j < len; j++) {
1351 if (j > 0 && !strcmp(aliases[j].
name, aliases[j - 1].name))
1354 printf(
"%s ", aliases[j].name);
1357 if (aliases[j].
desc && !quiet_flag) {
1360 if (aliases[j].topic && (!topic ||
1361 strcmp(topic, aliases[j].topic))) {
1362 printf(
"%s%s:\n", topic ?
"\n" :
"",
1364 topic = aliases[j].
topic;
1366 printf(
" %-50s\n", aliases[j].name);
1367 printf(
"%*s", 8,
"[");
1371 printf(
"%*s%s/%s/ ", 8,
"", aliases[j].pmu, aliases[j].
str);
1372 if (aliases[j].metric_name)
1373 printf(
" MetricName: %s", aliases[j].metric_name);
1375 printf(
" MetricExpr: %s", aliases[j].metric_expr);
1379 printf(
" %-50s [Kernel PMU event]\n", aliases[j].name);
1382 if (printed && pager_in_use())
1385 for (j = 0; j < len; j++)
1391 printf(
"FATAL: not enough memory to print PMU events\n");
1403 if (strcmp(pname, pmu->
name))
1406 if (!strcmp(alias->
name, name))
1418 sysfs = sysfs__mountpoint();
1425 if (stat(path, &st) < 0)
1428 return fopen(path,
"r");
1438 va_start(args, fmt);
1441 ret = vfscanf(file, fmt, args);
static char * perf_pmu__getcpuid(struct perf_pmu *pmu)
void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag, bool long_desc, bool details_flag)
static int pmu_aliases(const char *name, struct list_head *head)
int strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
void parse_events_terms__purge(struct list_head *terms)
int parse_events_terms(struct list_head *terms, const char *str)
static struct header_column columns[PERF_HPP_DIFF__MAX_INDEX]
int perf_pmu__format_parse(char *dir, struct list_head *head)
static char * format_alias_or(char *buf, int len, struct perf_pmu *pmu, struct perf_pmu_alias *alias)
#define CPUS_TEMPLATE_CPU
static int check_info_data(struct perf_pmu_alias *alias, struct perf_pmu_info *info)
static void wordwrap(char *s, int start, int max, int corr)
static int pmu_config_term(struct list_head *formats, struct perf_event_attr *attr, struct parse_events_term *term, struct list_head *head_terms, bool zero, struct parse_events_error *err)
static char * format_alias(char *buf, int len, struct perf_pmu *pmu, struct perf_pmu_alias *alias)
int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,...)
static int convert_scale(const char *scale, char **end, double *sval)
static bool pmu_is_uncore(const char *name)
struct cpu_map * cpu_map__read(FILE *file)
static int term(yyscan_t scanner, int type)
struct perf_event_attr * default_config
static __u64 pmu_format_max_value(const unsigned long *format)
bool strglobmatch(const char *str, const char *pat)
static int pmu_alias_terms(struct perf_pmu_alias *alias, struct list_head *terms)
x86 movsq based memset() in arch/x86/lib/memset_64.S") MEMSET_FN(memset_erms
union parse_events_term::@132 val
struct perf_pmu * perf_pmu__scan(struct perf_pmu *pmu)
static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name)
void cpu_map__put(struct cpu_map *map)
void perf_pmu__set_format(unsigned long *bits, long from, long to)
static struct perf_pmu * pmu_find(const char *name)
static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, char *dir, char *name)
#define pr_debug(fmt,...)
int parse_events__is_hardcoded_term(struct parse_events_term *term)
int perf_pmu__new_format(struct list_head *list, char *name, int config, unsigned long *bits)
static struct perf_pmu_alias * pmu_find_alias(struct perf_pmu *pmu, struct parse_events_term *term)
static char * pmu_formats_string(struct list_head *formats)
static int str(yyscan_t scanner, int token)
static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, bool zero)
bool pmu_have_event(const char *pname, const char *name)
int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, struct list_head *head_terms, struct parse_events_error *err)
static int pmu_resolve_param_term(struct parse_events_term *term, struct list_head *head_terms, __u64 *value)
static int pmu_type(const char *name, __u32 *type)
static struct cpu_map * __pmu_cpumask(const char *path)
struct pmu_events_map * perf_pmu__find_map(struct perf_pmu *pmu)
struct perf_event_attr * perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
x86 movsq based memcpy() in arch/x86/lib/memcpy_64.S") MEMCPY_FN(memcpy_erms
int parse_events_term__clone(struct parse_events_term **new, struct parse_events_term *term)
int perf_pmu__config_terms(struct list_head *formats, struct perf_event_attr *attr, struct list_head *head_terms, bool zero, struct parse_events_error *err)
static FILE * perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
struct perf_pmu * perf_pmu__find(const char *name)
static int cmp_sevent(const void *a, const void *b)
#define EVENT_SOURCE_DEVICE_PATH
int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, struct perf_pmu_info *info)
static int pmu_aliases_parse(char *dir, struct list_head *head)
static bool pmu_alias_info_file(char *name)
bool strglobmatch_nocase(const char *str, const char *pat)
char * strbuf_detach(struct strbuf *sb, size_t *sz)
static int is_arm_pmu_core(const char *name)
static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
int perf_pmu_parse(struct list_head *list, char *name)
char * parse_events_formats_error_string(char *additional_terms)
static struct cpu_map * pmu_cpumask(const char *name)
static struct perf_pmu * pmu_lookup(const char *name)
static struct perf_pmu_format * pmu_find_format(struct list_head *formats, const char *name)
char unit[UNIT_MAX_LEN+1]
const char * metric_group
int strbuf_addf(struct strbuf *sb, const char *fmt,...)
static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, char *desc, char *val, char *long_desc, char *topic, char *unit, char *perpkg, char *metric_expr, char *metric_name)
static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
static int sub_non_neg(int a, int b)
#define CPUS_TEMPLATE_UNCORE
static void pmu_read_sysfs(void)
char *__weak get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
void strbuf_release(struct strbuf *sb)
static int pmu_format(const char *name, struct list_head *format)
#define PERF_PMU_FORMAT_BITS
__u64 perf_pmu__format_bits(struct list_head *formats, const char *name)
void static void * zalloc(size_t size)
static int perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name)