diff options
Diffstat (limited to 'tools/perf/util/pmu.c')
-rw-r--r-- | tools/perf/util/pmu.c | 42 |
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 | ||
391 | struct perf_event_attr *__attribute__((weak)) | ||
392 | perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) | ||
393 | { | ||
394 | return NULL; | ||
395 | } | ||
396 | |||
390 | static struct perf_pmu *pmu_lookup(const char *name) | 397 | static 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 | */ |
487 | static __u64 pmu_format_value(unsigned long *format, __u64 value) | 495 | static 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 | */ |
510 | static int pmu_config_term(struct list_head *formats, | 516 | static 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 | ||
555 | int perf_pmu__config_terms(struct list_head *formats, | 562 | int 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, | |||
573 | int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, | 581 | int 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 | ||
580 | static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, | 590 | static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, |