diff options
Diffstat (limited to 'tools/perf/util/evsel.c')
| -rw-r--r-- | tools/perf/util/evsel.c | 56 |
1 files changed, 53 insertions, 3 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 2f9e68025ede..f2dc91fb87fa 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
| @@ -658,9 +658,22 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) | |||
| 658 | attr->mmap_data = track; | 658 | attr->mmap_data = track; |
| 659 | } | 659 | } |
| 660 | 660 | ||
| 661 | /* | ||
| 662 | * We don't allow user space callchains for function trace | ||
| 663 | * event, due to issues with page faults while tracing page | ||
| 664 | * fault handler and its overall trickiness nature. | ||
| 665 | */ | ||
| 666 | if (perf_evsel__is_function_event(evsel)) | ||
| 667 | evsel->attr.exclude_callchain_user = 1; | ||
| 668 | |||
| 661 | if (callchain_param.enabled && !evsel->no_aux_samples) | 669 | if (callchain_param.enabled && !evsel->no_aux_samples) |
| 662 | perf_evsel__config_callgraph(evsel); | 670 | perf_evsel__config_callgraph(evsel); |
| 663 | 671 | ||
| 672 | if (opts->sample_intr_regs) { | ||
| 673 | attr->sample_regs_intr = PERF_REGS_MASK; | ||
| 674 | perf_evsel__set_sample_bit(evsel, REGS_INTR); | ||
| 675 | } | ||
| 676 | |||
| 664 | if (target__has_cpu(&opts->target)) | 677 | if (target__has_cpu(&opts->target)) |
| 665 | perf_evsel__set_sample_bit(evsel, CPU); | 678 | perf_evsel__set_sample_bit(evsel, CPU); |
| 666 | 679 | ||
| @@ -853,8 +866,6 @@ void perf_evsel__exit(struct perf_evsel *evsel) | |||
| 853 | perf_evsel__free_id(evsel); | 866 | perf_evsel__free_id(evsel); |
| 854 | close_cgroup(evsel->cgrp); | 867 | close_cgroup(evsel->cgrp); |
| 855 | zfree(&evsel->group_name); | 868 | zfree(&evsel->group_name); |
| 856 | if (evsel->tp_format) | ||
| 857 | pevent_free_format(evsel->tp_format); | ||
| 858 | zfree(&evsel->name); | 869 | zfree(&evsel->name); |
| 859 | perf_evsel__object.fini(evsel); | 870 | perf_evsel__object.fini(evsel); |
| 860 | } | 871 | } |
| @@ -1039,6 +1050,7 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp) | |||
| 1039 | ret += PRINT_ATTR_X64(branch_sample_type); | 1050 | ret += PRINT_ATTR_X64(branch_sample_type); |
| 1040 | ret += PRINT_ATTR_X64(sample_regs_user); | 1051 | ret += PRINT_ATTR_X64(sample_regs_user); |
| 1041 | ret += PRINT_ATTR_U32(sample_stack_user); | 1052 | ret += PRINT_ATTR_U32(sample_stack_user); |
| 1053 | ret += PRINT_ATTR_X64(sample_regs_intr); | ||
| 1042 | 1054 | ||
| 1043 | ret += fprintf(fp, "%.60s\n", graph_dotted_line); | 1055 | ret += fprintf(fp, "%.60s\n", graph_dotted_line); |
| 1044 | 1056 | ||
| @@ -1538,6 +1550,23 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, | |||
| 1538 | array++; | 1550 | array++; |
| 1539 | } | 1551 | } |
| 1540 | 1552 | ||
| 1553 | data->intr_regs.abi = PERF_SAMPLE_REGS_ABI_NONE; | ||
| 1554 | if (type & PERF_SAMPLE_REGS_INTR) { | ||
| 1555 | OVERFLOW_CHECK_u64(array); | ||
| 1556 | data->intr_regs.abi = *array; | ||
| 1557 | array++; | ||
| 1558 | |||
| 1559 | if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) { | ||
| 1560 | u64 mask = evsel->attr.sample_regs_intr; | ||
| 1561 | |||
| 1562 | sz = hweight_long(mask) * sizeof(u64); | ||
| 1563 | OVERFLOW_CHECK(array, sz, max_size); | ||
| 1564 | data->intr_regs.mask = mask; | ||
| 1565 | data->intr_regs.regs = (u64 *)array; | ||
| 1566 | array = (void *)array + sz; | ||
| 1567 | } | ||
| 1568 | } | ||
| 1569 | |||
| 1541 | return 0; | 1570 | return 0; |
| 1542 | } | 1571 | } |
| 1543 | 1572 | ||
| @@ -1633,6 +1662,16 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, | |||
| 1633 | if (type & PERF_SAMPLE_TRANSACTION) | 1662 | if (type & PERF_SAMPLE_TRANSACTION) |
| 1634 | result += sizeof(u64); | 1663 | result += sizeof(u64); |
| 1635 | 1664 | ||
| 1665 | if (type & PERF_SAMPLE_REGS_INTR) { | ||
| 1666 | if (sample->intr_regs.abi) { | ||
| 1667 | result += sizeof(u64); | ||
| 1668 | sz = hweight_long(sample->intr_regs.mask) * sizeof(u64); | ||
| 1669 | result += sz; | ||
| 1670 | } else { | ||
| 1671 | result += sizeof(u64); | ||
| 1672 | } | ||
| 1673 | } | ||
| 1674 | |||
| 1636 | return result; | 1675 | return result; |
| 1637 | } | 1676 | } |
| 1638 | 1677 | ||
| @@ -1811,6 +1850,17 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, | |||
| 1811 | array++; | 1850 | array++; |
| 1812 | } | 1851 | } |
| 1813 | 1852 | ||
| 1853 | if (type & PERF_SAMPLE_REGS_INTR) { | ||
| 1854 | if (sample->intr_regs.abi) { | ||
| 1855 | *array++ = sample->intr_regs.abi; | ||
| 1856 | sz = hweight_long(sample->intr_regs.mask) * sizeof(u64); | ||
| 1857 | memcpy(array, sample->intr_regs.regs, sz); | ||
| 1858 | array = (void *)array + sz; | ||
| 1859 | } else { | ||
| 1860 | *array++ = 0; | ||
| 1861 | } | ||
| 1862 | } | ||
| 1863 | |||
| 1814 | return 0; | 1864 | return 0; |
| 1815 | } | 1865 | } |
| 1816 | 1866 | ||
| @@ -1940,7 +1990,7 @@ static int sample_type__fprintf(FILE *fp, bool *first, u64 value) | |||
| 1940 | bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), | 1990 | bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), |
| 1941 | bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), | 1991 | bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), |
| 1942 | bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), | 1992 | bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), |
| 1943 | bit_name(IDENTIFIER), | 1993 | bit_name(IDENTIFIER), bit_name(REGS_INTR), |
| 1944 | { .name = NULL, } | 1994 | { .name = NULL, } |
| 1945 | }; | 1995 | }; |
| 1946 | #undef bit_name | 1996 | #undef bit_name |
