Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'perf-tools-for-v6.1-2-2022-10-16' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull more perf tools updates from Arnaldo Carvalho de Melo:

- Use BPF CO-RE (Compile Once, Run Everywhere) to support old kernels
when using bperf (perf BPF based counters) with cgroups.

- Support HiSilicon PCIe Performance Monitoring Unit (PMU), that
monitors bandwidth, latency, bus utilization and buffer occupancy.

Documented in Documentation/admin-guide/perf/hisi-pcie-pmu.rst.

- User space tasks can migrate between CPUs, so when tracing selected
CPUs, system-wide sideband is still needed, fix it in the setup of
Intel PT on hybrid systems.

- Fix metricgroups title message in 'perf list', it should state that
the metrics groups are to be used with the '-M' option, not '-e'.

- Sync the msr-index.h copy with the kernel sources, adding support for
using "AMD64_TSC_RATIO" in filter expressions in 'perf trace' as well
as decoding it when printing the MSR tracepoint arguments.

- Fix program header size and alignment when generating a JIT ELF in
'perf inject'.

- Add multiple new Intel PT 'perf test' entries, including a jitdump
one.

- Fix the 'perf test' entries for 'perf stat' CSV and JSON output when
running on PowerPC due to an invalid topology number in that arch.

- Fix the 'perf test' for arm_coresight failures on the ARM Juno
system.

- Fix the 'perf test' attr entry for PERF_FORMAT_LOST, adding this
option to the or expression expected in the intercepted
perf_event_open() syscall.

- Add missing condition flags ('hs', 'lo', 'vc', 'vs') for arm64 in the
'perf annotate' asm parser.

- Fix 'perf mem record -C' option processing, it was being chopped up
when preparing the underlying 'perf record -e mem-events' and thus
being ignored, requiring using '-- -C CPUs' as a workaround.

- Improvements and tidy ups for 'perf test' shell infra.

- Fix Intel PT information printing segfault in uClibc, where a NULL
format was being passed to fprintf.

* tag 'perf-tools-for-v6.1-2-2022-10-16' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux: (23 commits)
tools arch x86: Sync the msr-index.h copy with the kernel sources
perf auxtrace arm64: Add support for parsing HiSilicon PCIe Trace packet
perf auxtrace arm64: Add support for HiSilicon PCIe Tune and Trace device driver
perf auxtrace arm: Refactor event list iteration in auxtrace_record__init()
perf tests stat+json_output: Include sanity check for topology
perf tests stat+csv_output: Include sanity check for topology
perf intel-pt: Fix system_wide dummy event for hybrid
perf intel-pt: Fix segfault in intel_pt_print_info() with uClibc
perf test: Fix attr tests for PERF_FORMAT_LOST
perf test: test_intel_pt.sh: Add 9 tests
perf inject: Fix GEN_ELF_TEXT_OFFSET for jit
perf test: test_intel_pt.sh: Add jitdump test
perf test: test_intel_pt.sh: Tidy some alignment
perf test: test_intel_pt.sh: Print a message when skipping kernel tracing
perf test: test_intel_pt.sh: Tidy some perf record options
perf test: test_intel_pt.sh: Fix return checking again
perf: Skip and warn on unknown format 'configN' attrs
perf list: Fix metricgroups title message
perf mem: Fix -C option behavior for perf mem record
perf annotate: Add missing condition flags for arm64
...

+1265 -71
+18
tools/arch/x86/include/asm/msr-index.h
··· 155 155 * Return Stack Buffer Predictions. 156 156 */ 157 157 158 + #define ARCH_CAP_XAPIC_DISABLE BIT(21) /* 159 + * IA32_XAPIC_DISABLE_STATUS MSR 160 + * supported 161 + */ 162 + 158 163 #define MSR_IA32_FLUSH_CMD 0x0000010b 159 164 #define L1D_FLUSH BIT(0) /* 160 165 * Writeback and invalidate the ··· 590 585 #define MSR_AMD64_PERF_CNTR_GLOBAL_CTL 0xc0000301 591 586 #define MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR 0xc0000302 592 587 588 + /* AMD Last Branch Record MSRs */ 589 + #define MSR_AMD64_LBR_SELECT 0xc000010e 590 + 593 591 /* Fam 17h MSRs */ 594 592 #define MSR_F17H_IRPERF 0xc00000e9 595 593 ··· 763 755 /* AMD Branch Sampling configuration */ 764 756 #define MSR_AMD_DBG_EXTN_CFG 0xc000010f 765 757 #define MSR_AMD_SAMP_BR_FROM 0xc0010300 758 + 759 + #define DBG_EXTN_CFG_LBRV2EN BIT_ULL(6) 766 760 767 761 #define MSR_IA32_MPERF 0x000000e7 768 762 #define MSR_IA32_APERF 0x000000e8 ··· 1063 1053 /* Hardware Feedback Interface */ 1064 1054 #define MSR_IA32_HW_FEEDBACK_PTR 0x17d0 1065 1055 #define MSR_IA32_HW_FEEDBACK_CONFIG 0x17d1 1056 + 1057 + /* x2APIC locked status */ 1058 + #define MSR_IA32_XAPIC_DISABLE_STATUS 0xBD 1059 + #define LEGACY_XAPIC_DISABLED BIT(0) /* 1060 + * x2APIC mode is locked and 1061 + * disabling x2APIC will cause 1062 + * a #GP 1063 + */ 1066 1064 1067 1065 #endif /* _ASM_X86_MSR_INDEX_H */
+2 -3
tools/lib/perf/include/perf/event.h
··· 6 6 #include <linux/types.h> 7 7 #include <linux/limits.h> 8 8 #include <linux/bpf.h> 9 - #include <linux/compiler.h> 10 9 #include <sys/types.h> /* pid_t */ 11 10 12 11 #define event_contains(obj, mem) ((obj).header.size > offsetof(typeof(obj), mem)) ··· 206 207 __u16 end_cpu; 207 208 }; 208 209 209 - struct __packed perf_record_cpu_map_data { 210 + struct perf_record_cpu_map_data { 210 211 __u16 type; 211 212 union { 212 213 /* Used when type == PERF_CPU_MAP__CPUS. */ ··· 218 219 /* Used when type == PERF_CPU_MAP__RANGE_CPUS. */ 219 220 struct perf_record_range_cpu_map range_cpu_data; 220 221 }; 221 - }; 222 + } __attribute__((packed)); 222 223 223 224 #pragma GCC diagnostic pop 224 225
+97 -19
tools/perf/arch/arm/util/auxtrace.c
··· 4 4 * Author: Mathieu Poirier <mathieu.poirier@linaro.org> 5 5 */ 6 6 7 + #include <dirent.h> 7 8 #include <stdbool.h> 8 9 #include <linux/coresight-pmu.h> 9 10 #include <linux/zalloc.h> 11 + #include <api/fs/fs.h> 10 12 11 13 #include "../../../util/auxtrace.h" 12 14 #include "../../../util/debug.h" ··· 16 14 #include "../../../util/pmu.h" 17 15 #include "cs-etm.h" 18 16 #include "arm-spe.h" 17 + #include "hisi-ptt.h" 19 18 20 19 static struct perf_pmu **find_all_arm_spe_pmus(int *nr_spes, int *err) 21 20 { ··· 53 50 return arm_spe_pmus; 54 51 } 55 52 53 + static struct perf_pmu **find_all_hisi_ptt_pmus(int *nr_ptts, int *err) 54 + { 55 + const char *sysfs = sysfs__mountpoint(); 56 + struct perf_pmu **hisi_ptt_pmus = NULL; 57 + struct dirent *dent; 58 + char path[PATH_MAX]; 59 + DIR *dir = NULL; 60 + int idx = 0; 61 + 62 + snprintf(path, PATH_MAX, "%s" EVENT_SOURCE_DEVICE_PATH, sysfs); 63 + dir = opendir(path); 64 + if (!dir) { 65 + pr_err("can't read directory '%s'\n", EVENT_SOURCE_DEVICE_PATH); 66 + *err = -EINVAL; 67 + return NULL; 68 + } 69 + 70 + while ((dent = readdir(dir))) { 71 + if (strstr(dent->d_name, HISI_PTT_PMU_NAME)) 72 + (*nr_ptts)++; 73 + } 74 + 75 + if (!(*nr_ptts)) 76 + goto out; 77 + 78 + hisi_ptt_pmus = zalloc(sizeof(struct perf_pmu *) * (*nr_ptts)); 79 + if (!hisi_ptt_pmus) { 80 + pr_err("hisi_ptt alloc failed\n"); 81 + *err = -ENOMEM; 82 + goto out; 83 + } 84 + 85 + rewinddir(dir); 86 + while ((dent = readdir(dir))) { 87 + if (strstr(dent->d_name, HISI_PTT_PMU_NAME) && idx < *nr_ptts) { 88 + hisi_ptt_pmus[idx] = perf_pmu__find(dent->d_name); 89 + if (hisi_ptt_pmus[idx]) 90 + idx++; 91 + } 92 + } 93 + 94 + out: 95 + closedir(dir); 96 + return hisi_ptt_pmus; 97 + } 98 + 99 + static struct perf_pmu *find_pmu_for_event(struct perf_pmu **pmus, 100 + int pmu_nr, struct evsel *evsel) 101 + { 102 + int i; 103 + 104 + if (!pmus) 105 + return NULL; 106 + 107 + for (i = 0; i < pmu_nr; i++) { 108 + if (evsel->core.attr.type == pmus[i]->type) 109 + return pmus[i]; 110 + } 111 + 112 + return NULL; 113 + } 114 + 56 115 struct auxtrace_record 57 116 *auxtrace_record__init(struct evlist *evlist, int *err) 58 117 { 59 - struct perf_pmu *cs_etm_pmu; 60 - struct evsel *evsel; 61 - bool found_etm = false; 62 - struct perf_pmu *found_spe = NULL; 118 + struct perf_pmu *cs_etm_pmu = NULL; 63 119 struct perf_pmu **arm_spe_pmus = NULL; 120 + struct perf_pmu **hisi_ptt_pmus = NULL; 121 + struct evsel *evsel; 122 + struct perf_pmu *found_etm = NULL; 123 + struct perf_pmu *found_spe = NULL; 124 + struct perf_pmu *found_ptt = NULL; 125 + int auxtrace_event_cnt = 0; 64 126 int nr_spes = 0; 65 - int i = 0; 127 + int nr_ptts = 0; 66 128 67 129 if (!evlist) 68 130 return NULL; 69 131 70 132 cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME); 71 133 arm_spe_pmus = find_all_arm_spe_pmus(&nr_spes, err); 134 + hisi_ptt_pmus = find_all_hisi_ptt_pmus(&nr_ptts, err); 72 135 73 136 evlist__for_each_entry(evlist, evsel) { 74 - if (cs_etm_pmu && 75 - evsel->core.attr.type == cs_etm_pmu->type) 76 - found_etm = true; 137 + if (cs_etm_pmu && !found_etm) 138 + found_etm = find_pmu_for_event(&cs_etm_pmu, 1, evsel); 77 139 78 - if (!nr_spes || found_spe) 79 - continue; 140 + if (arm_spe_pmus && !found_spe) 141 + found_spe = find_pmu_for_event(arm_spe_pmus, nr_spes, evsel); 80 142 81 - for (i = 0; i < nr_spes; i++) { 82 - if (evsel->core.attr.type == arm_spe_pmus[i]->type) { 83 - found_spe = arm_spe_pmus[i]; 84 - break; 85 - } 86 - } 143 + if (hisi_ptt_pmus && !found_ptt) 144 + found_ptt = find_pmu_for_event(hisi_ptt_pmus, nr_ptts, evsel); 87 145 } 88 - free(arm_spe_pmus); 89 146 90 - if (found_etm && found_spe) { 91 - pr_err("Concurrent ARM Coresight ETM and SPE operation not currently supported\n"); 147 + free(arm_spe_pmus); 148 + free(hisi_ptt_pmus); 149 + 150 + if (found_etm) 151 + auxtrace_event_cnt++; 152 + 153 + if (found_spe) 154 + auxtrace_event_cnt++; 155 + 156 + if (found_ptt) 157 + auxtrace_event_cnt++; 158 + 159 + if (auxtrace_event_cnt > 1) { 160 + pr_err("Concurrent AUX trace operation not currently supported\n"); 92 161 *err = -EOPNOTSUPP; 93 162 return NULL; 94 163 } ··· 171 96 #if defined(__aarch64__) 172 97 if (found_spe) 173 98 return arm_spe_recording_init(err, found_spe); 99 + 100 + if (found_ptt) 101 + return hisi_ptt_recording_init(err, found_ptt); 174 102 #endif 175 103 176 104 /*
+3
tools/perf/arch/arm/util/pmu.c
··· 10 10 #include <linux/string.h> 11 11 12 12 #include "arm-spe.h" 13 + #include "hisi-ptt.h" 13 14 #include "../../../util/pmu.h" 14 15 15 16 struct perf_event_attr ··· 23 22 #if defined(__aarch64__) 24 23 } else if (strstarts(pmu->name, ARM_SPE_PMU_NAME)) { 25 24 return arm_spe_pmu_default_config(pmu); 25 + } else if (strstarts(pmu->name, HISI_PTT_PMU_NAME)) { 26 + pmu->selectable = true; 26 27 #endif 27 28 } 28 29
+1 -1
tools/perf/arch/arm64/annotate/instructions.c
··· 102 102 if (err) 103 103 goto out_free_arm; 104 104 /* b, b.cond, br, cbz/cbnz, tbz/tbnz */ 105 - err = regcomp(&arm->jump_insn, "^[ct]?br?\\.?(cc|cs|eq|ge|gt|hi|le|ls|lt|mi|ne|pl)?n?z?$", 105 + err = regcomp(&arm->jump_insn, "^[ct]?br?\\.?(cc|cs|eq|ge|gt|hi|hs|le|lo|ls|lt|mi|ne|pl|vc|vs)?n?z?$", 106 106 REG_EXTENDED); 107 107 if (err) 108 108 goto out_free_call;
+1 -1
tools/perf/arch/arm64/util/Build
··· 11 11 perf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \ 12 12 ../../arm/util/auxtrace.o \ 13 13 ../../arm/util/cs-etm.o \ 14 - arm-spe.o mem-events.o 14 + arm-spe.o mem-events.o hisi-ptt.o
+188
tools/perf/arch/arm64/util/hisi-ptt.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * HiSilicon PCIe Trace and Tuning (PTT) support 4 + * Copyright (c) 2022 HiSilicon Technologies Co., Ltd. 5 + */ 6 + 7 + #include <linux/kernel.h> 8 + #include <linux/types.h> 9 + #include <linux/bitops.h> 10 + #include <linux/log2.h> 11 + #include <linux/zalloc.h> 12 + #include <time.h> 13 + 14 + #include <internal/lib.h> // page_size 15 + #include "../../../util/auxtrace.h" 16 + #include "../../../util/cpumap.h" 17 + #include "../../../util/debug.h" 18 + #include "../../../util/event.h" 19 + #include "../../../util/evlist.h" 20 + #include "../../../util/evsel.h" 21 + #include "../../../util/hisi-ptt.h" 22 + #include "../../../util/pmu.h" 23 + #include "../../../util/record.h" 24 + #include "../../../util/session.h" 25 + #include "../../../util/tsc.h" 26 + 27 + #define KiB(x) ((x) * 1024) 28 + #define MiB(x) ((x) * 1024 * 1024) 29 + 30 + struct hisi_ptt_recording { 31 + struct auxtrace_record itr; 32 + struct perf_pmu *hisi_ptt_pmu; 33 + struct evlist *evlist; 34 + }; 35 + 36 + static size_t 37 + hisi_ptt_info_priv_size(struct auxtrace_record *itr __maybe_unused, 38 + struct evlist *evlist __maybe_unused) 39 + { 40 + return HISI_PTT_AUXTRACE_PRIV_SIZE; 41 + } 42 + 43 + static int hisi_ptt_info_fill(struct auxtrace_record *itr, 44 + struct perf_session *session, 45 + struct perf_record_auxtrace_info *auxtrace_info, 46 + size_t priv_size) 47 + { 48 + struct hisi_ptt_recording *pttr = 49 + container_of(itr, struct hisi_ptt_recording, itr); 50 + struct perf_pmu *hisi_ptt_pmu = pttr->hisi_ptt_pmu; 51 + 52 + if (priv_size != HISI_PTT_AUXTRACE_PRIV_SIZE) 53 + return -EINVAL; 54 + 55 + if (!session->evlist->core.nr_mmaps) 56 + return -EINVAL; 57 + 58 + auxtrace_info->type = PERF_AUXTRACE_HISI_PTT; 59 + auxtrace_info->priv[0] = hisi_ptt_pmu->type; 60 + 61 + return 0; 62 + } 63 + 64 + static int hisi_ptt_set_auxtrace_mmap_page(struct record_opts *opts) 65 + { 66 + bool privileged = perf_event_paranoid_check(-1); 67 + 68 + if (!opts->full_auxtrace) 69 + return 0; 70 + 71 + if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) { 72 + if (privileged) { 73 + opts->auxtrace_mmap_pages = MiB(16) / page_size; 74 + } else { 75 + opts->auxtrace_mmap_pages = KiB(128) / page_size; 76 + if (opts->mmap_pages == UINT_MAX) 77 + opts->mmap_pages = KiB(256) / page_size; 78 + } 79 + } 80 + 81 + /* Validate auxtrace_mmap_pages */ 82 + if (opts->auxtrace_mmap_pages) { 83 + size_t sz = opts->auxtrace_mmap_pages * (size_t)page_size; 84 + size_t min_sz = KiB(8); 85 + 86 + if (sz < min_sz || !is_power_of_2(sz)) { 87 + pr_err("Invalid mmap size for HISI PTT: must be at least %zuKiB and a power of 2\n", 88 + min_sz / 1024); 89 + return -EINVAL; 90 + } 91 + } 92 + 93 + return 0; 94 + } 95 + 96 + static int hisi_ptt_recording_options(struct auxtrace_record *itr, 97 + struct evlist *evlist, 98 + struct record_opts *opts) 99 + { 100 + struct hisi_ptt_recording *pttr = 101 + container_of(itr, struct hisi_ptt_recording, itr); 102 + struct perf_pmu *hisi_ptt_pmu = pttr->hisi_ptt_pmu; 103 + struct evsel *evsel, *hisi_ptt_evsel = NULL; 104 + struct evsel *tracking_evsel; 105 + int err; 106 + 107 + pttr->evlist = evlist; 108 + evlist__for_each_entry(evlist, evsel) { 109 + if (evsel->core.attr.type == hisi_ptt_pmu->type) { 110 + if (hisi_ptt_evsel) { 111 + pr_err("There may be only one " HISI_PTT_PMU_NAME "x event\n"); 112 + return -EINVAL; 113 + } 114 + evsel->core.attr.freq = 0; 115 + evsel->core.attr.sample_period = 1; 116 + evsel->needs_auxtrace_mmap = true; 117 + hisi_ptt_evsel = evsel; 118 + opts->full_auxtrace = true; 119 + } 120 + } 121 + 122 + err = hisi_ptt_set_auxtrace_mmap_page(opts); 123 + if (err) 124 + return err; 125 + /* 126 + * To obtain the auxtrace buffer file descriptor, the auxtrace event 127 + * must come first. 128 + */ 129 + evlist__to_front(evlist, hisi_ptt_evsel); 130 + evsel__set_sample_bit(hisi_ptt_evsel, TIME); 131 + 132 + /* Add dummy event to keep tracking */ 133 + err = parse_event(evlist, "dummy:u"); 134 + if (err) 135 + return err; 136 + 137 + tracking_evsel = evlist__last(evlist); 138 + evlist__set_tracking_event(evlist, tracking_evsel); 139 + 140 + tracking_evsel->core.attr.freq = 0; 141 + tracking_evsel->core.attr.sample_period = 1; 142 + evsel__set_sample_bit(tracking_evsel, TIME); 143 + 144 + return 0; 145 + } 146 + 147 + static u64 hisi_ptt_reference(struct auxtrace_record *itr __maybe_unused) 148 + { 149 + return rdtsc(); 150 + } 151 + 152 + static void hisi_ptt_recording_free(struct auxtrace_record *itr) 153 + { 154 + struct hisi_ptt_recording *pttr = 155 + container_of(itr, struct hisi_ptt_recording, itr); 156 + 157 + free(pttr); 158 + } 159 + 160 + struct auxtrace_record *hisi_ptt_recording_init(int *err, 161 + struct perf_pmu *hisi_ptt_pmu) 162 + { 163 + struct hisi_ptt_recording *pttr; 164 + 165 + if (!hisi_ptt_pmu) { 166 + *err = -ENODEV; 167 + return NULL; 168 + } 169 + 170 + pttr = zalloc(sizeof(*pttr)); 171 + if (!pttr) { 172 + *err = -ENOMEM; 173 + return NULL; 174 + } 175 + 176 + pttr->hisi_ptt_pmu = hisi_ptt_pmu; 177 + pttr->itr.pmu = hisi_ptt_pmu; 178 + pttr->itr.recording_options = hisi_ptt_recording_options; 179 + pttr->itr.info_priv_size = hisi_ptt_info_priv_size; 180 + pttr->itr.info_fill = hisi_ptt_info_fill; 181 + pttr->itr.free = hisi_ptt_recording_free; 182 + pttr->itr.reference = hisi_ptt_reference; 183 + pttr->itr.read_finish = auxtrace_record__read_finish; 184 + pttr->itr.alignment = 0; 185 + 186 + *err = 0; 187 + return &pttr->itr; 188 + }
+1 -1
tools/perf/arch/x86/util/intel-pt.c
··· 866 866 * User space tasks can migrate between CPUs, so when tracing 867 867 * selected CPUs, sideband for all CPUs is still needed. 868 868 */ 869 - need_system_wide_tracking = evlist->core.has_user_cpus && 869 + need_system_wide_tracking = opts->target.cpu_list && 870 870 !intel_pt_evsel->core.attr.exclude_user; 871 871 872 872 tracking_evsel = evlist__add_aux_dummy(evlist, need_system_wide_tracking);
+1 -1
tools/perf/builtin-list.c
··· 60 60 setup_pager(); 61 61 62 62 if (!raw_dump && pager_in_use()) 63 - printf("\nList of pre-defined events (to be used in -e):\n\n"); 63 + printf("\nList of pre-defined events (to be used in -e or -M):\n\n"); 64 64 65 65 if (hybrid_type) { 66 66 pmu_name = perf_pmu__hybrid_type_to_pmu(hybrid_type);
+8
tools/perf/builtin-mem.c
··· 97 97 else 98 98 rec_argc = argc + 9 * perf_pmu__hybrid_pmu_num(); 99 99 100 + if (mem->cpu_list) 101 + rec_argc += 2; 102 + 100 103 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 101 104 if (!rec_argv) 102 105 return -1; ··· 161 158 162 159 if (all_kernel) 163 160 rec_argv[i++] = "--all-kernel"; 161 + 162 + if (mem->cpu_list) { 163 + rec_argv[i++] = "-C"; 164 + rec_argv[i++] = mem->cpu_list; 165 + } 164 166 165 167 for (j = 0; j < argc; j++, i++) 166 168 rec_argv[i] = argv[j];
+1 -1
tools/perf/tests/attr/base-record
··· 9 9 config=0 10 10 sample_period=* 11 11 sample_type=263 12 - read_format=0|4 12 + read_format=0|4|20 13 13 disabled=1 14 14 inherit=1 15 15 pinned=0
+1 -1
tools/perf/tests/attr/system-wide-dummy
··· 11 11 config=9 12 12 sample_period=4000 13 13 sample_type=455 14 - read_format=4 14 + read_format=4|20 15 15 # Event will be enabled right away. 16 16 disabled=0 17 17 inherit=1
+2 -2
tools/perf/tests/attr/test-record-group
··· 7 7 fd=1 8 8 group_fd=-1 9 9 sample_type=327 10 - read_format=4 10 + read_format=4|20 11 11 12 12 [event-2:base-record] 13 13 fd=2 14 14 group_fd=1 15 15 config=1 16 16 sample_type=327 17 - read_format=4 17 + read_format=4|20 18 18 mmap=0 19 19 comm=0 20 20 task=0
+3 -3
tools/perf/tests/attr/test-record-group-sampling
··· 7 7 fd=1 8 8 group_fd=-1 9 9 sample_type=343 10 - read_format=12 10 + read_format=12|28 11 11 inherit=0 12 12 13 13 [event-2:base-record] ··· 21 21 # default | PERF_SAMPLE_READ 22 22 sample_type=343 23 23 24 - # PERF_FORMAT_ID | PERF_FORMAT_GROUP 25 - read_format=12 24 + # PERF_FORMAT_ID | PERF_FORMAT_GROUP | PERF_FORMAT_LOST 25 + read_format=12|28 26 26 task=0 27 27 mmap=0 28 28 comm=0
+2 -2
tools/perf/tests/attr/test-record-group1
··· 7 7 fd=1 8 8 group_fd=-1 9 9 sample_type=327 10 - read_format=4 10 + read_format=4|20 11 11 12 12 [event-2:base-record] 13 13 fd=2 ··· 15 15 type=0 16 16 config=1 17 17 sample_type=327 18 - read_format=4 18 + read_format=4|20 19 19 mmap=0 20 20 comm=0 21 21 task=0
+2 -2
tools/perf/tests/attr/test-record-group2
··· 9 9 config=0|1 10 10 sample_period=1234000 11 11 sample_type=87 12 - read_format=12 12 + read_format=12|28 13 13 inherit=0 14 14 freq=0 15 15 ··· 19 19 config=0|1 20 20 sample_period=6789000 21 21 sample_type=87 22 - read_format=12 22 + read_format=12|28 23 23 disabled=0 24 24 inherit=0 25 25 mmap=0
+39 -4
tools/perf/tests/shell/stat+csv_output.sh
··· 6 6 7 7 set -e 8 8 9 + skip_test=0 10 + 9 11 function commachecker() 10 12 { 11 13 local -i cnt=0 ··· 158 156 echo "[Success]" 159 157 } 160 158 159 + # The perf stat options for per-socket, per-core, per-die 160 + # and -A ( no_aggr mode ) uses the info fetched from this 161 + # directory: "/sys/devices/system/cpu/cpu*/topology". For 162 + # example, socket value is fetched from "physical_package_id" 163 + # file in topology directory. 164 + # Reference: cpu__get_topology_int in util/cpumap.c 165 + # If the platform doesn't expose topology information, values 166 + # will be set to -1. For example, incase of pSeries platform 167 + # of powerpc, value for "physical_package_id" is restricted 168 + # and set to -1. Check here validates the socket-id read from 169 + # topology file before proceeding further 170 + 171 + FILE_LOC="/sys/devices/system/cpu/cpu*/topology/" 172 + FILE_NAME="physical_package_id" 173 + 174 + check_for_topology() 175 + { 176 + if ! ParanoidAndNotRoot 0 177 + then 178 + socket_file=`ls $FILE_LOC/$FILE_NAME | head -n 1` 179 + [ -z $socket_file ] && return 0 180 + socket_id=`cat $socket_file` 181 + [ $socket_id == -1 ] && skip_test=1 182 + return 0 183 + fi 184 + } 185 + 186 + check_for_topology 161 187 check_no_args 162 188 check_system_wide 163 - check_system_wide_no_aggr 164 189 check_interval 165 190 check_event 166 - check_per_core 167 191 check_per_thread 168 - check_per_die 169 192 check_per_node 170 - check_per_socket 193 + if [ $skip_test -ne 1 ] 194 + then 195 + check_system_wide_no_aggr 196 + check_per_core 197 + check_per_die 198 + check_per_socket 199 + else 200 + echo "[Skip] Skipping tests for system_wide_no_aggr, per_core, per_die and per_socket since socket id exposed via topology is invalid" 201 + fi 171 202 exit 0
+39 -4
tools/perf/tests/shell/stat+json_output.sh
··· 6 6 7 7 set -e 8 8 9 + skip_test=0 10 + 9 11 pythonchecker=$(dirname $0)/lib/perf_json_output_lint.py 10 12 if [ "x$PYTHON" == "x" ] 11 13 then ··· 136 134 echo "[Success]" 137 135 } 138 136 137 + # The perf stat options for per-socket, per-core, per-die 138 + # and -A ( no_aggr mode ) uses the info fetched from this 139 + # directory: "/sys/devices/system/cpu/cpu*/topology". For 140 + # example, socket value is fetched from "physical_package_id" 141 + # file in topology directory. 142 + # Reference: cpu__get_topology_int in util/cpumap.c 143 + # If the platform doesn't expose topology information, values 144 + # will be set to -1. For example, incase of pSeries platform 145 + # of powerpc, value for "physical_package_id" is restricted 146 + # and set to -1. Check here validates the socket-id read from 147 + # topology file before proceeding further 148 + 149 + FILE_LOC="/sys/devices/system/cpu/cpu*/topology/" 150 + FILE_NAME="physical_package_id" 151 + 152 + check_for_topology() 153 + { 154 + if ! ParanoidAndNotRoot 0 155 + then 156 + socket_file=`ls $FILE_LOC/$FILE_NAME | head -n 1` 157 + [ -z $socket_file ] && return 0 158 + socket_id=`cat $socket_file` 159 + [ $socket_id == -1 ] && skip_test=1 160 + return 0 161 + fi 162 + } 163 + 164 + check_for_topology 139 165 check_no_args 140 166 check_system_wide 141 - check_system_wide_no_aggr 142 167 check_interval 143 168 check_event 144 - check_per_core 145 169 check_per_thread 146 - check_per_die 147 170 check_per_node 148 - check_per_socket 171 + if [ $skip_test -ne 1 ] 172 + then 173 + check_system_wide_no_aggr 174 + check_per_core 175 + check_per_die 176 + check_per_socket 177 + else 178 + echo "[Skip] Skipping tests for system_wide_no_aggr, per_core, per_die and per_socket since socket id exposed via topology is invalid" 179 + fi 149 180 exit 0
+1 -1
tools/perf/tests/shell/test_arm_coresight.sh
··· 70 70 # 68.12% touch libc-2.27.so [.] _dl_addr 71 71 # 5.80% touch libc-2.27.so [.] getenv 72 72 # 4.35% touch ld-2.27.so [.] _dl_fixup 73 - perf report --itrace=i1000i --stdio -i ${perfdata} 2>&1 | \ 73 + perf report --itrace=i20i --stdio -i ${perfdata} 2>&1 | \ 74 74 egrep " +[0-9]+\.[0-9]+% +$1" > /dev/null 2>&1 75 75 } 76 76
+377 -8
tools/perf/tests/shell/test_intel_pt.sh
··· 22 22 errfile="${temp_dir}/test-err.txt" 23 23 workload="${temp_dir}/workload" 24 24 awkscript="${temp_dir}/awkscript" 25 + jitdump_workload="${temp_dir}/jitdump_workload" 26 + maxbrstack="${temp_dir}/maxbrstack.py" 25 27 26 28 cleanup() 27 29 { ··· 43 41 } 44 42 45 43 trap trap_cleanup EXIT TERM INT 44 + 45 + # perf record for testing without decoding 46 + perf_record_no_decode() 47 + { 48 + # Options to speed up recording: no post-processing, no build-id cache update, 49 + # and no BPF events. 50 + perf record -B -N --no-bpf-event "$@" 51 + } 52 + 53 + # perf record for testing should not need BPF events 54 + perf_record_no_bpf() 55 + { 56 + # Options for no BPF events 57 + perf record --no-bpf-event "$@" 58 + } 46 59 47 60 have_workload=false 48 61 cat << _end_of_file_ | /usr/bin/cc -o "${workload}" -xc - -pthread && have_workload=true ··· 93 76 can_cpu_wide() 94 77 { 95 78 echo "Checking for CPU-wide recording on CPU $1" 96 - if ! perf record -o "${tmpfile}" -B -N --no-bpf-event -e dummy:u -C "$1" true >/dev/null 2>&1 ; then 79 + if ! perf_record_no_decode -o "${tmpfile}" -e dummy:u -C "$1" true >/dev/null 2>&1 ; then 97 80 echo "No so skipping" 98 81 return 2 99 82 fi ··· 110 93 can_cpu_wide 1 || return $? 111 94 112 95 # Record on CPU 0 a task running on CPU 1 113 - perf record -B -N --no-bpf-event -o "${perfdatafile}" -e intel_pt//u -C 0 -- taskset --cpu-list 1 uname 96 + perf_record_no_decode -o "${perfdatafile}" -e intel_pt//u -C 0 -- taskset --cpu-list 1 uname 114 97 115 98 # Should get MMAP events from CPU 1 because they can be needed to decode 116 99 mmap_cnt=$(perf script -i "${perfdatafile}" --no-itrace --show-mmap-events -C 1 2>/dev/null | grep -c MMAP) ··· 126 109 127 110 can_kernel() 128 111 { 129 - perf record -o "${tmpfile}" -B -N --no-bpf-event -e dummy:k true >/dev/null 2>&1 || return 2 112 + if [ -z "${can_kernel_trace}" ] ; then 113 + can_kernel_trace=0 114 + perf_record_no_decode -o "${tmpfile}" -e dummy:k true >/dev/null 2>&1 && can_kernel_trace=1 115 + fi 116 + if [ ${can_kernel_trace} -eq 0 ] ; then 117 + echo "SKIP: no kernel tracing" 118 + return 2 119 + fi 130 120 return 0 131 121 } 132 122 ··· 259 235 wait_for_threads ${w1} 2 260 236 wait_for_threads ${w2} 2 261 237 262 - perf record -B -N --no-bpf-event -o "${perfdatafile}" -e intel_pt//u"${k}" -vvv --per-thread -p "${w1},${w2}" 2>"${errfile}" >"${outfile}" & 238 + perf_record_no_decode -o "${perfdatafile}" -e intel_pt//u"${k}" -vvv --per-thread -p "${w1},${w2}" 2>"${errfile}" >"${outfile}" & 263 239 ppid=$! 264 240 echo "perf PID is $ppid" 265 241 wait_for_perf_to_start ${ppid} "${errfile}" || return 1 ··· 278 254 return 0 279 255 } 280 256 257 + test_jitdump() 258 + { 259 + echo "--- Test tracing self-modifying code that uses jitdump ---" 260 + 261 + script_path=$(realpath "$0") 262 + script_dir=$(dirname "$script_path") 263 + jitdump_incl_dir="${script_dir}/../../util" 264 + jitdump_h="${jitdump_incl_dir}/jitdump.h" 265 + 266 + if [ ! -e "${jitdump_h}" ] ; then 267 + echo "SKIP: Include file jitdump.h not found" 268 + return 2 269 + fi 270 + 271 + if [ -z "${have_jitdump_workload}" ] ; then 272 + have_jitdump_workload=false 273 + # Create a workload that uses self-modifying code and generates its own jitdump file 274 + cat <<- "_end_of_file_" | /usr/bin/cc -o "${jitdump_workload}" -I "${jitdump_incl_dir}" -xc - -pthread && have_jitdump_workload=true 275 + #define _GNU_SOURCE 276 + #include <sys/mman.h> 277 + #include <sys/types.h> 278 + #include <stddef.h> 279 + #include <stdio.h> 280 + #include <stdint.h> 281 + #include <unistd.h> 282 + #include <string.h> 283 + 284 + #include "jitdump.h" 285 + 286 + #define CHK_BYTE 0x5a 287 + 288 + static inline uint64_t rdtsc(void) 289 + { 290 + unsigned int low, high; 291 + 292 + asm volatile("rdtsc" : "=a" (low), "=d" (high)); 293 + 294 + return low | ((uint64_t)high) << 32; 295 + } 296 + 297 + static FILE *open_jitdump(void) 298 + { 299 + struct jitheader header = { 300 + .magic = JITHEADER_MAGIC, 301 + .version = JITHEADER_VERSION, 302 + .total_size = sizeof(header), 303 + .pid = getpid(), 304 + .timestamp = rdtsc(), 305 + .flags = JITDUMP_FLAGS_ARCH_TIMESTAMP, 306 + }; 307 + char filename[256]; 308 + FILE *f; 309 + void *m; 310 + 311 + snprintf(filename, sizeof(filename), "jit-%d.dump", getpid()); 312 + f = fopen(filename, "w+"); 313 + if (!f) 314 + goto err; 315 + /* Create an MMAP event for the jitdump file. That is how perf tool finds it. */ 316 + m = mmap(0, 4096, PROT_READ | PROT_EXEC, MAP_PRIVATE, fileno(f), 0); 317 + if (m == MAP_FAILED) 318 + goto err_close; 319 + munmap(m, 4096); 320 + if (fwrite(&header,sizeof(header),1,f) != 1) 321 + goto err_close; 322 + return f; 323 + 324 + err_close: 325 + fclose(f); 326 + err: 327 + return NULL; 328 + } 329 + 330 + static int write_jitdump(FILE *f, void *addr, const uint8_t *dat, size_t sz, uint64_t *idx) 331 + { 332 + struct jr_code_load rec = { 333 + .p.id = JIT_CODE_LOAD, 334 + .p.total_size = sizeof(rec) + sz, 335 + .p.timestamp = rdtsc(), 336 + .pid = getpid(), 337 + .tid = gettid(), 338 + .vma = (unsigned long)addr, 339 + .code_addr = (unsigned long)addr, 340 + .code_size = sz, 341 + .code_index = ++*idx, 342 + }; 343 + 344 + if (fwrite(&rec,sizeof(rec),1,f) != 1 || 345 + fwrite(dat, sz, 1, f) != 1) 346 + return -1; 347 + return 0; 348 + } 349 + 350 + static void close_jitdump(FILE *f) 351 + { 352 + fclose(f); 353 + } 354 + 355 + int main() 356 + { 357 + /* Get a memory page to store executable code */ 358 + void *addr = mmap(0, 4096, PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 359 + /* Code to execute: mov CHK_BYTE, %eax ; ret */ 360 + uint8_t dat[] = {0xb8, CHK_BYTE, 0x00, 0x00, 0x00, 0xc3}; 361 + FILE *f = open_jitdump(); 362 + uint64_t idx = 0; 363 + int ret = 1; 364 + 365 + if (!f) 366 + return 1; 367 + /* Copy executable code to executable memory page */ 368 + memcpy(addr, dat, sizeof(dat)); 369 + /* Record it in the jitdump file */ 370 + if (write_jitdump(f, addr, dat, sizeof(dat), &idx)) 371 + goto out_close; 372 + /* Call it */ 373 + ret = ((int (*)(void))addr)() - CHK_BYTE; 374 + out_close: 375 + close_jitdump(f); 376 + return ret; 377 + } 378 + _end_of_file_ 379 + fi 380 + 381 + if ! $have_jitdump_workload ; then 382 + echo "SKIP: No jitdump workload" 383 + return 2 384 + fi 385 + 386 + # Change to temp_dir so jitdump collateral files go there 387 + cd "${temp_dir}" 388 + perf_record_no_bpf -o "${tmpfile}" -e intel_pt//u "${jitdump_workload}" 389 + perf inject -i "${tmpfile}" -o "${perfdatafile}" --jit 390 + decode_br_cnt=$(perf script -i "${perfdatafile}" --itrace=b | wc -l) 391 + # Note that overflow and lost errors are suppressed for the error count 392 + decode_err_cnt=$(perf script -i "${perfdatafile}" --itrace=e-o-l | grep -ci error) 393 + cd - 394 + # Should be thousands of branches 395 + if [ "${decode_br_cnt}" -lt 1000 ] ; then 396 + echo "Decode failed, only ${decode_br_cnt} branches" 397 + return 1 398 + fi 399 + # Should be no errors 400 + if [ "${decode_err_cnt}" -ne 0 ] ; then 401 + echo "Decode failed, ${decode_err_cnt} errors" 402 + perf script -i "${perfdatafile}" --itrace=e-o-l --show-mmap-events | cat 403 + return 1 404 + fi 405 + 406 + echo OK 407 + return 0 408 + } 409 + 410 + test_packet_filter() 411 + { 412 + echo "--- Test with MTC and TSC disabled ---" 413 + # Disable MTC and TSC 414 + perf_record_no_decode -o "${perfdatafile}" -e intel_pt/mtc=0,tsc=0/u uname 415 + # Should not get MTC packet 416 + mtc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "MTC 0x") 417 + if [ "${mtc_cnt}" -ne 0 ] ; then 418 + echo "Failed to filter with mtc=0" 419 + return 1 420 + fi 421 + # Should not get TSC package 422 + tsc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "TSC 0x") 423 + if [ "${tsc_cnt}" -ne 0 ] ; then 424 + echo "Failed to filter with tsc=0" 425 + return 1 426 + fi 427 + echo OK 428 + return 0 429 + } 430 + 431 + test_disable_branch() 432 + { 433 + echo "--- Test with branches disabled ---" 434 + # Disable branch 435 + perf_record_no_decode -o "${perfdatafile}" -e intel_pt/branch=0/u uname 436 + # Should not get branch related packets 437 + tnt_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "TNT 0x") 438 + tip_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "TIP 0x") 439 + fup_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "FUP 0x") 440 + if [ "${tnt_cnt}" -ne 0 ] || [ "${tip_cnt}" -ne 0 ] || [ "${fup_cnt}" -ne 0 ] ; then 441 + echo "Failed to disable branches" 442 + return 1 443 + fi 444 + echo OK 445 + return 0 446 + } 447 + 448 + test_time_cyc() 449 + { 450 + echo "--- Test with/without CYC ---" 451 + # Check if CYC is supported 452 + cyc=$(cat /sys/bus/event_source/devices/intel_pt/caps/psb_cyc) 453 + if [ "${cyc}" != "1" ] ; then 454 + echo "SKIP: CYC is not supported" 455 + return 2 456 + fi 457 + # Enable CYC 458 + perf_record_no_decode -o "${perfdatafile}" -e intel_pt/cyc/u uname 459 + # should get CYC packets 460 + cyc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "CYC 0x") 461 + if [ "${cyc_cnt}" = "0" ] ; then 462 + echo "Failed to get CYC packet" 463 + return 1 464 + fi 465 + # Without CYC 466 + perf_record_no_decode -o "${perfdatafile}" -e intel_pt//u uname 467 + # Should not get CYC packets 468 + cyc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "CYC 0x") 469 + if [ "${cyc_cnt}" -gt 0 ] ; then 470 + echo "Still get CYC packet without cyc" 471 + return 1 472 + fi 473 + echo OK 474 + return 0 475 + } 476 + 477 + test_sample() 478 + { 479 + echo "--- Test recording with sample mode ---" 480 + # Check if recording with sample mode is working 481 + if ! perf_record_no_decode -o "${perfdatafile}" --aux-sample=8192 -e '{intel_pt//u,branch-misses:u}' uname ; then 482 + echo "perf record failed with --aux-sample" 483 + return 1 484 + fi 485 + echo OK 486 + return 0 487 + } 488 + 489 + test_kernel_trace() 490 + { 491 + echo "--- Test with kernel trace ---" 492 + # Check if recording with kernel trace is working 493 + can_kernel || return 2 494 + if ! perf_record_no_decode -o "${perfdatafile}" -e intel_pt//k -m1,128 uname ; then 495 + echo "perf record failed with intel_pt//k" 496 + return 1 497 + fi 498 + echo OK 499 + return 0 500 + } 501 + 502 + test_virtual_lbr() 503 + { 504 + echo "--- Test virtual LBR ---" 505 + 506 + # Python script to determine the maximum size of branch stacks 507 + cat << "_end_of_file_" > "${maxbrstack}" 508 + from __future__ import print_function 509 + 510 + bmax = 0 511 + 512 + def process_event(param_dict): 513 + if "brstack" in param_dict: 514 + brstack = param_dict["brstack"] 515 + n = len(brstack) 516 + global bmax 517 + if n > bmax: 518 + bmax = n 519 + 520 + def trace_end(): 521 + print("max brstack", bmax) 522 + _end_of_file_ 523 + 524 + # Check if virtual lbr is working 525 + perf_record_no_bpf -o "${perfdatafile}" --aux-sample -e '{intel_pt//,cycles}:u' uname 526 + times_val=$(perf script -i "${perfdatafile}" --itrace=L -s "${maxbrstack}" 2>/dev/null | grep "max brstack " | cut -d " " -f 3) 527 + case "${times_val}" in 528 + [0-9]*) ;; 529 + *) times_val=0;; 530 + esac 531 + if [ "${times_val}" -lt 2 ] ; then 532 + echo "Failed with virtual lbr" 533 + return 1 534 + fi 535 + echo OK 536 + return 0 537 + } 538 + 539 + test_power_event() 540 + { 541 + echo "--- Test power events ---" 542 + # Check if power events are supported 543 + power_event=$(cat /sys/bus/event_source/devices/intel_pt/caps/power_event_trace) 544 + if [ "${power_event}" != "1" ] ; then 545 + echo "SKIP: power_event_trace is not supported" 546 + return 2 547 + fi 548 + if ! perf_record_no_decode -o "${perfdatafile}" -a -e intel_pt/pwr_evt/u uname ; then 549 + echo "perf record failed with pwr_evt" 550 + return 1 551 + fi 552 + echo OK 553 + return 0 554 + } 555 + 556 + test_no_tnt() 557 + { 558 + echo "--- Test with TNT packets disabled ---" 559 + # Check if TNT disable is supported 560 + notnt=$(cat /sys/bus/event_source/devices/intel_pt/caps/tnt_disable) 561 + if [ "${notnt}" != "1" ] ; then 562 + echo "SKIP: tnt_disable is not supported" 563 + return 2 564 + fi 565 + perf_record_no_decode -o "${perfdatafile}" -e intel_pt/notnt/u uname 566 + # Should be no TNT packets 567 + tnt_cnt=$(perf script -i "${perfdatafile}" -D | grep -c TNT) 568 + if [ "${tnt_cnt}" -ne 0 ] ; then 569 + echo "TNT packets still there after notnt" 570 + return 1 571 + fi 572 + echo OK 573 + return 0 574 + } 575 + 576 + test_event_trace() 577 + { 578 + echo "--- Test with event_trace ---" 579 + # Check if event_trace is supported 580 + event_trace=$(cat /sys/bus/event_source/devices/intel_pt/caps/event_trace) 581 + if [ "${event_trace}" != 1 ] ; then 582 + echo "SKIP: event_trace is not supported" 583 + return 2 584 + fi 585 + if ! perf_record_no_decode -o "${perfdatafile}" -e intel_pt/event/u uname ; then 586 + echo "perf record failed with event trace" 587 + return 1 588 + fi 589 + echo OK 590 + return 0 591 + } 592 + 281 593 count_result() 282 594 { 283 595 if [ "$1" -eq 2 ] ; then ··· 625 265 return 626 266 fi 627 267 err_cnt=$((err_cnt + 1)) 628 - ret=0 629 268 } 630 269 631 270 ret=0 632 - test_system_wide_side_band || ret=$? ; count_result $ret 633 - test_per_thread "" "" || ret=$? ; count_result $ret 634 - test_per_thread "k" "(incl. kernel) " || ret=$? ; count_result $ret 271 + test_system_wide_side_band || ret=$? ; count_result $ret ; ret=0 272 + test_per_thread "" "" || ret=$? ; count_result $ret ; ret=0 273 + test_per_thread "k" "(incl. kernel) " || ret=$? ; count_result $ret ; ret=0 274 + test_jitdump || ret=$? ; count_result $ret ; ret=0 275 + test_packet_filter || ret=$? ; count_result $ret ; ret=0 276 + test_disable_branch || ret=$? ; count_result $ret ; ret=0 277 + test_time_cyc || ret=$? ; count_result $ret ; ret=0 278 + test_sample || ret=$? ; count_result $ret ; ret=0 279 + test_kernel_trace || ret=$? ; count_result $ret ; ret=0 280 + test_virtual_lbr || ret=$? ; count_result $ret ; ret=0 281 + test_power_event || ret=$? ; count_result $ret ; ret=0 282 + test_no_tnt || ret=$? ; count_result $ret ; ret=0 283 + test_event_trace || ret=$? ; count_result $ret ; ret=0 635 284 636 285 cleanup 637 286
+2
tools/perf/util/Build
··· 118 118 perf-$(CONFIG_AUXTRACE) += intel-bts.o 119 119 perf-$(CONFIG_AUXTRACE) += arm-spe.o 120 120 perf-$(CONFIG_AUXTRACE) += arm-spe-decoder/ 121 + perf-$(CONFIG_AUXTRACE) += hisi-ptt.o 122 + perf-$(CONFIG_AUXTRACE) += hisi-ptt-decoder/ 121 123 perf-$(CONFIG_AUXTRACE) += s390-cpumsf.o 122 124 123 125 ifdef CONFIG_LIBOPENCSD
+4
tools/perf/util/auxtrace.c
··· 52 52 #include "intel-pt.h" 53 53 #include "intel-bts.h" 54 54 #include "arm-spe.h" 55 + #include "hisi-ptt.h" 55 56 #include "s390-cpumsf.h" 56 57 #include "util/mmap.h" 57 58 ··· 1320 1319 break; 1321 1320 case PERF_AUXTRACE_S390_CPUMSF: 1322 1321 err = s390_cpumsf_process_auxtrace_info(event, session); 1322 + break; 1323 + case PERF_AUXTRACE_HISI_PTT: 1324 + err = hisi_ptt_process_auxtrace_info(event, session); 1323 1325 break; 1324 1326 case PERF_AUXTRACE_UNKNOWN: 1325 1327 default:
+1
tools/perf/util/auxtrace.h
··· 48 48 PERF_AUXTRACE_CS_ETM, 49 49 PERF_AUXTRACE_ARM_SPE, 50 50 PERF_AUXTRACE_S390_CPUMSF, 51 + PERF_AUXTRACE_HISI_PTT, 51 52 }; 52 53 53 54 enum itrace_period_type {
+28 -1
tools/perf/util/bpf_skel/bperf_cgroup.bpf.c
··· 43 43 __uint(value_size, sizeof(struct bpf_perf_event_value)); 44 44 } cgrp_readings SEC(".maps"); 45 45 46 + /* new kernel cgroup definition */ 47 + struct cgroup___new { 48 + int level; 49 + struct cgroup *ancestors[]; 50 + } __attribute__((preserve_access_index)); 51 + 52 + /* old kernel cgroup definition */ 53 + struct cgroup___old { 54 + int level; 55 + u64 ancestor_ids[]; 56 + } __attribute__((preserve_access_index)); 57 + 46 58 const volatile __u32 num_events = 1; 47 59 const volatile __u32 num_cpus = 1; 48 60 49 61 int enabled = 0; 50 62 int use_cgroup_v2 = 0; 51 63 int perf_subsys_id = -1; 64 + 65 + static inline __u64 get_cgroup_v1_ancestor_id(struct cgroup *cgrp, int level) 66 + { 67 + /* recast pointer to capture new type for compiler */ 68 + struct cgroup___new *cgrp_new = (void *)cgrp; 69 + 70 + if (bpf_core_field_exists(cgrp_new->ancestors)) { 71 + return BPF_CORE_READ(cgrp_new, ancestors[level], kn, id); 72 + } else { 73 + /* recast pointer to capture old type for compiler */ 74 + struct cgroup___old *cgrp_old = (void *)cgrp; 75 + 76 + return BPF_CORE_READ(cgrp_old, ancestor_ids[level]); 77 + } 78 + } 52 79 53 80 static inline int get_cgroup_v1_idx(__u32 *cgrps, int size) 54 81 { ··· 104 77 break; 105 78 106 79 // convert cgroup-id to a map index 107 - cgrp_id = BPF_CORE_READ(cgrp, ancestors[i], kn, id); 80 + cgrp_id = get_cgroup_v1_ancestor_id(cgrp, i); 108 81 elem = bpf_map_lookup_elem(&cgrp_idx, &cgrp_id); 109 82 if (!elem) 110 83 continue;
+3 -1
tools/perf/util/genelf.h
··· 2 2 #ifndef __GENELF_H__ 3 3 #define __GENELF_H__ 4 4 5 + #include <linux/math.h> 6 + 5 7 /* genelf.c */ 6 8 int jit_write_elf(int fd, uint64_t code_addr, const char *sym, 7 9 const void *code, int csize, void *debug, int nr_debug_entries, ··· 78 76 #endif 79 77 80 78 /* The .text section is directly after the ELF header */ 81 - #define GEN_ELF_TEXT_OFFSET sizeof(Elf_Ehdr) 79 + #define GEN_ELF_TEXT_OFFSET round_up(sizeof(Elf_Ehdr) + sizeof(Elf_Phdr), 16) 82 80 83 81 #endif
+1
tools/perf/util/hisi-ptt-decoder/Build
··· 1 + perf-$(CONFIG_AUXTRACE) += hisi-ptt-pkt-decoder.o
+164
tools/perf/util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * HiSilicon PCIe Trace and Tuning (PTT) support 4 + * Copyright (c) 2022 HiSilicon Technologies Co., Ltd. 5 + */ 6 + 7 + #include <stdlib.h> 8 + #include <stdio.h> 9 + #include <string.h> 10 + #include <endian.h> 11 + #include <byteswap.h> 12 + #include <linux/bitops.h> 13 + #include <stdarg.h> 14 + 15 + #include "../color.h" 16 + #include "hisi-ptt-pkt-decoder.h" 17 + 18 + /* 19 + * For 8DW format, the bit[31:11] of DW0 is always 0x1fffff, which can be 20 + * used to distinguish the data format. 21 + * 8DW format is like: 22 + * bits [ 31:11 ][ 10:0 ] 23 + * |---------------------------------------|-------------------| 24 + * DW0 [ 0x1fffff ][ Reserved (0x7ff) ] 25 + * DW1 [ Prefix ] 26 + * DW2 [ Header DW0 ] 27 + * DW3 [ Header DW1 ] 28 + * DW4 [ Header DW2 ] 29 + * DW5 [ Header DW3 ] 30 + * DW6 [ Reserved (0x0) ] 31 + * DW7 [ Time ] 32 + * 33 + * 4DW format is like: 34 + * bits [31:30] [ 29:25 ][24][23][22][21][ 20:11 ][ 10:0 ] 35 + * |-----|---------|---|---|---|---|-------------|-------------| 36 + * DW0 [ Fmt ][ Type ][T9][T8][TH][SO][ Length ][ Time ] 37 + * DW1 [ Header DW1 ] 38 + * DW2 [ Header DW2 ] 39 + * DW3 [ Header DW3 ] 40 + */ 41 + 42 + enum hisi_ptt_8dw_pkt_field_type { 43 + HISI_PTT_8DW_CHK_AND_RSV0, 44 + HISI_PTT_8DW_PREFIX, 45 + HISI_PTT_8DW_HEAD0, 46 + HISI_PTT_8DW_HEAD1, 47 + HISI_PTT_8DW_HEAD2, 48 + HISI_PTT_8DW_HEAD3, 49 + HISI_PTT_8DW_RSV1, 50 + HISI_PTT_8DW_TIME, 51 + HISI_PTT_8DW_TYPE_MAX 52 + }; 53 + 54 + enum hisi_ptt_4dw_pkt_field_type { 55 + HISI_PTT_4DW_HEAD1, 56 + HISI_PTT_4DW_HEAD2, 57 + HISI_PTT_4DW_HEAD3, 58 + HISI_PTT_4DW_TYPE_MAX 59 + }; 60 + 61 + static const char * const hisi_ptt_8dw_pkt_field_name[] = { 62 + [HISI_PTT_8DW_PREFIX] = "Prefix", 63 + [HISI_PTT_8DW_HEAD0] = "Header DW0", 64 + [HISI_PTT_8DW_HEAD1] = "Header DW1", 65 + [HISI_PTT_8DW_HEAD2] = "Header DW2", 66 + [HISI_PTT_8DW_HEAD3] = "Header DW3", 67 + [HISI_PTT_8DW_TIME] = "Time" 68 + }; 69 + 70 + static const char * const hisi_ptt_4dw_pkt_field_name[] = { 71 + [HISI_PTT_4DW_HEAD1] = "Header DW1", 72 + [HISI_PTT_4DW_HEAD2] = "Header DW2", 73 + [HISI_PTT_4DW_HEAD3] = "Header DW3", 74 + }; 75 + 76 + union hisi_ptt_4dw { 77 + struct { 78 + uint32_t format : 2; 79 + uint32_t type : 5; 80 + uint32_t t9 : 1; 81 + uint32_t t8 : 1; 82 + uint32_t th : 1; 83 + uint32_t so : 1; 84 + uint32_t len : 10; 85 + uint32_t time : 11; 86 + }; 87 + uint32_t value; 88 + }; 89 + 90 + static void hisi_ptt_print_pkt(const unsigned char *buf, int pos, const char *desc) 91 + { 92 + const char *color = PERF_COLOR_BLUE; 93 + int i; 94 + 95 + printf("."); 96 + color_fprintf(stdout, color, " %08x: ", pos); 97 + for (i = 0; i < HISI_PTT_FIELD_LENTH; i++) 98 + color_fprintf(stdout, color, "%02x ", buf[pos + i]); 99 + for (i = 0; i < HISI_PTT_MAX_SPACE_LEN; i++) 100 + color_fprintf(stdout, color, " "); 101 + color_fprintf(stdout, color, " %s\n", desc); 102 + } 103 + 104 + static int hisi_ptt_8dw_kpt_desc(const unsigned char *buf, int pos) 105 + { 106 + int i; 107 + 108 + for (i = 0; i < HISI_PTT_8DW_TYPE_MAX; i++) { 109 + /* Do not show 8DW check field and reserved fields */ 110 + if (i == HISI_PTT_8DW_CHK_AND_RSV0 || i == HISI_PTT_8DW_RSV1) { 111 + pos += HISI_PTT_FIELD_LENTH; 112 + continue; 113 + } 114 + 115 + hisi_ptt_print_pkt(buf, pos, hisi_ptt_8dw_pkt_field_name[i]); 116 + pos += HISI_PTT_FIELD_LENTH; 117 + } 118 + 119 + return hisi_ptt_pkt_size[HISI_PTT_8DW_PKT]; 120 + } 121 + 122 + static void hisi_ptt_4dw_print_dw0(const unsigned char *buf, int pos) 123 + { 124 + const char *color = PERF_COLOR_BLUE; 125 + union hisi_ptt_4dw dw0; 126 + int i; 127 + 128 + dw0.value = *(uint32_t *)(buf + pos); 129 + printf("."); 130 + color_fprintf(stdout, color, " %08x: ", pos); 131 + for (i = 0; i < HISI_PTT_FIELD_LENTH; i++) 132 + color_fprintf(stdout, color, "%02x ", buf[pos + i]); 133 + for (i = 0; i < HISI_PTT_MAX_SPACE_LEN; i++) 134 + color_fprintf(stdout, color, " "); 135 + 136 + color_fprintf(stdout, color, 137 + " %s %x %s %x %s %x %s %x %s %x %s %x %s %x %s %x\n", 138 + "Format", dw0.format, "Type", dw0.type, "T9", dw0.t9, 139 + "T8", dw0.t8, "TH", dw0.th, "SO", dw0.so, "Length", 140 + dw0.len, "Time", dw0.time); 141 + } 142 + 143 + static int hisi_ptt_4dw_kpt_desc(const unsigned char *buf, int pos) 144 + { 145 + int i; 146 + 147 + hisi_ptt_4dw_print_dw0(buf, pos); 148 + pos += HISI_PTT_FIELD_LENTH; 149 + 150 + for (i = 0; i < HISI_PTT_4DW_TYPE_MAX; i++) { 151 + hisi_ptt_print_pkt(buf, pos, hisi_ptt_4dw_pkt_field_name[i]); 152 + pos += HISI_PTT_FIELD_LENTH; 153 + } 154 + 155 + return hisi_ptt_pkt_size[HISI_PTT_4DW_PKT]; 156 + } 157 + 158 + int hisi_ptt_pkt_desc(const unsigned char *buf, int pos, enum hisi_ptt_pkt_type type) 159 + { 160 + if (type == HISI_PTT_8DW_PKT) 161 + return hisi_ptt_8dw_kpt_desc(buf, pos); 162 + 163 + return hisi_ptt_4dw_kpt_desc(buf, pos); 164 + }
+31
tools/perf/util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * HiSilicon PCIe Trace and Tuning (PTT) support 4 + * Copyright (c) 2022 HiSilicon Technologies Co., Ltd. 5 + */ 6 + 7 + #ifndef INCLUDE__HISI_PTT_PKT_DECODER_H__ 8 + #define INCLUDE__HISI_PTT_PKT_DECODER_H__ 9 + 10 + #include <stddef.h> 11 + #include <stdint.h> 12 + 13 + #define HISI_PTT_8DW_CHECK_MASK GENMASK(31, 11) 14 + #define HISI_PTT_IS_8DW_PKT GENMASK(31, 11) 15 + #define HISI_PTT_MAX_SPACE_LEN 10 16 + #define HISI_PTT_FIELD_LENTH 4 17 + 18 + enum hisi_ptt_pkt_type { 19 + HISI_PTT_4DW_PKT, 20 + HISI_PTT_8DW_PKT, 21 + HISI_PTT_PKT_MAX 22 + }; 23 + 24 + static int hisi_ptt_pkt_size[] = { 25 + [HISI_PTT_4DW_PKT] = 16, 26 + [HISI_PTT_8DW_PKT] = 32, 27 + }; 28 + 29 + int hisi_ptt_pkt_desc(const unsigned char *buf, int pos, enum hisi_ptt_pkt_type type); 30 + 31 + #endif
+192
tools/perf/util/hisi-ptt.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * HiSilicon PCIe Trace and Tuning (PTT) support 4 + * Copyright (c) 2022 HiSilicon Technologies Co., Ltd. 5 + */ 6 + 7 + #include <byteswap.h> 8 + #include <endian.h> 9 + #include <errno.h> 10 + #include <inttypes.h> 11 + #include <linux/bitops.h> 12 + #include <linux/kernel.h> 13 + #include <linux/log2.h> 14 + #include <linux/types.h> 15 + #include <linux/zalloc.h> 16 + #include <stdlib.h> 17 + #include <unistd.h> 18 + 19 + #include "auxtrace.h" 20 + #include "color.h" 21 + #include "debug.h" 22 + #include "evsel.h" 23 + #include "hisi-ptt.h" 24 + #include "hisi-ptt-decoder/hisi-ptt-pkt-decoder.h" 25 + #include "machine.h" 26 + #include "session.h" 27 + #include "tool.h" 28 + #include <internal/lib.h> 29 + 30 + struct hisi_ptt { 31 + struct auxtrace auxtrace; 32 + u32 auxtrace_type; 33 + struct perf_session *session; 34 + struct machine *machine; 35 + u32 pmu_type; 36 + }; 37 + 38 + struct hisi_ptt_queue { 39 + struct hisi_ptt *ptt; 40 + struct auxtrace_buffer *buffer; 41 + }; 42 + 43 + static enum hisi_ptt_pkt_type hisi_ptt_check_packet_type(unsigned char *buf) 44 + { 45 + uint32_t head = *(uint32_t *)buf; 46 + 47 + if ((HISI_PTT_8DW_CHECK_MASK & head) == HISI_PTT_IS_8DW_PKT) 48 + return HISI_PTT_8DW_PKT; 49 + 50 + return HISI_PTT_4DW_PKT; 51 + } 52 + 53 + static void hisi_ptt_dump(struct hisi_ptt *ptt __maybe_unused, 54 + unsigned char *buf, size_t len) 55 + { 56 + const char *color = PERF_COLOR_BLUE; 57 + enum hisi_ptt_pkt_type type; 58 + size_t pos = 0; 59 + int pkt_len; 60 + 61 + type = hisi_ptt_check_packet_type(buf); 62 + len = round_down(len, hisi_ptt_pkt_size[type]); 63 + color_fprintf(stdout, color, ". ... HISI PTT data: size %zu bytes\n", 64 + len); 65 + 66 + while (len > 0) { 67 + pkt_len = hisi_ptt_pkt_desc(buf, pos, type); 68 + if (!pkt_len) 69 + color_fprintf(stdout, color, " Bad packet!\n"); 70 + 71 + pos += pkt_len; 72 + len -= pkt_len; 73 + } 74 + } 75 + 76 + static void hisi_ptt_dump_event(struct hisi_ptt *ptt, unsigned char *buf, 77 + size_t len) 78 + { 79 + printf(".\n"); 80 + 81 + hisi_ptt_dump(ptt, buf, len); 82 + } 83 + 84 + static int hisi_ptt_process_event(struct perf_session *session __maybe_unused, 85 + union perf_event *event __maybe_unused, 86 + struct perf_sample *sample __maybe_unused, 87 + struct perf_tool *tool __maybe_unused) 88 + { 89 + return 0; 90 + } 91 + 92 + static int hisi_ptt_process_auxtrace_event(struct perf_session *session, 93 + union perf_event *event, 94 + struct perf_tool *tool __maybe_unused) 95 + { 96 + struct hisi_ptt *ptt = container_of(session->auxtrace, struct hisi_ptt, 97 + auxtrace); 98 + int fd = perf_data__fd(session->data); 99 + int size = event->auxtrace.size; 100 + void *data = malloc(size); 101 + off_t data_offset; 102 + int err; 103 + 104 + if (!data) 105 + return -errno; 106 + 107 + if (perf_data__is_pipe(session->data)) { 108 + data_offset = 0; 109 + } else { 110 + data_offset = lseek(fd, 0, SEEK_CUR); 111 + if (data_offset == -1) 112 + return -errno; 113 + } 114 + 115 + err = readn(fd, data, size); 116 + if (err != (ssize_t)size) { 117 + free(data); 118 + return -errno; 119 + } 120 + 121 + if (dump_trace) 122 + hisi_ptt_dump_event(ptt, data, size); 123 + 124 + return 0; 125 + } 126 + 127 + static int hisi_ptt_flush(struct perf_session *session __maybe_unused, 128 + struct perf_tool *tool __maybe_unused) 129 + { 130 + return 0; 131 + } 132 + 133 + static void hisi_ptt_free_events(struct perf_session *session __maybe_unused) 134 + { 135 + } 136 + 137 + static void hisi_ptt_free(struct perf_session *session) 138 + { 139 + struct hisi_ptt *ptt = container_of(session->auxtrace, struct hisi_ptt, 140 + auxtrace); 141 + 142 + session->auxtrace = NULL; 143 + free(ptt); 144 + } 145 + 146 + static bool hisi_ptt_evsel_is_auxtrace(struct perf_session *session, 147 + struct evsel *evsel) 148 + { 149 + struct hisi_ptt *ptt = container_of(session->auxtrace, struct hisi_ptt, auxtrace); 150 + 151 + return evsel->core.attr.type == ptt->pmu_type; 152 + } 153 + 154 + static void hisi_ptt_print_info(__u64 type) 155 + { 156 + if (!dump_trace) 157 + return; 158 + 159 + fprintf(stdout, " PMU Type %" PRId64 "\n", (s64) type); 160 + } 161 + 162 + int hisi_ptt_process_auxtrace_info(union perf_event *event, 163 + struct perf_session *session) 164 + { 165 + struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info; 166 + struct hisi_ptt *ptt; 167 + 168 + if (auxtrace_info->header.size < HISI_PTT_AUXTRACE_PRIV_SIZE + 169 + sizeof(struct perf_record_auxtrace_info)) 170 + return -EINVAL; 171 + 172 + ptt = zalloc(sizeof(*ptt)); 173 + if (!ptt) 174 + return -ENOMEM; 175 + 176 + ptt->session = session; 177 + ptt->machine = &session->machines.host; /* No kvm support */ 178 + ptt->auxtrace_type = auxtrace_info->type; 179 + ptt->pmu_type = auxtrace_info->priv[0]; 180 + 181 + ptt->auxtrace.process_event = hisi_ptt_process_event; 182 + ptt->auxtrace.process_auxtrace_event = hisi_ptt_process_auxtrace_event; 183 + ptt->auxtrace.flush_events = hisi_ptt_flush; 184 + ptt->auxtrace.free_events = hisi_ptt_free_events; 185 + ptt->auxtrace.free = hisi_ptt_free; 186 + ptt->auxtrace.evsel_is_auxtrace = hisi_ptt_evsel_is_auxtrace; 187 + session->auxtrace = &ptt->auxtrace; 188 + 189 + hisi_ptt_print_info(auxtrace_info->priv[0]); 190 + 191 + return 0; 192 + }
+19
tools/perf/util/hisi-ptt.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * HiSilicon PCIe Trace and Tuning (PTT) support 4 + * Copyright (c) 2022 HiSilicon Technologies Co., Ltd. 5 + */ 6 + 7 + #ifndef INCLUDE__PERF_HISI_PTT_H__ 8 + #define INCLUDE__PERF_HISI_PTT_H__ 9 + 10 + #define HISI_PTT_PMU_NAME "hisi_ptt" 11 + #define HISI_PTT_AUXTRACE_PRIV_SIZE sizeof(u64) 12 + 13 + struct auxtrace_record *hisi_ptt_recording_init(int *err, 14 + struct perf_pmu *hisi_ptt_pmu); 15 + 16 + int hisi_ptt_process_auxtrace_info(union perf_event *event, 17 + struct perf_session *session); 18 + 19 + #endif
+7 -2
tools/perf/util/intel-pt.c
··· 4046 4046 [INTEL_PT_SNAPSHOT_MODE] = " Snapshot mode %"PRId64"\n", 4047 4047 [INTEL_PT_PER_CPU_MMAPS] = " Per-cpu maps %"PRId64"\n", 4048 4048 [INTEL_PT_MTC_BIT] = " MTC bit %#"PRIx64"\n", 4049 + [INTEL_PT_MTC_FREQ_BITS] = " MTC freq bits %#"PRIx64"\n", 4049 4050 [INTEL_PT_TSC_CTC_N] = " TSC:CTC numerator %"PRIu64"\n", 4050 4051 [INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n", 4051 4052 [INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n", ··· 4061 4060 if (!dump_trace) 4062 4061 return; 4063 4062 4064 - for (i = start; i <= finish; i++) 4065 - fprintf(stdout, intel_pt_info_fmts[i], arr[i]); 4063 + for (i = start; i <= finish; i++) { 4064 + const char *fmt = intel_pt_info_fmts[i]; 4065 + 4066 + if (fmt) 4067 + fprintf(stdout, fmt, arr[i]); 4068 + } 4066 4069 } 4067 4070 4068 4071 static void intel_pt_print_info_str(const char *name, const char *str)
+3
tools/perf/util/parse-events.c
··· 246 246 struct perf_cpu_map *cpus = pmu ? perf_cpu_map__get(pmu->cpus) : 247 247 cpu_list ? perf_cpu_map__new(cpu_list) : NULL; 248 248 249 + if (pmu) 250 + perf_pmu__warn_invalid_formats(pmu); 251 + 249 252 if (pmu && attr->type == PERF_TYPE_RAW) 250 253 perf_pmu__warn_invalid_config(pmu, attr->config, name); 251 254
+17
tools/perf/util/pmu.c
··· 1005 1005 return NULL; 1006 1006 } 1007 1007 1008 + void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu) 1009 + { 1010 + struct perf_pmu_format *format; 1011 + 1012 + /* fake pmu doesn't have format list */ 1013 + if (pmu == &perf_pmu__fake) 1014 + return; 1015 + 1016 + list_for_each_entry(format, &pmu->format, list) 1017 + if (format->value >= PERF_PMU_FORMAT_VALUE_CONFIG_END) { 1018 + pr_warning("WARNING: '%s' format '%s' requires 'perf_event_attr::config%d'" 1019 + "which is not supported by this version of perf!\n", 1020 + pmu->name, format->name, format->value); 1021 + return; 1022 + } 1023 + } 1024 + 1008 1025 static struct perf_pmu *pmu_find(const char *name) 1009 1026 { 1010 1027 struct perf_pmu *pmu;
+2
tools/perf/util/pmu.h
··· 17 17 PERF_PMU_FORMAT_VALUE_CONFIG, 18 18 PERF_PMU_FORMAT_VALUE_CONFIG1, 19 19 PERF_PMU_FORMAT_VALUE_CONFIG2, 20 + PERF_PMU_FORMAT_VALUE_CONFIG_END, 20 21 }; 21 22 22 23 #define PERF_PMU_FORMAT_BITS 64 ··· 140 139 141 140 void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config, 142 141 const char *name); 142 + void perf_pmu__warn_invalid_formats(struct perf_pmu *pmu); 143 143 144 144 bool perf_pmu__has_hybrid(void); 145 145 int perf_pmu__match(char *pattern, char *name, char *tok);
-2
tools/perf/util/pmu.l
··· 27 27 28 28 {num_dec} { return value(10); } 29 29 config { return PP_CONFIG; } 30 - config1 { return PP_CONFIG1; } 31 - config2 { return PP_CONFIG2; } 32 30 - { return '-'; } 33 31 : { return ':'; } 34 32 , { return ','; }
+4 -11
tools/perf/util/pmu.y
··· 18 18 19 19 %} 20 20 21 - %token PP_CONFIG PP_CONFIG1 PP_CONFIG2 21 + %token PP_CONFIG 22 22 %token PP_VALUE PP_ERROR 23 23 %type <num> PP_VALUE 24 24 %type <bits> bit_term ··· 45 45 $3)); 46 46 } 47 47 | 48 - PP_CONFIG1 ':' bits 48 + PP_CONFIG PP_VALUE ':' bits 49 49 { 50 50 ABORT_ON(perf_pmu__new_format(format, name, 51 - PERF_PMU_FORMAT_VALUE_CONFIG1, 52 - $3)); 53 - } 54 - | 55 - PP_CONFIG2 ':' bits 56 - { 57 - ABORT_ON(perf_pmu__new_format(format, name, 58 - PERF_PMU_FORMAT_VALUE_CONFIG2, 59 - $3)); 51 + $2, 52 + $4)); 60 53 } 61 54 62 55 bits: