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.c42
1 files changed, 26 insertions, 16 deletions
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 9bf582750561..438bb261f391 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -2,6 +2,7 @@
2#include <sys/types.h> 2#include <sys/types.h>
3#include <unistd.h> 3#include <unistd.h>
4#include <stdio.h> 4#include <stdio.h>
5#include <stdbool.h>
5#include <dirent.h> 6#include <dirent.h>
6#include <api/fs/fs.h> 7#include <api/fs/fs.h>
7#include <locale.h> 8#include <locale.h>
@@ -387,6 +388,12 @@ static struct cpu_map *pmu_cpumask(const char *name)
387 return cpus; 388 return cpus;
388} 389}
389 390
391struct perf_event_attr *__attribute__((weak))
392perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
393{
394 return NULL;
395}
396
390static struct perf_pmu *pmu_lookup(const char *name) 397static struct perf_pmu *pmu_lookup(const char *name)
391{ 398{
392 struct perf_pmu *pmu; 399 struct perf_pmu *pmu;
@@ -421,6 +428,9 @@ static struct perf_pmu *pmu_lookup(const char *name)
421 pmu->name = strdup(name); 428 pmu->name = strdup(name);
422 pmu->type = type; 429 pmu->type = type;
423 list_add_tail(&pmu->list, &pmus); 430 list_add_tail(&pmu->list, &pmus);
431
432 pmu->default_config = perf_pmu__get_default_config(pmu);
433
424 return pmu; 434 return pmu;
425} 435}
426 436
@@ -479,28 +489,24 @@ pmu_find_format(struct list_head *formats, char *name)
479} 489}
480 490
481/* 491/*
482 * Returns value based on the format definition (format parameter) 492 * Sets value based on the format definition (format parameter)
483 * and unformated value (value parameter). 493 * and unformated value (value parameter).
484 *
485 * TODO maybe optimize a little ;)
486 */ 494 */
487static __u64 pmu_format_value(unsigned long *format, __u64 value) 495static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
496 bool zero)
488{ 497{
489 unsigned long fbit, vbit; 498 unsigned long fbit, vbit;
490 __u64 v = 0;
491 499
492 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 500 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
493 501
494 if (!test_bit(fbit, format)) 502 if (!test_bit(fbit, format))
495 continue; 503 continue;
496 504
497 if (!(value & (1llu << vbit++))) 505 if (value & (1llu << vbit++))
498 continue; 506 *v |= (1llu << fbit);
499 507 else if (zero)
500 v |= (1llu << fbit); 508 *v &= ~(1llu << fbit);
501 } 509 }
502
503 return v;
504} 510}
505 511
506/* 512/*
@@ -509,7 +515,8 @@ static __u64 pmu_format_value(unsigned long *format, __u64 value)
509 */ 515 */
510static int pmu_config_term(struct list_head *formats, 516static int pmu_config_term(struct list_head *formats,
511 struct perf_event_attr *attr, 517 struct perf_event_attr *attr,
512 struct parse_events_term *term) 518 struct parse_events_term *term,
519 bool zero)
513{ 520{
514 struct perf_pmu_format *format; 521 struct perf_pmu_format *format;
515 __u64 *vp; 522 __u64 *vp;
@@ -548,18 +555,19 @@ static int pmu_config_term(struct list_head *formats,
548 * non-hardcoded terms, here's the place to translate 555 * non-hardcoded terms, here's the place to translate
549 * them into value. 556 * them into value.
550 */ 557 */
551 *vp |= pmu_format_value(format->bits, term->val.num); 558 pmu_format_value(format->bits, term->val.num, vp, zero);
552 return 0; 559 return 0;
553} 560}
554 561
555int perf_pmu__config_terms(struct list_head *formats, 562int perf_pmu__config_terms(struct list_head *formats,
556 struct perf_event_attr *attr, 563 struct perf_event_attr *attr,
557 struct list_head *head_terms) 564 struct list_head *head_terms,
565 bool zero)
558{ 566{
559 struct parse_events_term *term; 567 struct parse_events_term *term;
560 568
561 list_for_each_entry(term, head_terms, list) 569 list_for_each_entry(term, head_terms, list)
562 if (pmu_config_term(formats, attr, term)) 570 if (pmu_config_term(formats, attr, term, zero))
563 return -EINVAL; 571 return -EINVAL;
564 572
565 return 0; 573 return 0;
@@ -573,8 +581,10 @@ int perf_pmu__config_terms(struct list_head *formats,
573int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 581int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
574 struct list_head *head_terms) 582 struct list_head *head_terms)
575{ 583{
584 bool zero = !!pmu->default_config;
585
576 attr->type = pmu->type; 586 attr->type = pmu->type;
577 return perf_pmu__config_terms(&pmu->format, attr, head_terms); 587 return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero);
578} 588}
579 589
580static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 590static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,