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-fixes-for-v5.18-2022-04-09' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull perf tools fixes from Arnaldo Carvalho de Melo:

- Fix the clang command line option probing and remove some options to
filter out, fixing the build with the latest clang versions

- Fix 'perf bench' futex and epoll benchmarks to deal with machines
with more than 1K CPUs

- Fix 'perf test tsc' error message when not supported

- Remap perf ring buffer if there is no space for event, fixing perf
usage in 32-bit ChromeOS

- Drop objdump stderr to avoid getting stuck waiting for stdout output
in 'perf annotate'

- Fix up garbled output by now showing unwind error messages when
augmenting frame in best effort mode

- Fix perf's libperf_print callback, use the va_args eprintf() variant

- Sync vhost and arm64 cputype headers with the kernel sources

- Fix 'perf report --mem-mode' with ARM SPE

- Add missing external commands ('iiostat', etc) to 'perf --list-cmds'

* tag 'perf-tools-fixes-for-v5.18-2022-04-09' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux:
perf annotate: Drop objdump stderr to avoid getting stuck waiting for stdout output
perf tools: Add external commands to list-cmds
perf docs: Add perf-iostat link to manpages
perf session: Remap buf if there is no space for event
perf bench: Fix epoll bench to correct usage of affinity for machines with #CPUs > 1K
perf bench: Fix futex bench to correct usage of affinity for machines with #CPUs > 1K
perf tools: Fix perf's libperf_print callback
perf: arm-spe: Fix perf report --mem-mode
perf unwind: Don't show unwind error messages when augmenting frame pointer stack
tools headers arm64: Sync arm64's cputype.h with the kernel sources
perf test tsc: Fix error message when not supported
perf build: Don't use -ffat-lto-objects in the python feature test when building with clang-13
perf python: Fix probing for some clang command line options
tools build: Filter out options and warnings not supported by clang
tools build: Use $(shell ) instead of `` to get embedded libperl's ccopts
tools include UAPI: Sync linux/vhost.h with the kernel sources

+234 -71
+2
tools/arch/arm64/include/asm/cputype.h
··· 75 75 #define ARM_CPU_PART_CORTEX_A77 0xD0D 76 76 #define ARM_CPU_PART_NEOVERSE_V1 0xD40 77 77 #define ARM_CPU_PART_CORTEX_A78 0xD41 78 + #define ARM_CPU_PART_CORTEX_A78AE 0xD42 78 79 #define ARM_CPU_PART_CORTEX_X1 0xD44 79 80 #define ARM_CPU_PART_CORTEX_A510 0xD46 80 81 #define ARM_CPU_PART_CORTEX_A710 0xD47 ··· 131 130 #define MIDR_CORTEX_A77 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77) 132 131 #define MIDR_NEOVERSE_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V1) 133 132 #define MIDR_CORTEX_A78 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78) 133 + #define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE) 134 134 #define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1) 135 135 #define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510) 136 136 #define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
+8 -1
tools/build/feature/Makefile
··· 217 217 PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null) 218 218 PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS)) 219 219 PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS)) 220 - PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` 220 + PERL_EMBED_CCOPTS = $(shell perl -MExtUtils::Embed -e ccopts 2>/dev/null) 221 221 FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) 222 + 223 + ifeq ($(CC_NO_CLANG), 0) 224 + PERL_EMBED_LDOPTS := $(filter-out -specs=%,$(PERL_EMBED_LDOPTS)) 225 + PERL_EMBED_CCOPTS := $(filter-out -flto=auto -ffat-lto-objects, $(PERL_EMBED_CCOPTS)) 226 + PERL_EMBED_CCOPTS := $(filter-out -specs=%,$(PERL_EMBED_CCOPTS)) 227 + FLAGS_PERL_EMBED += -Wno-compound-token-split-by-macro 228 + endif 222 229 223 230 $(OUTPUT)test-libperl.bin: 224 231 $(BUILD) $(FLAGS_PERL_EMBED)
+7
tools/include/uapi/linux/vhost.h
··· 150 150 /* Get the valid iova range */ 151 151 #define VHOST_VDPA_GET_IOVA_RANGE _IOR(VHOST_VIRTIO, 0x78, \ 152 152 struct vhost_vdpa_iova_range) 153 + 154 + /* Get the config size */ 155 + #define VHOST_VDPA_GET_CONFIG_SIZE _IOR(VHOST_VIRTIO, 0x79, __u32) 156 + 157 + /* Get the count of all virtqueues */ 158 + #define VHOST_VDPA_GET_VQS_COUNT _IOR(VHOST_VIRTIO, 0x80, __u32) 159 + 153 160 #endif
+1 -1
tools/perf/Documentation/perf.txt
··· 83 83 linkperf:perf-config[1], linkperf:perf-data[1], linkperf:perf-diff[1], 84 84 linkperf:perf-evlist[1], linkperf:perf-ftrace[1], 85 85 linkperf:perf-help[1], linkperf:perf-inject[1], 86 - linkperf:perf-intel-pt[1], linkperf:perf-kallsyms[1], 86 + linkperf:perf-intel-pt[1], linkperf:perf-iostat[1], linkperf:perf-kallsyms[1], 87 87 linkperf:perf-kmem[1], linkperf:perf-kvm[1], linkperf:perf-lock[1], 88 88 linkperf:perf-mem[1], linkperf:perf-probe[1], linkperf:perf-sched[1], 89 89 linkperf:perf-script[1], linkperf:perf-test[1],
+6
tools/perf/Makefile.config
··· 272 272 PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil 273 273 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --includes 2>/dev/null) 274 274 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 275 + ifeq ($(CC_NO_CLANG), 0) 276 + PYTHON_EMBED_CCOPTS := $(filter-out -ffat-lto-objects, $(PYTHON_EMBED_CCOPTS)) 277 + endif 275 278 endif 276 279 277 280 FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS) ··· 793 790 LDFLAGS += $(PERL_EMBED_LDFLAGS) 794 791 EXTLIBS += $(PERL_EMBED_LIBADD) 795 792 CFLAGS += -DHAVE_LIBPERL_SUPPORT 793 + ifeq ($(CC_NO_CLANG), 0) 794 + CFLAGS += -Wno-compound-token-split-by-macro 795 + endif 796 796 $(call detected,CONFIG_LIBPERL) 797 797 endif 798 798 endif
+6
tools/perf/arch/arm64/util/arm-spe.c
··· 239 239 arm_spe_set_timestamp(itr, arm_spe_evsel); 240 240 } 241 241 242 + /* 243 + * Set this only so that perf report knows that SPE generates memory info. It has no effect 244 + * on the opening of the event or the SPE data produced. 245 + */ 246 + evsel__set_sample_bit(arm_spe_evsel, DATA_SRC); 247 + 242 248 /* Add dummy event to keep tracking */ 243 249 err = parse_events(evlist, "dummy:u", NULL); 244 250 if (err)
+19 -6
tools/perf/bench/epoll-ctl.c
··· 222 222 static int do_threads(struct worker *worker, struct perf_cpu_map *cpu) 223 223 { 224 224 pthread_attr_t thread_attr, *attrp = NULL; 225 - cpu_set_t cpuset; 225 + cpu_set_t *cpuset; 226 226 unsigned int i, j; 227 227 int ret = 0; 228 + int nrcpus; 229 + size_t size; 228 230 229 231 if (!noaffinity) 230 232 pthread_attr_init(&thread_attr); 233 + 234 + nrcpus = perf_cpu_map__nr(cpu); 235 + cpuset = CPU_ALLOC(nrcpus); 236 + BUG_ON(!cpuset); 237 + size = CPU_ALLOC_SIZE(nrcpus); 231 238 232 239 for (i = 0; i < nthreads; i++) { 233 240 struct worker *w = &worker[i]; ··· 259 252 init_fdmaps(w, 50); 260 253 261 254 if (!noaffinity) { 262 - CPU_ZERO(&cpuset); 263 - CPU_SET(perf_cpu_map__cpu(cpu, i % perf_cpu_map__nr(cpu)).cpu, &cpuset); 255 + CPU_ZERO_S(size, cpuset); 256 + CPU_SET_S(perf_cpu_map__cpu(cpu, i % perf_cpu_map__nr(cpu)).cpu, 257 + size, cpuset); 264 258 265 - ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset); 266 - if (ret) 259 + ret = pthread_attr_setaffinity_np(&thread_attr, size, cpuset); 260 + if (ret) { 261 + CPU_FREE(cpuset); 267 262 err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); 263 + } 268 264 269 265 attrp = &thread_attr; 270 266 } 271 267 272 268 ret = pthread_create(&w->thread, attrp, workerfn, 273 269 (void *)(struct worker *) w); 274 - if (ret) 270 + if (ret) { 271 + CPU_FREE(cpuset); 275 272 err(EXIT_FAILURE, "pthread_create"); 273 + } 276 274 } 277 275 276 + CPU_FREE(cpuset); 278 277 if (!noaffinity) 279 278 pthread_attr_destroy(&thread_attr); 280 279
+19 -6
tools/perf/bench/epoll-wait.c
··· 291 291 static int do_threads(struct worker *worker, struct perf_cpu_map *cpu) 292 292 { 293 293 pthread_attr_t thread_attr, *attrp = NULL; 294 - cpu_set_t cpuset; 294 + cpu_set_t *cpuset; 295 295 unsigned int i, j; 296 296 int ret = 0, events = EPOLLIN; 297 + int nrcpus; 298 + size_t size; 297 299 298 300 if (oneshot) 299 301 events |= EPOLLONESHOT; ··· 307 305 nonblocking ? " (nonblocking)":""); 308 306 if (!noaffinity) 309 307 pthread_attr_init(&thread_attr); 308 + 309 + nrcpus = perf_cpu_map__nr(cpu); 310 + cpuset = CPU_ALLOC(nrcpus); 311 + BUG_ON(!cpuset); 312 + size = CPU_ALLOC_SIZE(nrcpus); 310 313 311 314 for (i = 0; i < nthreads; i++) { 312 315 struct worker *w = &worker[i]; ··· 348 341 } 349 342 350 343 if (!noaffinity) { 351 - CPU_ZERO(&cpuset); 352 - CPU_SET(perf_cpu_map__cpu(cpu, i % perf_cpu_map__nr(cpu)).cpu, &cpuset); 344 + CPU_ZERO_S(size, cpuset); 345 + CPU_SET_S(perf_cpu_map__cpu(cpu, i % perf_cpu_map__nr(cpu)).cpu, 346 + size, cpuset); 353 347 354 - ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset); 355 - if (ret) 348 + ret = pthread_attr_setaffinity_np(&thread_attr, size, cpuset); 349 + if (ret) { 350 + CPU_FREE(cpuset); 356 351 err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); 352 + } 357 353 358 354 attrp = &thread_attr; 359 355 } 360 356 361 357 ret = pthread_create(&w->thread, attrp, workerfn, 362 358 (void *)(struct worker *) w); 363 - if (ret) 359 + if (ret) { 360 + CPU_FREE(cpuset); 364 361 err(EXIT_FAILURE, "pthread_create"); 362 + } 365 363 } 366 364 365 + CPU_FREE(cpuset); 367 366 if (!noaffinity) 368 367 pthread_attr_destroy(&thread_attr); 369 368
+19 -7
tools/perf/bench/futex-hash.c
··· 122 122 int bench_futex_hash(int argc, const char **argv) 123 123 { 124 124 int ret = 0; 125 - cpu_set_t cpuset; 125 + cpu_set_t *cpuset; 126 126 struct sigaction act; 127 127 unsigned int i; 128 128 pthread_attr_t thread_attr; 129 129 struct worker *worker = NULL; 130 130 struct perf_cpu_map *cpu; 131 + int nrcpus; 132 + size_t size; 131 133 132 134 argc = parse_options(argc, argv, options, bench_futex_hash_usage, 0); 133 135 if (argc) { ··· 172 170 threads_starting = params.nthreads; 173 171 pthread_attr_init(&thread_attr); 174 172 gettimeofday(&bench__start, NULL); 173 + 174 + nrcpus = perf_cpu_map__nr(cpu); 175 + cpuset = CPU_ALLOC(nrcpus); 176 + BUG_ON(!cpuset); 177 + size = CPU_ALLOC_SIZE(nrcpus); 178 + 175 179 for (i = 0; i < params.nthreads; i++) { 176 180 worker[i].tid = i; 177 181 worker[i].futex = calloc(params.nfutexes, sizeof(*worker[i].futex)); 178 182 if (!worker[i].futex) 179 183 goto errmem; 180 184 181 - CPU_ZERO(&cpuset); 182 - CPU_SET(perf_cpu_map__cpu(cpu, i % perf_cpu_map__nr(cpu)).cpu, &cpuset); 185 + CPU_ZERO_S(size, cpuset); 183 186 184 - ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset); 185 - if (ret) 187 + CPU_SET_S(perf_cpu_map__cpu(cpu, i % perf_cpu_map__nr(cpu)).cpu, size, cpuset); 188 + ret = pthread_attr_setaffinity_np(&thread_attr, size, cpuset); 189 + if (ret) { 190 + CPU_FREE(cpuset); 186 191 err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); 187 - 192 + } 188 193 ret = pthread_create(&worker[i].thread, &thread_attr, workerfn, 189 194 (void *)(struct worker *) &worker[i]); 190 - if (ret) 195 + if (ret) { 196 + CPU_FREE(cpuset); 191 197 err(EXIT_FAILURE, "pthread_create"); 198 + } 192 199 193 200 } 201 + CPU_FREE(cpuset); 194 202 pthread_attr_destroy(&thread_attr); 195 203 196 204 pthread_mutex_lock(&thread_lock);
+16 -5
tools/perf/bench/futex-lock-pi.c
··· 120 120 static void create_threads(struct worker *w, pthread_attr_t thread_attr, 121 121 struct perf_cpu_map *cpu) 122 122 { 123 - cpu_set_t cpuset; 123 + cpu_set_t *cpuset; 124 124 unsigned int i; 125 + int nrcpus = perf_cpu_map__nr(cpu); 126 + size_t size; 125 127 126 128 threads_starting = params.nthreads; 129 + 130 + cpuset = CPU_ALLOC(nrcpus); 131 + BUG_ON(!cpuset); 132 + size = CPU_ALLOC_SIZE(nrcpus); 127 133 128 134 for (i = 0; i < params.nthreads; i++) { 129 135 worker[i].tid = i; ··· 141 135 } else 142 136 worker[i].futex = &global_futex; 143 137 144 - CPU_ZERO(&cpuset); 145 - CPU_SET(perf_cpu_map__cpu(cpu, i % perf_cpu_map__nr(cpu)).cpu, &cpuset); 138 + CPU_ZERO_S(size, cpuset); 139 + CPU_SET_S(perf_cpu_map__cpu(cpu, i % perf_cpu_map__nr(cpu)).cpu, size, cpuset); 146 140 147 - if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset)) 141 + if (pthread_attr_setaffinity_np(&thread_attr, size, cpuset)) { 142 + CPU_FREE(cpuset); 148 143 err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); 144 + } 149 145 150 - if (pthread_create(&w[i].thread, &thread_attr, workerfn, &worker[i])) 146 + if (pthread_create(&w[i].thread, &thread_attr, workerfn, &worker[i])) { 147 + CPU_FREE(cpuset); 151 148 err(EXIT_FAILURE, "pthread_create"); 149 + } 152 150 } 151 + CPU_FREE(cpuset); 153 152 } 154 153 155 154 int bench_futex_lock_pi(int argc, const char **argv)
+16 -5
tools/perf/bench/futex-requeue.c
··· 123 123 static void block_threads(pthread_t *w, 124 124 pthread_attr_t thread_attr, struct perf_cpu_map *cpu) 125 125 { 126 - cpu_set_t cpuset; 126 + cpu_set_t *cpuset; 127 127 unsigned int i; 128 + int nrcpus = perf_cpu_map__nr(cpu); 129 + size_t size; 128 130 129 131 threads_starting = params.nthreads; 130 132 133 + cpuset = CPU_ALLOC(nrcpus); 134 + BUG_ON(!cpuset); 135 + size = CPU_ALLOC_SIZE(nrcpus); 136 + 131 137 /* create and block all threads */ 132 138 for (i = 0; i < params.nthreads; i++) { 133 - CPU_ZERO(&cpuset); 134 - CPU_SET(perf_cpu_map__cpu(cpu, i % perf_cpu_map__nr(cpu)).cpu, &cpuset); 139 + CPU_ZERO_S(size, cpuset); 140 + CPU_SET_S(perf_cpu_map__cpu(cpu, i % perf_cpu_map__nr(cpu)).cpu, size, cpuset); 135 141 136 - if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset)) 142 + if (pthread_attr_setaffinity_np(&thread_attr, size, cpuset)) { 143 + CPU_FREE(cpuset); 137 144 err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); 145 + } 138 146 139 - if (pthread_create(&w[i], &thread_attr, workerfn, NULL)) 147 + if (pthread_create(&w[i], &thread_attr, workerfn, NULL)) { 148 + CPU_FREE(cpuset); 140 149 err(EXIT_FAILURE, "pthread_create"); 150 + } 141 151 } 152 + CPU_FREE(cpuset); 142 153 } 143 154 144 155 static void toggle_done(int sig __maybe_unused,
+16 -5
tools/perf/bench/futex-wake-parallel.c
··· 144 144 static void block_threads(pthread_t *w, pthread_attr_t thread_attr, 145 145 struct perf_cpu_map *cpu) 146 146 { 147 - cpu_set_t cpuset; 147 + cpu_set_t *cpuset; 148 148 unsigned int i; 149 + int nrcpus = perf_cpu_map__nr(cpu); 150 + size_t size; 149 151 150 152 threads_starting = params.nthreads; 151 153 154 + cpuset = CPU_ALLOC(nrcpus); 155 + BUG_ON(!cpuset); 156 + size = CPU_ALLOC_SIZE(nrcpus); 157 + 152 158 /* create and block all threads */ 153 159 for (i = 0; i < params.nthreads; i++) { 154 - CPU_ZERO(&cpuset); 155 - CPU_SET(perf_cpu_map__cpu(cpu, i % perf_cpu_map__nr(cpu)).cpu, &cpuset); 160 + CPU_ZERO_S(size, cpuset); 161 + CPU_SET_S(perf_cpu_map__cpu(cpu, i % perf_cpu_map__nr(cpu)).cpu, size, cpuset); 156 162 157 - if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset)) 163 + if (pthread_attr_setaffinity_np(&thread_attr, size, cpuset)) { 164 + CPU_FREE(cpuset); 158 165 err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); 166 + } 159 167 160 - if (pthread_create(&w[i], &thread_attr, blocked_workerfn, NULL)) 168 + if (pthread_create(&w[i], &thread_attr, blocked_workerfn, NULL)) { 169 + CPU_FREE(cpuset); 161 170 err(EXIT_FAILURE, "pthread_create"); 171 + } 162 172 } 173 + CPU_FREE(cpuset); 163 174 } 164 175 165 176 static void print_run(struct thread_data *waking_worker, unsigned int run_num)
+16 -6
tools/perf/bench/futex-wake.c
··· 97 97 static void block_threads(pthread_t *w, 98 98 pthread_attr_t thread_attr, struct perf_cpu_map *cpu) 99 99 { 100 - cpu_set_t cpuset; 100 + cpu_set_t *cpuset; 101 101 unsigned int i; 102 - 102 + size_t size; 103 + int nrcpus = perf_cpu_map__nr(cpu); 103 104 threads_starting = params.nthreads; 105 + 106 + cpuset = CPU_ALLOC(nrcpus); 107 + BUG_ON(!cpuset); 108 + size = CPU_ALLOC_SIZE(nrcpus); 104 109 105 110 /* create and block all threads */ 106 111 for (i = 0; i < params.nthreads; i++) { 107 - CPU_ZERO(&cpuset); 108 - CPU_SET(perf_cpu_map__cpu(cpu, i % perf_cpu_map__nr(cpu)).cpu, &cpuset); 112 + CPU_ZERO_S(size, cpuset); 113 + CPU_SET_S(perf_cpu_map__cpu(cpu, i % perf_cpu_map__nr(cpu)).cpu, size, cpuset); 109 114 110 - if (pthread_attr_setaffinity_np(&thread_attr, sizeof(cpu_set_t), &cpuset)) 115 + if (pthread_attr_setaffinity_np(&thread_attr, size, cpuset)) { 116 + CPU_FREE(cpuset); 111 117 err(EXIT_FAILURE, "pthread_attr_setaffinity_np"); 118 + } 112 119 113 - if (pthread_create(&w[i], &thread_attr, workerfn, NULL)) 120 + if (pthread_create(&w[i], &thread_attr, workerfn, NULL)) { 121 + CPU_FREE(cpuset); 114 122 err(EXIT_FAILURE, "pthread_create"); 123 + } 115 124 } 125 + CPU_FREE(cpuset); 116 126 } 117 127 118 128 static void toggle_done(int sig __maybe_unused,
+5 -1
tools/perf/perf.c
··· 55 55 }; 56 56 57 57 static struct cmd_struct commands[] = { 58 + { "archive", NULL, 0 }, 58 59 { "buildid-cache", cmd_buildid_cache, 0 }, 59 60 { "buildid-list", cmd_buildid_list, 0 }, 60 61 { "config", cmd_config, 0 }, ··· 63 62 { "diff", cmd_diff, 0 }, 64 63 { "evlist", cmd_evlist, 0 }, 65 64 { "help", cmd_help, 0 }, 65 + { "iostat", NULL, 0 }, 66 66 { "kallsyms", cmd_kallsyms, 0 }, 67 67 { "list", cmd_list, 0 }, 68 68 { "record", cmd_record, 0 }, ··· 362 360 363 361 for (i = 0; i < ARRAY_SIZE(commands); i++) { 364 362 struct cmd_struct *p = commands+i; 363 + if (p->fn == NULL) 364 + continue; 365 365 if (strcmp(p->cmd, cmd)) 366 366 continue; 367 367 exit(run_builtin(p, argc, argv)); ··· 438 434 static int libperf_print(enum libperf_print_level level, 439 435 const char *fmt, va_list ap) 440 436 { 441 - return eprintf(level, verbose, fmt, ap); 437 + return veprintf(level, verbose, fmt, ap); 442 438 } 443 439 444 440 int main(int argc, const char **argv)
+1 -1
tools/perf/tests/dwarf-unwind.c
··· 122 122 } 123 123 124 124 err = unwind__get_entries(unwind_entry, &cnt, thread, 125 - &sample, MAX_STACK); 125 + &sample, MAX_STACK, false); 126 126 if (err) 127 127 pr_debug("unwind failed\n"); 128 128 else if (cnt != MAX_STACK) {
+27 -9
tools/perf/tests/perf-time-to-tsc.c
··· 47 47 } \ 48 48 } 49 49 50 + static int test__tsc_is_supported(struct test_suite *test __maybe_unused, 51 + int subtest __maybe_unused) 52 + { 53 + if (!TSC_IS_SUPPORTED) { 54 + pr_debug("Test not supported on this architecture\n"); 55 + return TEST_SKIP; 56 + } 57 + 58 + return TEST_OK; 59 + } 60 + 50 61 /** 51 62 * test__perf_time_to_tsc - test converting perf time to TSC. 52 63 * ··· 81 70 struct perf_cpu_map *cpus = NULL; 82 71 struct evlist *evlist = NULL; 83 72 struct evsel *evsel = NULL; 84 - int err = -1, ret, i; 73 + int err = TEST_FAIL, ret, i; 85 74 const char *comm1, *comm2; 86 75 struct perf_tsc_conversion tc; 87 76 struct perf_event_mmap_page *pc; ··· 90 79 u64 test_time, comm1_time = 0, comm2_time = 0; 91 80 struct mmap *md; 92 81 93 - if (!TSC_IS_SUPPORTED) { 94 - pr_debug("Test not supported on this architecture"); 95 - return TEST_SKIP; 96 - } 97 82 98 83 threads = thread_map__new(-1, getpid(), UINT_MAX); 99 84 CHECK_NOT_NULL__(threads); ··· 131 124 ret = perf_read_tsc_conversion(pc, &tc); 132 125 if (ret) { 133 126 if (ret == -EOPNOTSUPP) { 134 - fprintf(stderr, " (not supported)"); 135 - return 0; 127 + pr_debug("perf_read_tsc_conversion is not supported in current kernel\n"); 128 + err = TEST_SKIP; 136 129 } 137 130 goto out_err; 138 131 } ··· 198 191 test_tsc >= comm2_tsc) 199 192 goto out_err; 200 193 201 - err = 0; 194 + err = TEST_OK; 202 195 203 196 out_err: 204 197 evlist__delete(evlist); ··· 207 200 return err; 208 201 } 209 202 210 - DEFINE_SUITE("Convert perf time to TSC", perf_time_to_tsc); 203 + static struct test_case time_to_tsc_tests[] = { 204 + TEST_CASE_REASON("TSC support", tsc_is_supported, 205 + "This architecture does not support"), 206 + TEST_CASE_REASON("Perf time to TSC", perf_time_to_tsc, 207 + "perf_read_tsc_conversion is not supported"), 208 + { .name = NULL, } 209 + }; 210 + 211 + struct test_suite suite__perf_time_to_tsc = { 212 + .desc = "Convert perf time to TSC", 213 + .test_cases = time_to_tsc_tests, 214 + };
+1
tools/perf/util/annotate.c
··· 2047 2047 objdump_process.argv = objdump_argv; 2048 2048 objdump_process.out = -1; 2049 2049 objdump_process.err = -1; 2050 + objdump_process.no_stderr = 1; 2050 2051 if (start_command(&objdump_process)) { 2051 2052 pr_err("Failure starting to run %s\n", command); 2052 2053 err = -1;
+1 -1
tools/perf/util/arm64-frame-pointer-unwind-support.c
··· 53 53 sample->user_regs.cache_regs[PERF_REG_ARM64_SP] = 0; 54 54 } 55 55 56 - ret = unwind__get_entries(add_entry, &entries, thread, sample, 2); 56 + ret = unwind__get_entries(add_entry, &entries, thread, sample, 2, true); 57 57 sample->user_regs = old_regs; 58 58 59 59 if (ret || entries.length != 2)
+1 -1
tools/perf/util/machine.c
··· 2987 2987 return 0; 2988 2988 2989 2989 return unwind__get_entries(unwind_entry, cursor, 2990 - thread, sample, max_stack); 2990 + thread, sample, max_stack, false); 2991 2991 } 2992 2992 2993 2993 int thread__resolve_callchain(struct thread *thread,
+12 -3
tools/perf/util/session.c
··· 2095 2095 bool needs_swap, union perf_event *error) 2096 2096 { 2097 2097 union perf_event *event; 2098 + u16 event_size; 2098 2099 2099 2100 /* 2100 2101 * Ensure we have enough space remaining to read ··· 2108 2107 if (needs_swap) 2109 2108 perf_event_header__bswap(&event->header); 2110 2109 2111 - if (head + event->header.size <= mmap_size) 2110 + event_size = event->header.size; 2111 + if (head + event_size <= mmap_size) 2112 2112 return event; 2113 2113 2114 2114 /* We're not fetching the event so swap back again */ 2115 2115 if (needs_swap) 2116 2116 perf_event_header__bswap(&event->header); 2117 2117 2118 - pr_debug("%s: head=%#" PRIx64 " event->header_size=%#x, mmap_size=%#zx:" 2119 - " fuzzed or compressed perf.data?\n",__func__, head, event->header.size, mmap_size); 2118 + /* Check if the event fits into the next mmapped buf. */ 2119 + if (event_size <= mmap_size - head % page_size) { 2120 + /* Remap buf and fetch again. */ 2121 + return NULL; 2122 + } 2123 + 2124 + /* Invalid input. Event size should never exceed mmap_size. */ 2125 + pr_debug("%s: head=%#" PRIx64 " event->header.size=%#x, mmap_size=%#zx:" 2126 + " fuzzed or compressed perf.data?\n", __func__, head, event_size, mmap_size); 2120 2127 2121 2128 return error; 2122 2129 }
+6 -2
tools/perf/util/setup.py
··· 1 - from os import getenv 1 + from os import getenv, path 2 2 from subprocess import Popen, PIPE 3 3 from re import sub 4 4 5 5 cc = getenv("CC") 6 6 cc_is_clang = b"clang version" in Popen([cc.split()[0], "-v"], stderr=PIPE).stderr.readline() 7 + src_feature_tests = getenv('srctree') + '/tools/build/feature' 7 8 8 9 def clang_has_option(option): 9 - return [o for o in Popen([cc, option], stderr=PIPE).stderr.readlines() if b"unknown argument" in o] == [ ] 10 + cc_output = Popen([cc, option, path.join(src_feature_tests, "test-hello.c") ], stderr=PIPE).stderr.readlines() 11 + return [o for o in cc_output if ((b"unknown argument" in o) or (b"is not supported" in o))] == [ ] 10 12 11 13 if cc_is_clang: 12 14 from distutils.sysconfig import get_config_vars ··· 25 23 vars[var] = sub("-fstack-protector-strong", "", vars[var]) 26 24 if not clang_has_option("-fno-semantic-interposition"): 27 25 vars[var] = sub("-fno-semantic-interposition", "", vars[var]) 26 + if not clang_has_option("-ffat-lto-objects"): 27 + vars[var] = sub("-ffat-lto-objects", "", vars[var]) 28 28 29 29 from distutils.core import setup, Extension 30 30
+7 -3
tools/perf/util/unwind-libdw.c
··· 200 200 bool isactivation; 201 201 202 202 if (!dwfl_frame_pc(state, &pc, NULL)) { 203 - pr_err("%s", dwfl_errmsg(-1)); 203 + if (!ui->best_effort) 204 + pr_err("%s", dwfl_errmsg(-1)); 204 205 return DWARF_CB_ABORT; 205 206 } 206 207 ··· 209 208 report_module(pc, ui); 210 209 211 210 if (!dwfl_frame_pc(state, &pc, &isactivation)) { 212 - pr_err("%s", dwfl_errmsg(-1)); 211 + if (!ui->best_effort) 212 + pr_err("%s", dwfl_errmsg(-1)); 213 213 return DWARF_CB_ABORT; 214 214 } 215 215 ··· 224 222 int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 225 223 struct thread *thread, 226 224 struct perf_sample *data, 227 - int max_stack) 225 + int max_stack, 226 + bool best_effort) 228 227 { 229 228 struct unwind_info *ui, ui_buf = { 230 229 .sample = data, ··· 234 231 .cb = cb, 235 232 .arg = arg, 236 233 .max_stack = max_stack, 234 + .best_effort = best_effort 237 235 }; 238 236 Dwarf_Word ip; 239 237 int err = -EINVAL, i;
+1
tools/perf/util/unwind-libdw.h
··· 20 20 void *arg; 21 21 int max_stack; 22 22 int idx; 23 + bool best_effort; 23 24 struct unwind_entry entries[]; 24 25 }; 25 26
+7 -3
tools/perf/util/unwind-libunwind-local.c
··· 96 96 struct perf_sample *sample; 97 97 struct machine *machine; 98 98 struct thread *thread; 99 + bool best_effort; 99 100 }; 100 101 101 102 #define dw_read(ptr, type, end) ({ \ ··· 554 553 555 554 ret = perf_reg_value(&val, &ui->sample->user_regs, id); 556 555 if (ret) { 557 - pr_err("unwind: can't read reg %d\n", regnum); 556 + if (!ui->best_effort) 557 + pr_err("unwind: can't read reg %d\n", regnum); 558 558 return ret; 559 559 } 560 560 ··· 668 666 return -1; 669 667 670 668 ret = unw_init_remote(&c, addr_space, ui); 671 - if (ret) 669 + if (ret && !ui->best_effort) 672 670 display_error(ret); 673 671 674 672 while (!ret && (unw_step(&c) > 0) && i < max_stack) { ··· 706 704 707 705 static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg, 708 706 struct thread *thread, 709 - struct perf_sample *data, int max_stack) 707 + struct perf_sample *data, int max_stack, 708 + bool best_effort) 710 709 { 711 710 struct unwind_info ui = { 712 711 .sample = data, 713 712 .thread = thread, 714 713 .machine = thread->maps->machine, 714 + .best_effort = best_effort 715 715 }; 716 716 717 717 if (!data->user_regs.regs)
+4 -2
tools/perf/util/unwind-libunwind.c
··· 80 80 81 81 int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 82 82 struct thread *thread, 83 - struct perf_sample *data, int max_stack) 83 + struct perf_sample *data, int max_stack, 84 + bool best_effort) 84 85 { 85 86 if (thread->maps->unwind_libunwind_ops) 86 - return thread->maps->unwind_libunwind_ops->get_entries(cb, arg, thread, data, max_stack); 87 + return thread->maps->unwind_libunwind_ops->get_entries(cb, arg, thread, data, 88 + max_stack, best_effort); 87 89 return 0; 88 90 }
+10 -3
tools/perf/util/unwind.h
··· 23 23 void (*finish_access)(struct maps *maps); 24 24 int (*get_entries)(unwind_entry_cb_t cb, void *arg, 25 25 struct thread *thread, 26 - struct perf_sample *data, int max_stack); 26 + struct perf_sample *data, int max_stack, bool best_effort); 27 27 }; 28 28 29 29 #ifdef HAVE_DWARF_UNWIND_SUPPORT 30 + /* 31 + * When best_effort is set, don't report errors and fail silently. This could 32 + * be expanded in the future to be more permissive about things other than 33 + * error messages. 34 + */ 30 35 int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 31 36 struct thread *thread, 32 - struct perf_sample *data, int max_stack); 37 + struct perf_sample *data, int max_stack, 38 + bool best_effort); 33 39 /* libunwind specific */ 34 40 #ifdef HAVE_LIBUNWIND_SUPPORT 35 41 #ifndef LIBUNWIND__ARCH_REG_ID ··· 71 65 void *arg __maybe_unused, 72 66 struct thread *thread __maybe_unused, 73 67 struct perf_sample *data __maybe_unused, 74 - int max_stack __maybe_unused) 68 + int max_stack __maybe_unused, 69 + bool best_effort __maybe_unused) 75 70 { 76 71 return 0; 77 72 }