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.12-2020-03-28' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull perf tooling fixes from Arnaldo Carvalho de Melo:

- Avoid write of uninitialized memory when generating PERF_RECORD_MMAP*
records.

- Fix 'perf top' BPF support related crash with perf_event_paranoid=3 +
kptr_restrict.

- Validate raw event with sysfs exported format bits.

- Fix waipid on SIGCHLD delivery bugs in 'perf daemon'.

- Change to use bash for daemon test on Debian, where the default is
dash and thus fails for use of bashisms in this test.

- Fix memory leak in vDSO found using ASAN.

- Remove now useless (due to the fact that BPF now supports static
vars) failing sub test "BPF relocation checker".

- Fix auxtrace queue conflict.

- Sync linux/kvm.h with the kernel sources.

* tag 'perf-tools-fixes-for-v5.12-2020-03-28' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux:
perf test: Change to use bash for daemon test
perf record: Fix memory leak in vDSO found using ASAN
perf test: Remove now useless failing sub test "BPF relocation checker"
perf daemon: Return from kill functions
perf daemon: Force waipid for all session on SIGCHLD delivery
perf top: Fix BPF support related crash with perf_event_paranoid=3 + kptr_restrict
perf pmu: Validate raw event with sysfs exported format bits
perf synthetic events: Avoid write of uninitialized memory when generating PERF_RECORD_MMAP* records
tools headers UAPI: Sync linux/kvm.h with the kernel sources
perf synthetic-events: Fix uninitialized 'kernel_thread' variable
perf auxtrace: Fix auxtrace queue conflict

+106 -46
+13
tools/include/uapi/linux/kvm.h
··· 1154 1154 #define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0) 1155 1155 #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1) 1156 1156 #define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2) 1157 + #define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 3) 1157 1158 1158 1159 struct kvm_xen_hvm_config { 1159 1160 __u32 flags; ··· 1622 1621 union { 1623 1622 __u64 gpa; 1624 1623 __u64 pad[8]; 1624 + struct { 1625 + __u64 state; 1626 + __u64 state_entry_time; 1627 + __u64 time_running; 1628 + __u64 time_runnable; 1629 + __u64 time_blocked; 1630 + __u64 time_offline; 1631 + } runstate; 1625 1632 } u; 1626 1633 }; 1627 1634 1628 1635 /* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */ 1629 1636 #define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO 0x0 1630 1637 #define KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO 0x1 1638 + #define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR 0x2 1639 + #define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT 0x3 1640 + #define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA 0x4 1641 + #define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST 0x5 1631 1642 1632 1643 /* Secure Encrypted Virtualization command */ 1633 1644 enum sev_cmd_id {
+34 -25
tools/perf/builtin-daemon.c
··· 402 402 int status; 403 403 pid_t pid; 404 404 405 + /* 406 + * Take signal fd data as pure signal notification and check all 407 + * the sessions state. The reason is that multiple signals can get 408 + * coalesced in kernel and we can receive only single signal even 409 + * if multiple SIGCHLD were generated. 410 + */ 405 411 err = read(daemon->signal_fd, &si, sizeof(struct signalfd_siginfo)); 406 - if (err != sizeof(struct signalfd_siginfo)) 412 + if (err != sizeof(struct signalfd_siginfo)) { 413 + pr_err("failed to read signal fd\n"); 407 414 return -1; 415 + } 408 416 409 417 list_for_each_entry(session, &daemon->sessions, list) { 410 - 411 - if (session->pid != (int) si.ssi_pid) 418 + if (session->pid == -1) 412 419 continue; 413 420 414 - pid = waitpid(session->pid, &status, 0); 415 - if (pid == session->pid) { 416 - if (WIFEXITED(status)) { 417 - pr_info("session '%s' exited, status=%d\n", 418 - session->name, WEXITSTATUS(status)); 419 - } else if (WIFSIGNALED(status)) { 420 - pr_info("session '%s' killed (signal %d)\n", 421 - session->name, WTERMSIG(status)); 422 - } else if (WIFSTOPPED(status)) { 423 - pr_info("session '%s' stopped (signal %d)\n", 424 - session->name, WSTOPSIG(status)); 425 - } else { 426 - pr_info("session '%s' Unexpected status (0x%x)\n", 427 - session->name, status); 428 - } 421 + pid = waitpid(session->pid, &status, WNOHANG); 422 + if (pid <= 0) 423 + continue; 424 + 425 + if (WIFEXITED(status)) { 426 + pr_info("session '%s' exited, status=%d\n", 427 + session->name, WEXITSTATUS(status)); 428 + } else if (WIFSIGNALED(status)) { 429 + pr_info("session '%s' killed (signal %d)\n", 430 + session->name, WTERMSIG(status)); 431 + } else if (WIFSTOPPED(status)) { 432 + pr_info("session '%s' stopped (signal %d)\n", 433 + session->name, WSTOPSIG(status)); 434 + } else { 435 + pr_info("session '%s' Unexpected status (0x%x)\n", 436 + session->name, status); 429 437 } 430 438 431 439 session->state = KILL; 432 440 session->pid = -1; 433 - return pid; 434 441 } 435 442 436 443 return 0; ··· 450 443 .fd = daemon->signal_fd, 451 444 .events = POLLIN, 452 445 }; 453 - pid_t wpid = 0, pid = session->pid; 454 446 time_t start; 455 447 456 448 start = time(NULL); ··· 458 452 int err = poll(&pollfd, 1, 1000); 459 453 460 454 if (err > 0) { 461 - wpid = handle_signalfd(daemon); 455 + handle_signalfd(daemon); 462 456 } else if (err < 0) { 463 457 perror("failed: poll\n"); 464 458 return -1; ··· 466 460 467 461 if (start + secs < time(NULL)) 468 462 return -1; 469 - } while (wpid != pid); 463 + } while (session->pid != -1); 470 464 471 465 return 0; 472 466 } ··· 908 902 daemon_session__signal(session, SIGKILL); 909 903 break; 910 904 default: 911 - break; 905 + pr_err("failed to wait for session %s\n", 906 + session->name); 907 + return; 912 908 } 913 909 how++; 914 910 ··· 963 955 daemon__signal(daemon, SIGKILL); 964 956 break; 965 957 default: 966 - break; 958 + pr_err("failed to wait for sessions\n"); 959 + return; 967 960 } 968 961 how++; 969 962 ··· 1353 1344 close(sock_fd); 1354 1345 if (conf_fd != -1) 1355 1346 close(conf_fd); 1356 - if (conf_fd != -1) 1347 + if (signal_fd != -1) 1357 1348 close(signal_fd); 1358 1349 1359 1350 pr_info("daemon exited\n");
+1 -8
tools/perf/tests/bpf.c
··· 86 86 .msg_load_fail = "check your vmlinux setting?", 87 87 .target_func = &epoll_pwait_loop, 88 88 .expect_result = (NR_ITERS + 1) / 2, 89 - .pin = true, 89 + .pin = true, 90 90 }, 91 91 #ifdef HAVE_BPF_PROLOGUE 92 92 { ··· 99 99 .expect_result = (NR_ITERS + 1) / 4, 100 100 }, 101 101 #endif 102 - { 103 - .prog_id = LLVM_TESTCASE_BPF_RELOCATION, 104 - .desc = "BPF relocation checker", 105 - .name = "[bpf_relocation_test]", 106 - .msg_compile_fail = "fix 'perf test LLVM' first", 107 - .msg_load_fail = "libbpf error when dealing with relocation", 108 - }, 109 102 }; 110 103 111 104 static int do_test(struct bpf_object *obj, int (*func)(void),
+1 -1
tools/perf/tests/shell/daemon.sh
··· 1 - #!/bin/sh 1 + #!/bin/bash 2 2 # daemon operations 3 3 # SPDX-License-Identifier: GPL-2.0 4 4
-4
tools/perf/util/auxtrace.c
··· 298 298 queue->set = true; 299 299 queue->tid = buffer->tid; 300 300 queue->cpu = buffer->cpu; 301 - } else if (buffer->cpu != queue->cpu || buffer->tid != queue->tid) { 302 - pr_err("auxtrace queue conflict: cpu %d, tid %d vs cpu %d, tid %d\n", 303 - queue->cpu, queue->tid, buffer->cpu, buffer->tid); 304 - return -EINVAL; 305 301 } 306 302 307 303 buffer->buffer_nr = queues->next_buffer_nr++;
+10 -3
tools/perf/util/bpf-event.c
··· 196 196 } 197 197 198 198 if (info_linear->info_len < offsetof(struct bpf_prog_info, prog_tags)) { 199 + free(info_linear); 199 200 pr_debug("%s: the kernel is too old, aborting\n", __func__); 200 201 return -2; 201 202 } 202 203 203 204 info = &info_linear->info; 205 + if (!info->jited_ksyms) { 206 + free(info_linear); 207 + return -1; 208 + } 204 209 205 210 /* number of ksyms, func_lengths, and tags should match */ 206 211 sub_prog_cnt = info->nr_jited_ksyms; 207 212 if (sub_prog_cnt != info->nr_prog_tags || 208 - sub_prog_cnt != info->nr_jited_func_lens) 213 + sub_prog_cnt != info->nr_jited_func_lens) { 214 + free(info_linear); 209 215 return -1; 216 + } 210 217 211 218 /* check BTF func info support */ 212 219 if (info->btf_id && info->nr_func_info && info->func_info_rec_size) { 213 220 /* btf func info number should be same as sub_prog_cnt */ 214 221 if (sub_prog_cnt != info->nr_func_info) { 215 222 pr_debug("%s: mismatch in BPF sub program count and BTF function info count, aborting\n", __func__); 216 - err = -1; 217 - goto out; 223 + free(info_linear); 224 + return -1; 218 225 } 219 226 if (btf__get_from_id(info->btf_id, &btf)) { 220 227 pr_debug("%s: failed to get BTF of id %u, aborting\n", __func__, info->btf_id);
+3
tools/perf/util/parse-events.c
··· 356 356 struct perf_cpu_map *cpus = pmu ? perf_cpu_map__get(pmu->cpus) : 357 357 cpu_list ? perf_cpu_map__new(cpu_list) : NULL; 358 358 359 + if (pmu && attr->type == PERF_TYPE_RAW) 360 + perf_pmu__warn_invalid_config(pmu, attr->config, name); 361 + 359 362 if (init_attr) 360 363 event_attr_init(attr); 361 364
+33
tools/perf/util/pmu.c
··· 1812 1812 1813 1813 return nr_caps; 1814 1814 } 1815 + 1816 + void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config, 1817 + char *name) 1818 + { 1819 + struct perf_pmu_format *format; 1820 + __u64 masks = 0, bits; 1821 + char buf[100]; 1822 + unsigned int i; 1823 + 1824 + list_for_each_entry(format, &pmu->format, list) { 1825 + if (format->value != PERF_PMU_FORMAT_VALUE_CONFIG) 1826 + continue; 1827 + 1828 + for_each_set_bit(i, format->bits, PERF_PMU_FORMAT_BITS) 1829 + masks |= 1ULL << i; 1830 + } 1831 + 1832 + /* 1833 + * Kernel doesn't export any valid format bits. 1834 + */ 1835 + if (masks == 0) 1836 + return; 1837 + 1838 + bits = config & ~masks; 1839 + if (bits == 0) 1840 + return; 1841 + 1842 + bitmap_scnprintf((unsigned long *)&bits, sizeof(bits) * 8, buf, sizeof(buf)); 1843 + 1844 + pr_warning("WARNING: event '%s' not valid (bits %s of config " 1845 + "'%llx' not supported by kernel)!\n", 1846 + name ?: "N/A", buf, config); 1847 + }
+3
tools/perf/util/pmu.h
··· 123 123 124 124 int perf_pmu__caps_parse(struct perf_pmu *pmu); 125 125 126 + void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config, 127 + char *name); 128 + 126 129 #endif /* __PMU_H */
+6 -5
tools/perf/util/synthetic-events.c
··· 424 424 425 425 while (!io.eof) { 426 426 static const char anonstr[] = "//anon"; 427 - size_t size; 427 + size_t size, aligned_size; 428 428 429 429 /* ensure null termination since stack will be reused. */ 430 430 event->mmap2.filename[0] = '\0'; ··· 484 484 } 485 485 486 486 size = strlen(event->mmap2.filename) + 1; 487 - size = PERF_ALIGN(size, sizeof(u64)); 487 + aligned_size = PERF_ALIGN(size, sizeof(u64)); 488 488 event->mmap2.len -= event->mmap.start; 489 489 event->mmap2.header.size = (sizeof(event->mmap2) - 490 - (sizeof(event->mmap2.filename) - size)); 491 - memset(event->mmap2.filename + size, 0, machine->id_hdr_size); 490 + (sizeof(event->mmap2.filename) - aligned_size)); 491 + memset(event->mmap2.filename + size, 0, machine->id_hdr_size + 492 + (aligned_size - size)); 492 493 event->mmap2.header.size += machine->id_hdr_size; 493 494 event->mmap2.pid = tgid; 494 495 event->mmap2.tid = pid; ··· 759 758 for (i = 0; i < n; i++) { 760 759 char *end; 761 760 pid_t _pid; 762 - bool kernel_thread; 761 + bool kernel_thread = false; 763 762 764 763 _pid = strtol(dirent[i]->d_name, &end, 10); 765 764 if (*end)
+2
tools/perf/util/vdso.c
··· 133 133 if (dso != NULL) { 134 134 __dsos__add(&machine->dsos, dso); 135 135 dso__set_long_name(dso, long_name, false); 136 + /* Put dso here because __dsos_add already got it */ 137 + dso__put(dso); 136 138 } 137 139 138 140 return dso;