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

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

User visible changes:

o Support S/390 in 'perf kvm stat' (Alexander Yarygin)

Developer Stuff:

o Various fixes and prep work related to supporting Intel PT (Adrian Hunter)

o Introduce multiple debug variables control (Jiri Olsa)

o Add callchain and additional sample information for python scripts (Joseph Schuchart)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>

+1170 -470
+1
arch/s390/include/uapi/asm/Kbuild
··· 16 16 header-y += ipcbuf.h 17 17 header-y += kvm.h 18 18 header-y += kvm_para.h 19 + header-y += kvm_perf.h 19 20 header-y += kvm_virtio.h 20 21 header-y += mman.h 21 22 header-y += monwriter.h
+25
arch/s390/include/uapi/asm/kvm_perf.h
··· 1 + /* 2 + * Definitions for perf-kvm on s390 3 + * 4 + * Copyright 2014 IBM Corp. 5 + * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License (version 2 only) 9 + * as published by the Free Software Foundation. 10 + */ 11 + 12 + #ifndef __LINUX_KVM_PERF_S390_H 13 + #define __LINUX_KVM_PERF_S390_H 14 + 15 + #include <asm/sie.h> 16 + 17 + #define DECODE_STR_LEN 40 18 + 19 + #define VCPU_ID "id" 20 + 21 + #define KVM_ENTRY_TRACE "kvm:kvm_s390_sie_enter" 22 + #define KVM_EXIT_TRACE "kvm:kvm_s390_sie_exit" 23 + #define KVM_EXIT_REASON "icptcode" 24 + 25 + #endif
+1
arch/x86/include/uapi/asm/Kbuild
··· 22 22 header-y += ist.h 23 23 header-y += kvm.h 24 24 header-y += kvm_para.h 25 + header-y += kvm_perf.h 25 26 header-y += ldt.h 26 27 header-y += mce.h 27 28 header-y += mman.h
+16
arch/x86/include/uapi/asm/kvm_perf.h
··· 1 + #ifndef _ASM_X86_KVM_PERF_H 2 + #define _ASM_X86_KVM_PERF_H 3 + 4 + #include <asm/svm.h> 5 + #include <asm/vmx.h> 6 + #include <asm/kvm.h> 7 + 8 + #define DECODE_STR_LEN 20 9 + 10 + #define VCPU_ID "vcpu_id" 11 + 12 + #define KVM_ENTRY_TRACE "kvm:kvm_entry" 13 + #define KVM_EXIT_TRACE "kvm:kvm_exit" 14 + #define KVM_EXIT_REASON "exit_reason" 15 + 16 + #endif /* _ASM_X86_KVM_PERF_H */
+9 -7
tools/perf/Documentation/perf-kvm.txt
··· 51 51 'perf kvm stat <command>' to run a command and gather performance counter 52 52 statistics. 53 53 Especially, perf 'kvm stat record/report' generates a statistical analysis 54 - of KVM events. Currently, vmexit, mmio and ioport events are supported. 55 - 'perf kvm stat record <command>' records kvm events and the events between 56 - start and end <command>. 54 + of KVM events. Currently, vmexit, mmio (x86 only) and ioport (x86 only) 55 + events are supported. 'perf kvm stat record <command>' records kvm events 56 + and the events between start and end <command>. 57 57 And this command produces a file which contains tracing results of kvm 58 58 events. 59 59 ··· 103 103 analyze events which occures on this vcpu. (default: all vcpus) 104 104 105 105 --event=<value>:: 106 - event to be analyzed. Possible values: vmexit, mmio, ioport. 107 - (default: vmexit) 106 + event to be analyzed. Possible values: vmexit, mmio (x86 only), 107 + ioport (x86 only). (default: vmexit) 108 108 -k:: 109 109 --key=<value>:: 110 110 Sorting key. Possible values: sample (default, sort by samples ··· 138 138 139 139 140 140 --event=<value>:: 141 - event to be analyzed. Possible values: vmexit, mmio, ioport. 141 + event to be analyzed. Possible values: vmexit, 142 + mmio (x86 only), ioport (x86 only). 142 143 (default: vmexit) 143 144 144 145 -k:: ··· 148 147 number), time (sort by average time). 149 148 150 149 --duration=<value>:: 151 - Show events other than HLT that take longer than duration usecs. 150 + Show events other than HLT (x86 only) or Wait state (s390 only) 151 + that take longer than duration usecs. 152 152 153 153 SEE ALSO 154 154 --------
+9 -1
tools/perf/Documentation/perf.txt
··· 8 8 SYNOPSIS 9 9 -------- 10 10 [verse] 11 - 'perf' [--version] [--help] COMMAND [ARGS] 11 + 'perf' [--version] [--help] [OPTIONS] COMMAND [ARGS] 12 + 13 + OPTIONS 14 + ------- 15 + --debug:: 16 + Setup debug variable (just verbose for now) in value 17 + range (0, 10). Use like: 18 + --debug verbose # sets verbose = 1 19 + --debug verbose=2 # sets verbose = 2 12 20 13 21 DESCRIPTION 14 22 -----------
+3
tools/perf/MANIFEST
··· 37 37 arch/x86/include/uapi/asm/svm.h 38 38 arch/x86/include/uapi/asm/vmx.h 39 39 arch/x86/include/uapi/asm/kvm.h 40 + arch/x86/include/uapi/asm/kvm_perf.h 41 + arch/s390/include/uapi/asm/sie.h 42 + arch/s390/include/uapi/asm/kvm_perf.h
+3
tools/perf/Makefile.perf
··· 295 295 LIB_H += util/perf_regs.h 296 296 LIB_H += util/unwind.h 297 297 LIB_H += util/vdso.h 298 + LIB_H += util/tsc.h 298 299 LIB_H += ui/helpline.h 299 300 LIB_H += ui/progress.h 300 301 LIB_H += ui/util.h 301 302 LIB_H += ui/ui.h 302 303 LIB_H += util/data.h 304 + LIB_H += util/kvm-stat.h 303 305 304 306 LIB_OBJS += $(OUTPUT)util/abspath.o 305 307 LIB_OBJS += $(OUTPUT)util/alias.o ··· 375 373 LIB_OBJS += $(OUTPUT)util/record.o 376 374 LIB_OBJS += $(OUTPUT)util/srcline.o 377 375 LIB_OBJS += $(OUTPUT)util/data.o 376 + LIB_OBJS += $(OUTPUT)util/tsc.o 378 377 379 378 LIB_OBJS += $(OUTPUT)ui/setup.o 380 379 LIB_OBJS += $(OUTPUT)ui/helpline.o
+2
tools/perf/arch/s390/Makefile
··· 3 3 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o 4 4 endif 5 5 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o 6 + HAVE_KVM_STAT_SUPPORT := 1 7 + LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/kvm-stat.o
+105
tools/perf/arch/s390/util/kvm-stat.c
··· 1 + /* 2 + * Arch specific functions for perf kvm stat. 3 + * 4 + * Copyright 2014 IBM Corp. 5 + * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License (version 2 only) 9 + * as published by the Free Software Foundation. 10 + */ 11 + 12 + #include "../../util/kvm-stat.h" 13 + #include <asm/kvm_perf.h> 14 + 15 + define_exit_reasons_table(sie_exit_reasons, sie_intercept_code); 16 + define_exit_reasons_table(sie_icpt_insn_codes, icpt_insn_codes); 17 + define_exit_reasons_table(sie_sigp_order_codes, sigp_order_codes); 18 + define_exit_reasons_table(sie_diagnose_codes, diagnose_codes); 19 + define_exit_reasons_table(sie_icpt_prog_codes, icpt_prog_codes); 20 + 21 + static void event_icpt_insn_get_key(struct perf_evsel *evsel, 22 + struct perf_sample *sample, 23 + struct event_key *key) 24 + { 25 + unsigned long insn; 26 + 27 + insn = perf_evsel__intval(evsel, sample, "instruction"); 28 + key->key = icpt_insn_decoder(insn); 29 + key->exit_reasons = sie_icpt_insn_codes; 30 + } 31 + 32 + static void event_sigp_get_key(struct perf_evsel *evsel, 33 + struct perf_sample *sample, 34 + struct event_key *key) 35 + { 36 + key->key = perf_evsel__intval(evsel, sample, "order_code"); 37 + key->exit_reasons = sie_sigp_order_codes; 38 + } 39 + 40 + static void event_diag_get_key(struct perf_evsel *evsel, 41 + struct perf_sample *sample, 42 + struct event_key *key) 43 + { 44 + key->key = perf_evsel__intval(evsel, sample, "code"); 45 + key->exit_reasons = sie_diagnose_codes; 46 + } 47 + 48 + static void event_icpt_prog_get_key(struct perf_evsel *evsel, 49 + struct perf_sample *sample, 50 + struct event_key *key) 51 + { 52 + key->key = perf_evsel__intval(evsel, sample, "code"); 53 + key->exit_reasons = sie_icpt_prog_codes; 54 + } 55 + 56 + static struct child_event_ops child_events[] = { 57 + { .name = "kvm:kvm_s390_intercept_instruction", 58 + .get_key = event_icpt_insn_get_key }, 59 + { .name = "kvm:kvm_s390_handle_sigp", 60 + .get_key = event_sigp_get_key }, 61 + { .name = "kvm:kvm_s390_handle_diag", 62 + .get_key = event_diag_get_key }, 63 + { .name = "kvm:kvm_s390_intercept_prog", 64 + .get_key = event_icpt_prog_get_key }, 65 + { NULL, NULL }, 66 + }; 67 + 68 + static struct kvm_events_ops exit_events = { 69 + .is_begin_event = exit_event_begin, 70 + .is_end_event = exit_event_end, 71 + .child_ops = child_events, 72 + .decode_key = exit_event_decode_key, 73 + .name = "VM-EXIT" 74 + }; 75 + 76 + const char * const kvm_events_tp[] = { 77 + "kvm:kvm_s390_sie_enter", 78 + "kvm:kvm_s390_sie_exit", 79 + "kvm:kvm_s390_intercept_instruction", 80 + "kvm:kvm_s390_handle_sigp", 81 + "kvm:kvm_s390_handle_diag", 82 + "kvm:kvm_s390_intercept_prog", 83 + NULL, 84 + }; 85 + 86 + struct kvm_reg_events_ops kvm_reg_events_ops[] = { 87 + { .name = "vmexit", .ops = &exit_events }, 88 + { NULL, NULL }, 89 + }; 90 + 91 + const char * const kvm_skip_events[] = { 92 + "Wait state", 93 + NULL, 94 + }; 95 + 96 + int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid) 97 + { 98 + if (strstr(cpuid, "IBM/S390")) { 99 + kvm->exit_reasons = sie_exit_reasons; 100 + kvm->exit_reasons_isa = "SIE"; 101 + } else 102 + return -ENOTSUP; 103 + 104 + return 0; 105 + }
+1
tools/perf/arch/x86/Makefile
··· 16 16 LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o 17 17 LIB_H += arch/$(ARCH)/util/tsc.h 18 18 HAVE_KVM_STAT_SUPPORT := 1 19 + LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/kvm-stat.o
+1
tools/perf/arch/x86/tests/dwarf-unwind.c
··· 3 3 #include "thread.h" 4 4 #include "map.h" 5 5 #include "event.h" 6 + #include "debug.h" 6 7 #include "tests/tests.h" 7 8 8 9 #define STACK_SIZE 8192
+156
tools/perf/arch/x86/util/kvm-stat.c
··· 1 + #include "../../util/kvm-stat.h" 2 + #include <asm/kvm_perf.h> 3 + 4 + define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS); 5 + define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS); 6 + 7 + static struct kvm_events_ops exit_events = { 8 + .is_begin_event = exit_event_begin, 9 + .is_end_event = exit_event_end, 10 + .decode_key = exit_event_decode_key, 11 + .name = "VM-EXIT" 12 + }; 13 + 14 + /* 15 + * For the mmio events, we treat: 16 + * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry 17 + * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...). 18 + */ 19 + static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample, 20 + struct event_key *key) 21 + { 22 + key->key = perf_evsel__intval(evsel, sample, "gpa"); 23 + key->info = perf_evsel__intval(evsel, sample, "type"); 24 + } 25 + 26 + #define KVM_TRACE_MMIO_READ_UNSATISFIED 0 27 + #define KVM_TRACE_MMIO_READ 1 28 + #define KVM_TRACE_MMIO_WRITE 2 29 + 30 + static bool mmio_event_begin(struct perf_evsel *evsel, 31 + struct perf_sample *sample, struct event_key *key) 32 + { 33 + /* MMIO read begin event in kernel. */ 34 + if (kvm_exit_event(evsel)) 35 + return true; 36 + 37 + /* MMIO write begin event in kernel. */ 38 + if (!strcmp(evsel->name, "kvm:kvm_mmio") && 39 + perf_evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_WRITE) { 40 + mmio_event_get_key(evsel, sample, key); 41 + return true; 42 + } 43 + 44 + return false; 45 + } 46 + 47 + static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample, 48 + struct event_key *key) 49 + { 50 + /* MMIO write end event in kernel. */ 51 + if (kvm_entry_event(evsel)) 52 + return true; 53 + 54 + /* MMIO read end event in kernel.*/ 55 + if (!strcmp(evsel->name, "kvm:kvm_mmio") && 56 + perf_evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_READ) { 57 + mmio_event_get_key(evsel, sample, key); 58 + return true; 59 + } 60 + 61 + return false; 62 + } 63 + 64 + static void mmio_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused, 65 + struct event_key *key, 66 + char *decode) 67 + { 68 + scnprintf(decode, DECODE_STR_LEN, "%#lx:%s", 69 + (unsigned long)key->key, 70 + key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R"); 71 + } 72 + 73 + static struct kvm_events_ops mmio_events = { 74 + .is_begin_event = mmio_event_begin, 75 + .is_end_event = mmio_event_end, 76 + .decode_key = mmio_event_decode_key, 77 + .name = "MMIO Access" 78 + }; 79 + 80 + /* The time of emulation pio access is from kvm_pio to kvm_entry. */ 81 + static void ioport_event_get_key(struct perf_evsel *evsel, 82 + struct perf_sample *sample, 83 + struct event_key *key) 84 + { 85 + key->key = perf_evsel__intval(evsel, sample, "port"); 86 + key->info = perf_evsel__intval(evsel, sample, "rw"); 87 + } 88 + 89 + static bool ioport_event_begin(struct perf_evsel *evsel, 90 + struct perf_sample *sample, 91 + struct event_key *key) 92 + { 93 + if (!strcmp(evsel->name, "kvm:kvm_pio")) { 94 + ioport_event_get_key(evsel, sample, key); 95 + return true; 96 + } 97 + 98 + return false; 99 + } 100 + 101 + static bool ioport_event_end(struct perf_evsel *evsel, 102 + struct perf_sample *sample __maybe_unused, 103 + struct event_key *key __maybe_unused) 104 + { 105 + return kvm_entry_event(evsel); 106 + } 107 + 108 + static void ioport_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused, 109 + struct event_key *key, 110 + char *decode) 111 + { 112 + scnprintf(decode, DECODE_STR_LEN, "%#llx:%s", 113 + (unsigned long long)key->key, 114 + key->info ? "POUT" : "PIN"); 115 + } 116 + 117 + static struct kvm_events_ops ioport_events = { 118 + .is_begin_event = ioport_event_begin, 119 + .is_end_event = ioport_event_end, 120 + .decode_key = ioport_event_decode_key, 121 + .name = "IO Port Access" 122 + }; 123 + 124 + const char * const kvm_events_tp[] = { 125 + "kvm:kvm_entry", 126 + "kvm:kvm_exit", 127 + "kvm:kvm_mmio", 128 + "kvm:kvm_pio", 129 + NULL, 130 + }; 131 + 132 + struct kvm_reg_events_ops kvm_reg_events_ops[] = { 133 + { .name = "vmexit", .ops = &exit_events }, 134 + { .name = "mmio", .ops = &mmio_events }, 135 + { .name = "ioport", .ops = &ioport_events }, 136 + { NULL, NULL }, 137 + }; 138 + 139 + const char * const kvm_skip_events[] = { 140 + "HLT", 141 + NULL, 142 + }; 143 + 144 + int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid) 145 + { 146 + if (strstr(cpuid, "Intel")) { 147 + kvm->exit_reasons = vmx_exit_reasons; 148 + kvm->exit_reasons_isa = "VMX"; 149 + } else if (strstr(cpuid, "AMD")) { 150 + kvm->exit_reasons = svm_exit_reasons; 151 + kvm->exit_reasons_isa = "SVM"; 152 + } else 153 + return -ENOTSUP; 154 + 155 + return 0; 156 + }
+1 -21
tools/perf/arch/x86/util/tsc.c
··· 6 6 #include "../../perf.h" 7 7 #include <linux/types.h> 8 8 #include "../../util/debug.h" 9 + #include "../../util/tsc.h" 9 10 #include "tsc.h" 10 - 11 - u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc) 12 - { 13 - u64 t, quot, rem; 14 - 15 - t = ns - tc->time_zero; 16 - quot = t / tc->time_mult; 17 - rem = t % tc->time_mult; 18 - return (quot << tc->time_shift) + 19 - (rem << tc->time_shift) / tc->time_mult; 20 - } 21 - 22 - u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc) 23 - { 24 - u64 quot, rem; 25 - 26 - quot = cyc >> tc->time_shift; 27 - rem = cyc & ((1 << tc->time_shift) - 1); 28 - return tc->time_zero + quot * tc->time_mult + 29 - ((rem * tc->time_mult) >> tc->time_shift); 30 - } 31 11 32 12 int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, 33 13 struct perf_tsc_conversion *tc)
-3
tools/perf/arch/x86/util/tsc.h
··· 14 14 int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, 15 15 struct perf_tsc_conversion *tc); 16 16 17 - u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc); 18 - u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc); 19 - 20 17 #endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */
+1
tools/perf/arch/x86/util/unwind-libunwind.c
··· 3 3 #include <libunwind.h> 4 4 #include "perf_regs.h" 5 5 #include "../../util/unwind.h" 6 + #include "../../util/debug.h" 6 7 7 8 #ifdef HAVE_ARCH_X86_64_SUPPORT 8 9 int libunwind__arch_reg_id(int regnum)
+5 -3
tools/perf/builtin-buildid-cache.c
··· 125 125 return ret; 126 126 } 127 127 128 - static int build_id_cache__add_kcore(const char *filename, const char *debugdir) 128 + static int build_id_cache__add_kcore(const char *filename, const char *debugdir, 129 + bool force) 129 130 { 130 131 char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1]; 131 132 char from_dir[PATH_MAX], to_dir[PATH_MAX]; ··· 145 144 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s", 146 145 debugdir, sbuildid); 147 146 148 - if (!build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) { 147 + if (!force && 148 + !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) { 149 149 pr_debug("same kcore found in %s\n", to_dir); 150 150 return 0; 151 151 } ··· 391 389 } 392 390 393 391 if (kcore_filename && 394 - build_id_cache__add_kcore(kcore_filename, debugdir)) 392 + build_id_cache__add_kcore(kcore_filename, debugdir, force)) 395 393 pr_warning("Couldn't add %s\n", kcore_filename); 396 394 397 395 return ret;
+1
tools/perf/builtin-evlist.c
··· 15 15 #include "util/parse-options.h" 16 16 #include "util/session.h" 17 17 #include "util/data.h" 18 + #include "util/debug.h" 18 19 19 20 static int __cmd_evlist(const char *file_name, struct perf_attr_details *details) 20 21 {
+1
tools/perf/builtin-help.c
··· 11 11 #include "util/parse-options.h" 12 12 #include "util/run-command.h" 13 13 #include "util/help.h" 14 + #include "util/debug.h" 14 15 15 16 static struct man_viewer_list { 16 17 struct man_viewer_list *next;
+3
tools/perf/builtin-inject.c
··· 389 389 ret = perf_session__process_events(session, &inject->tool); 390 390 391 391 if (!file_out->is_pipe) { 392 + if (inject->build_ids) 393 + perf_header__set_feat(&session->header, 394 + HEADER_BUILD_ID); 392 395 session->header.data_size = inject->bytes_written; 393 396 perf_session__write_header(session, session->evlist, file_out->fd, true); 394 397 }
+104 -280
tools/perf/builtin-kvm.c
··· 30 30 #include <math.h> 31 31 32 32 #ifdef HAVE_KVM_STAT_SUPPORT 33 - #include <asm/svm.h> 34 - #include <asm/vmx.h> 35 - #include <asm/kvm.h> 33 + #include <asm/kvm_perf.h> 34 + #include "util/kvm-stat.h" 36 35 37 - struct event_key { 38 - #define INVALID_KEY (~0ULL) 39 - u64 key; 40 - int info; 41 - }; 42 - 43 - struct kvm_event_stats { 44 - u64 time; 45 - struct stats stats; 46 - }; 47 - 48 - struct kvm_event { 49 - struct list_head hash_entry; 50 - struct rb_node rb; 51 - 52 - struct event_key key; 53 - 54 - struct kvm_event_stats total; 55 - 56 - #define DEFAULT_VCPU_NUM 8 57 - int max_vcpu; 58 - struct kvm_event_stats *vcpu; 59 - }; 60 - 61 - typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int); 62 - 63 - struct kvm_event_key { 64 - const char *name; 65 - key_cmp_fun key; 66 - }; 67 - 68 - 69 - struct perf_kvm_stat; 70 - 71 - struct kvm_events_ops { 72 - bool (*is_begin_event)(struct perf_evsel *evsel, 73 - struct perf_sample *sample, 74 - struct event_key *key); 75 - bool (*is_end_event)(struct perf_evsel *evsel, 76 - struct perf_sample *sample, struct event_key *key); 77 - void (*decode_key)(struct perf_kvm_stat *kvm, struct event_key *key, 78 - char decode[20]); 79 - const char *name; 80 - }; 81 - 82 - struct exit_reasons_table { 83 - unsigned long exit_code; 84 - const char *reason; 85 - }; 86 - 87 - #define EVENTS_BITS 12 88 - #define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS) 89 - 90 - struct perf_kvm_stat { 91 - struct perf_tool tool; 92 - struct record_opts opts; 93 - struct perf_evlist *evlist; 94 - struct perf_session *session; 95 - 96 - const char *file_name; 97 - const char *report_event; 98 - const char *sort_key; 99 - int trace_vcpu; 100 - 101 - struct exit_reasons_table *exit_reasons; 102 - const char *exit_reasons_isa; 103 - 104 - struct kvm_events_ops *events_ops; 105 - key_cmp_fun compare; 106 - struct list_head kvm_events_cache[EVENTS_CACHE_SIZE]; 107 - 108 - u64 total_time; 109 - u64 total_count; 110 - u64 lost_events; 111 - u64 duration; 112 - 113 - const char *pid_str; 114 - struct intlist *pid_list; 115 - 116 - struct rb_root result; 117 - 118 - int timerfd; 119 - unsigned int display_time; 120 - bool live; 121 - }; 122 - 123 - 124 - static void exit_event_get_key(struct perf_evsel *evsel, 125 - struct perf_sample *sample, 126 - struct event_key *key) 36 + void exit_event_get_key(struct perf_evsel *evsel, 37 + struct perf_sample *sample, 38 + struct event_key *key) 127 39 { 128 40 key->info = 0; 129 - key->key = perf_evsel__intval(evsel, sample, "exit_reason"); 41 + key->key = perf_evsel__intval(evsel, sample, KVM_EXIT_REASON); 130 42 } 131 43 132 - static bool kvm_exit_event(struct perf_evsel *evsel) 44 + bool kvm_exit_event(struct perf_evsel *evsel) 133 45 { 134 - return !strcmp(evsel->name, "kvm:kvm_exit"); 46 + return !strcmp(evsel->name, KVM_EXIT_TRACE); 135 47 } 136 48 137 - static bool exit_event_begin(struct perf_evsel *evsel, 138 - struct perf_sample *sample, struct event_key *key) 49 + bool exit_event_begin(struct perf_evsel *evsel, 50 + struct perf_sample *sample, struct event_key *key) 139 51 { 140 52 if (kvm_exit_event(evsel)) { 141 53 exit_event_get_key(evsel, sample, key); ··· 57 145 return false; 58 146 } 59 147 60 - static bool kvm_entry_event(struct perf_evsel *evsel) 148 + bool kvm_entry_event(struct perf_evsel *evsel) 61 149 { 62 - return !strcmp(evsel->name, "kvm:kvm_entry"); 150 + return !strcmp(evsel->name, KVM_ENTRY_TRACE); 63 151 } 64 152 65 - static bool exit_event_end(struct perf_evsel *evsel, 66 - struct perf_sample *sample __maybe_unused, 67 - struct event_key *key __maybe_unused) 153 + bool exit_event_end(struct perf_evsel *evsel, 154 + struct perf_sample *sample __maybe_unused, 155 + struct event_key *key __maybe_unused) 68 156 { 69 157 return kvm_entry_event(evsel); 70 158 } 71 - 72 - #define define_exit_reasons_table(name, symbols) \ 73 - static struct exit_reasons_table name[] = { \ 74 - symbols, { -1, NULL } \ 75 - } 76 - 77 - define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS); 78 - define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS); 79 159 80 160 static const char *get_exit_reason(struct perf_kvm_stat *kvm, 81 161 struct exit_reasons_table *tbl, ··· 84 180 return "UNKNOWN"; 85 181 } 86 182 87 - static void exit_event_decode_key(struct perf_kvm_stat *kvm, 88 - struct event_key *key, 89 - char decode[20]) 183 + void exit_event_decode_key(struct perf_kvm_stat *kvm, 184 + struct event_key *key, 185 + char *decode) 90 186 { 91 - const char *exit_reason = get_exit_reason(kvm, kvm->exit_reasons, 187 + const char *exit_reason = get_exit_reason(kvm, key->exit_reasons, 92 188 key->key); 93 189 94 - scnprintf(decode, 20, "%s", exit_reason); 190 + scnprintf(decode, DECODE_STR_LEN, "%s", exit_reason); 95 191 } 96 - 97 - static struct kvm_events_ops exit_events = { 98 - .is_begin_event = exit_event_begin, 99 - .is_end_event = exit_event_end, 100 - .decode_key = exit_event_decode_key, 101 - .name = "VM-EXIT" 102 - }; 103 - 104 - /* 105 - * For the mmio events, we treat: 106 - * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry 107 - * the time of MMIO read: kvm_exit -> kvm_mmio(KVM_TRACE_MMIO_READ...). 108 - */ 109 - static void mmio_event_get_key(struct perf_evsel *evsel, struct perf_sample *sample, 110 - struct event_key *key) 111 - { 112 - key->key = perf_evsel__intval(evsel, sample, "gpa"); 113 - key->info = perf_evsel__intval(evsel, sample, "type"); 114 - } 115 - 116 - #define KVM_TRACE_MMIO_READ_UNSATISFIED 0 117 - #define KVM_TRACE_MMIO_READ 1 118 - #define KVM_TRACE_MMIO_WRITE 2 119 - 120 - static bool mmio_event_begin(struct perf_evsel *evsel, 121 - struct perf_sample *sample, struct event_key *key) 122 - { 123 - /* MMIO read begin event in kernel. */ 124 - if (kvm_exit_event(evsel)) 125 - return true; 126 - 127 - /* MMIO write begin event in kernel. */ 128 - if (!strcmp(evsel->name, "kvm:kvm_mmio") && 129 - perf_evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_WRITE) { 130 - mmio_event_get_key(evsel, sample, key); 131 - return true; 132 - } 133 - 134 - return false; 135 - } 136 - 137 - static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample, 138 - struct event_key *key) 139 - { 140 - /* MMIO write end event in kernel. */ 141 - if (kvm_entry_event(evsel)) 142 - return true; 143 - 144 - /* MMIO read end event in kernel.*/ 145 - if (!strcmp(evsel->name, "kvm:kvm_mmio") && 146 - perf_evsel__intval(evsel, sample, "type") == KVM_TRACE_MMIO_READ) { 147 - mmio_event_get_key(evsel, sample, key); 148 - return true; 149 - } 150 - 151 - return false; 152 - } 153 - 154 - static void mmio_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused, 155 - struct event_key *key, 156 - char decode[20]) 157 - { 158 - scnprintf(decode, 20, "%#lx:%s", (unsigned long)key->key, 159 - key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R"); 160 - } 161 - 162 - static struct kvm_events_ops mmio_events = { 163 - .is_begin_event = mmio_event_begin, 164 - .is_end_event = mmio_event_end, 165 - .decode_key = mmio_event_decode_key, 166 - .name = "MMIO Access" 167 - }; 168 - 169 - /* The time of emulation pio access is from kvm_pio to kvm_entry. */ 170 - static void ioport_event_get_key(struct perf_evsel *evsel, 171 - struct perf_sample *sample, 172 - struct event_key *key) 173 - { 174 - key->key = perf_evsel__intval(evsel, sample, "port"); 175 - key->info = perf_evsel__intval(evsel, sample, "rw"); 176 - } 177 - 178 - static bool ioport_event_begin(struct perf_evsel *evsel, 179 - struct perf_sample *sample, 180 - struct event_key *key) 181 - { 182 - if (!strcmp(evsel->name, "kvm:kvm_pio")) { 183 - ioport_event_get_key(evsel, sample, key); 184 - return true; 185 - } 186 - 187 - return false; 188 - } 189 - 190 - static bool ioport_event_end(struct perf_evsel *evsel, 191 - struct perf_sample *sample __maybe_unused, 192 - struct event_key *key __maybe_unused) 193 - { 194 - return kvm_entry_event(evsel); 195 - } 196 - 197 - static void ioport_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused, 198 - struct event_key *key, 199 - char decode[20]) 200 - { 201 - scnprintf(decode, 20, "%#llx:%s", (unsigned long long)key->key, 202 - key->info ? "POUT" : "PIN"); 203 - } 204 - 205 - static struct kvm_events_ops ioport_events = { 206 - .is_begin_event = ioport_event_begin, 207 - .is_end_event = ioport_event_end, 208 - .decode_key = ioport_event_decode_key, 209 - .name = "IO Port Access" 210 - }; 211 192 212 193 static bool register_kvm_events_ops(struct perf_kvm_stat *kvm) 213 194 { 214 - bool ret = true; 195 + struct kvm_reg_events_ops *events_ops = kvm_reg_events_ops; 215 196 216 - if (!strcmp(kvm->report_event, "vmexit")) 217 - kvm->events_ops = &exit_events; 218 - else if (!strcmp(kvm->report_event, "mmio")) 219 - kvm->events_ops = &mmio_events; 220 - else if (!strcmp(kvm->report_event, "ioport")) 221 - kvm->events_ops = &ioport_events; 222 - else { 223 - pr_err("Unknown report event:%s\n", kvm->report_event); 224 - ret = false; 197 + for (events_ops = kvm_reg_events_ops; events_ops->name; events_ops++) { 198 + if (!strcmp(events_ops->name, kvm->report_event)) { 199 + kvm->events_ops = events_ops->ops; 200 + return true; 201 + } 225 202 } 226 203 227 - return ret; 204 + return false; 228 205 } 229 206 230 207 struct vcpu_event_record { ··· 261 476 return true; 262 477 } 263 478 479 + static bool is_child_event(struct perf_kvm_stat *kvm, 480 + struct perf_evsel *evsel, 481 + struct perf_sample *sample, 482 + struct event_key *key) 483 + { 484 + struct child_event_ops *child_ops; 485 + 486 + child_ops = kvm->events_ops->child_ops; 487 + 488 + if (!child_ops) 489 + return false; 490 + 491 + for (; child_ops->name; child_ops++) { 492 + if (!strcmp(evsel->name, child_ops->name)) { 493 + child_ops->get_key(evsel, sample, key); 494 + return true; 495 + } 496 + } 497 + 498 + return false; 499 + } 500 + 501 + static bool handle_child_event(struct perf_kvm_stat *kvm, 502 + struct vcpu_event_record *vcpu_record, 503 + struct event_key *key, 504 + struct perf_sample *sample __maybe_unused) 505 + { 506 + struct kvm_event *event = NULL; 507 + 508 + if (key->key != INVALID_KEY) 509 + event = find_create_kvm_event(kvm, key); 510 + 511 + vcpu_record->last_event = event; 512 + 513 + return true; 514 + } 515 + 516 + static bool skip_event(const char *event) 517 + { 518 + const char * const *skip_events; 519 + 520 + for (skip_events = kvm_skip_events; *skip_events; skip_events++) 521 + if (!strcmp(event, *skip_events)) 522 + return true; 523 + 524 + return false; 525 + } 526 + 264 527 static bool handle_end_event(struct perf_kvm_stat *kvm, 265 528 struct vcpu_event_record *vcpu_record, 266 529 struct event_key *key, ··· 357 524 time_diff = sample->time - time_begin; 358 525 359 526 if (kvm->duration && time_diff > kvm->duration) { 360 - char decode[32]; 527 + char decode[DECODE_STR_LEN]; 361 528 362 529 kvm->events_ops->decode_key(kvm, &event->key, decode); 363 - if (strcmp(decode, "HLT")) { 530 + if (!skip_event(decode)) { 364 531 pr_info("%" PRIu64 " VM %d, vcpu %d: %s event took %" PRIu64 "usec\n", 365 532 sample->time, sample->pid, vcpu_record->vcpu_id, 366 533 decode, time_diff/1000); ··· 385 552 return NULL; 386 553 } 387 554 388 - vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, "vcpu_id"); 555 + vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, VCPU_ID); 389 556 thread->priv = vcpu_record; 390 557 } 391 558 ··· 398 565 struct perf_sample *sample) 399 566 { 400 567 struct vcpu_event_record *vcpu_record; 401 - struct event_key key = {.key = INVALID_KEY}; 568 + struct event_key key = { .key = INVALID_KEY, 569 + .exit_reasons = kvm->exit_reasons }; 402 570 403 571 vcpu_record = per_vcpu_record(thread, evsel, sample); 404 572 if (!vcpu_record) ··· 412 578 413 579 if (kvm->events_ops->is_begin_event(evsel, sample, &key)) 414 580 return handle_begin_event(kvm, vcpu_record, &key, sample->time); 581 + 582 + if (is_child_event(kvm, evsel, sample, &key)) 583 + return handle_child_event(kvm, vcpu_record, &key, sample); 415 584 416 585 if (kvm->events_ops->is_end_event(evsel, sample, &key)) 417 586 return handle_end_event(kvm, vcpu_record, &key, sample); ··· 576 739 577 740 static void print_result(struct perf_kvm_stat *kvm) 578 741 { 579 - char decode[20]; 742 + char decode[DECODE_STR_LEN]; 580 743 struct kvm_event *event; 581 744 int vcpu = kvm->trace_vcpu; 582 745 ··· 587 750 588 751 pr_info("\n\n"); 589 752 print_vcpu_info(kvm); 590 - pr_info("%20s ", kvm->events_ops->name); 753 + pr_info("%*s ", DECODE_STR_LEN, kvm->events_ops->name); 591 754 pr_info("%10s ", "Samples"); 592 755 pr_info("%9s ", "Samples%"); 593 756 ··· 606 769 min = get_event_min(event, vcpu); 607 770 608 771 kvm->events_ops->decode_key(kvm, &event->key, decode); 609 - pr_info("%20s ", decode); 772 + pr_info("%*s ", DECODE_STR_LEN, decode); 610 773 pr_info("%10llu ", (unsigned long long)ecount); 611 774 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100); 612 775 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100); ··· 668 831 669 832 if (!handle_kvm_event(kvm, thread, evsel, sample)) 670 833 return -1; 671 - 672 - return 0; 673 - } 674 - 675 - static int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid) 676 - { 677 - if (strstr(cpuid, "Intel")) { 678 - kvm->exit_reasons = vmx_exit_reasons; 679 - kvm->exit_reasons_isa = "VMX"; 680 - } else if (strstr(cpuid, "AMD")) { 681 - kvm->exit_reasons = svm_exit_reasons; 682 - kvm->exit_reasons_isa = "SVM"; 683 - } else 684 - return -ENOTSUP; 685 834 686 835 return 0; 687 836 } ··· 1130 1307 return ret; 1131 1308 } 1132 1309 1133 - static const char * const kvm_events_tp[] = { 1134 - "kvm:kvm_entry", 1135 - "kvm:kvm_exit", 1136 - "kvm:kvm_mmio", 1137 - "kvm:kvm_pio", 1138 - }; 1139 - 1140 1310 #define STRDUP_FAIL_EXIT(s) \ 1141 1311 ({ char *_p; \ 1142 1312 _p = strdup(s); \ ··· 1141 1325 static int 1142 1326 kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv) 1143 1327 { 1144 - unsigned int rec_argc, i, j; 1328 + unsigned int rec_argc, i, j, events_tp_size; 1145 1329 const char **rec_argv; 1146 1330 const char * const record_args[] = { 1147 1331 "record", ··· 1149 1333 "-m", "1024", 1150 1334 "-c", "1", 1151 1335 }; 1336 + const char * const *events_tp; 1337 + events_tp_size = 0; 1338 + 1339 + for (events_tp = kvm_events_tp; *events_tp; events_tp++) 1340 + events_tp_size++; 1152 1341 1153 1342 rec_argc = ARRAY_SIZE(record_args) + argc + 2 + 1154 - 2 * ARRAY_SIZE(kvm_events_tp); 1343 + 2 * events_tp_size; 1155 1344 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1156 1345 1157 1346 if (rec_argv == NULL) ··· 1165 1344 for (i = 0; i < ARRAY_SIZE(record_args); i++) 1166 1345 rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]); 1167 1346 1168 - for (j = 0; j < ARRAY_SIZE(kvm_events_tp); j++) { 1347 + for (j = 0; j < events_tp_size; j++) { 1169 1348 rec_argv[i++] = "-e"; 1170 1349 rec_argv[i++] = STRDUP_FAIL_EXIT(kvm_events_tp[j]); 1171 1350 } ··· 1184 1363 { 1185 1364 const struct option kvm_events_report_options[] = { 1186 1365 OPT_STRING(0, "event", &kvm->report_event, "report event", 1187 - "event for reporting: vmexit, mmio, ioport"), 1366 + "event for reporting: vmexit, " 1367 + "mmio (x86 only), ioport (x86 only)"), 1188 1368 OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu, 1189 1369 "vcpu id to report"), 1190 1370 OPT_STRING('k', "key", &kvm->sort_key, "sort-key", ··· 1220 1398 { 1221 1399 struct perf_evlist *evlist; 1222 1400 char *tp, *name, *sys; 1223 - unsigned int j; 1224 1401 int err = -1; 1402 + const char * const *events_tp; 1225 1403 1226 1404 evlist = perf_evlist__new(); 1227 1405 if (evlist == NULL) 1228 1406 return NULL; 1229 1407 1230 - for (j = 0; j < ARRAY_SIZE(kvm_events_tp); j++) { 1408 + for (events_tp = kvm_events_tp; *events_tp; events_tp++) { 1231 1409 1232 - tp = strdup(kvm_events_tp[j]); 1410 + tp = strdup(*events_tp); 1233 1411 if (tp == NULL) 1234 1412 goto out; 1235 1413 ··· 1238 1416 name = strchr(tp, ':'); 1239 1417 if (name == NULL) { 1240 1418 pr_err("Error parsing %s tracepoint: subsystem delimiter not found\n", 1241 - kvm_events_tp[j]); 1419 + *events_tp); 1242 1420 free(tp); 1243 1421 goto out; 1244 1422 } ··· 1246 1424 name++; 1247 1425 1248 1426 if (perf_evlist__add_newtp(evlist, sys, name, NULL)) { 1249 - pr_err("Failed to add %s tracepoint to the list\n", kvm_events_tp[j]); 1427 + pr_err("Failed to add %s tracepoint to the list\n", *events_tp); 1250 1428 free(tp); 1251 1429 goto out; 1252 1430 } ··· 1291 1469 "key for sorting: sample(sort by samples number)" 1292 1470 " time (sort by avg time)"), 1293 1471 OPT_U64(0, "duration", &kvm->duration, 1294 - "show events other than HALT that take longer than duration usecs"), 1472 + "show events other than" 1473 + " HLT (x86 only) or Wait state (s390 only)" 1474 + " that take longer than duration usecs"), 1295 1475 OPT_END() 1296 1476 }; 1297 1477 const char * const live_usage[] = {
+6 -6
tools/perf/builtin-sched.c
··· 935 935 return -1; 936 936 } 937 937 938 - sched_out = machine__findnew_thread(machine, 0, prev_pid); 939 - sched_in = machine__findnew_thread(machine, 0, next_pid); 938 + sched_out = machine__findnew_thread(machine, -1, prev_pid); 939 + sched_in = machine__findnew_thread(machine, -1, next_pid); 940 940 941 941 out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid); 942 942 if (!out_events) { ··· 979 979 { 980 980 const u32 pid = perf_evsel__intval(evsel, sample, "pid"); 981 981 const u64 runtime = perf_evsel__intval(evsel, sample, "runtime"); 982 - struct thread *thread = machine__findnew_thread(machine, 0, pid); 982 + struct thread *thread = machine__findnew_thread(machine, -1, pid); 983 983 struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); 984 984 u64 timestamp = sample->time; 985 985 int cpu = sample->cpu; ··· 1012 1012 struct thread *wakee; 1013 1013 u64 timestamp = sample->time; 1014 1014 1015 - wakee = machine__findnew_thread(machine, 0, pid); 1015 + wakee = machine__findnew_thread(machine, -1, pid); 1016 1016 atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); 1017 1017 if (!atoms) { 1018 1018 if (thread_atoms_insert(sched, wakee)) ··· 1072 1072 if (sched->profile_cpu == -1) 1073 1073 return 0; 1074 1074 1075 - migrant = machine__findnew_thread(machine, 0, pid); 1075 + migrant = machine__findnew_thread(machine, -1, pid); 1076 1076 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); 1077 1077 if (!atoms) { 1078 1078 if (thread_atoms_insert(sched, migrant)) ··· 1290 1290 return -1; 1291 1291 } 1292 1292 1293 - sched_in = machine__findnew_thread(machine, 0, next_pid); 1293 + sched_in = machine__findnew_thread(machine, -1, next_pid); 1294 1294 1295 1295 sched->curr_thread[this_cpu] = sched_in; 1296 1296
+1
tools/perf/builtin-timechart.c
··· 37 37 #include "util/svghelper.h" 38 38 #include "util/tool.h" 39 39 #include "util/data.h" 40 + #include "util/debug.h" 40 41 41 42 #define SUPPORT_OLD_POWER_EVENTS 1 42 43 #define PWR_EVENT_EXIT -1
+6
tools/perf/config/Makefile
··· 164 164 backtrace \ 165 165 dwarf \ 166 166 fortify-source \ 167 + sync-compare-and-swap \ 167 168 glibc \ 168 169 gtk2 \ 169 170 gtk2-infobar \ ··· 200 199 VF_FEATURE_TESTS = \ 201 200 backtrace \ 202 201 fortify-source \ 202 + sync-compare-and-swap \ 203 203 gtk2-infobar \ 204 204 libelf-getphdrnum \ 205 205 libelf-mmap \ ··· 273 271 CFLAGS += -I$(LIB_INCLUDE) 274 272 275 273 CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE 274 + 275 + ifeq ($(feature-sync-compare-and-swap), 1) 276 + CFLAGS += -DHAVE_SYNC_COMPARE_AND_SWAP_SUPPORT 277 + endif 276 278 277 279 ifndef NO_BIONIC 278 280 $(call feature_check,bionic)
+4
tools/perf/config/feature-checks/Makefile
··· 5 5 test-bionic.bin \ 6 6 test-dwarf.bin \ 7 7 test-fortify-source.bin \ 8 + test-sync-compare-and-swap.bin \ 8 9 test-glibc.bin \ 9 10 test-gtk2.bin \ 10 11 test-gtk2-infobar.bin \ ··· 141 140 142 141 test-libdw-dwarf-unwind.bin: 143 142 $(BUILD) 143 + 144 + test-sync-compare-and-swap.bin: 145 + $(BUILD) -Werror 144 146 145 147 -include *.d 146 148
+5
tools/perf/config/feature-checks/test-all.c
··· 89 89 # include "test-libdw-dwarf-unwind.c" 90 90 #undef main 91 91 92 + #define main main_test_sync_compare_and_swap 93 + # include "test-sync-compare-and-swap.c" 94 + #undef main 95 + 92 96 int main(int argc, char *argv[]) 93 97 { 94 98 main_test_libpython(); ··· 115 111 main_test_timerfd(); 116 112 main_test_stackprotector_all(); 117 113 main_test_libdw_dwarf_unwind(); 114 + main_test_sync_compare_and_swap(argc, argv); 118 115 119 116 return 0; 120 117 }
+14
tools/perf/config/feature-checks/test-sync-compare-and-swap.c
··· 1 + #include <stdint.h> 2 + 3 + volatile uint64_t x; 4 + 5 + int main(int argc, char *argv[]) 6 + { 7 + uint64_t old, new = argc; 8 + 9 + argv = argv; 10 + do { 11 + old = __sync_val_compare_and_swap(&x, 0, 0); 12 + } while (!__sync_bool_compare_and_swap(&x, old, new)); 13 + return old == new; 14 + }
+12 -1
tools/perf/perf.c
··· 13 13 #include "util/quote.h" 14 14 #include "util/run-command.h" 15 15 #include "util/parse-events.h" 16 + #include "util/debug.h" 16 17 #include <api/fs/debugfs.h> 17 18 #include <pthread.h> 18 19 19 20 const char perf_usage_string[] = 20 - "perf [--version] [--help] COMMAND [ARGS]"; 21 + "perf [--version] [--debug variable[=VALUE]] [--help] COMMAND [ARGS]"; 21 22 22 23 const char perf_more_info_string[] = 23 24 "See 'perf help COMMAND' for more information on a specific command."; ··· 213 212 printf("%s ", p->cmd); 214 213 } 215 214 exit(0); 215 + } else if (!strcmp(cmd, "--debug")) { 216 + if (*argc < 2) { 217 + fprintf(stderr, "No variable specified for --debug.\n"); 218 + usage(perf_usage_string); 219 + } 220 + if (perf_debug_option((*argv)[1])) 221 + usage(perf_usage_string); 222 + 223 + (*argv)++; 224 + (*argc)--; 216 225 } else { 217 226 fprintf(stderr, "Unknown option: %s\n", cmd); 218 227 usage(perf_usage_string);
+2 -1
tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
··· 107 107 108 108 class EventHeaders: 109 109 def __init__(self, common_cpu, common_secs, common_nsecs, 110 - common_pid, common_comm): 110 + common_pid, common_comm, common_callchain): 111 111 self.cpu = common_cpu 112 112 self.secs = common_secs 113 113 self.nsecs = common_nsecs 114 114 self.pid = common_pid 115 115 self.comm = common_comm 116 + self.callchain = common_callchain 116 117 117 118 def ts(self): 118 119 return (self.secs * (10 ** 9)) + self.nsecs
+2 -2
tools/perf/scripts/python/check-perf-trace.py
··· 27 27 28 28 def irq__softirq_entry(event_name, context, common_cpu, 29 29 common_secs, common_nsecs, common_pid, common_comm, 30 - vec): 30 + common_callchain, vec): 31 31 print_header(event_name, common_cpu, common_secs, common_nsecs, 32 32 common_pid, common_comm) 33 33 ··· 38 38 39 39 def kmem__kmalloc(event_name, context, common_cpu, 40 40 common_secs, common_nsecs, common_pid, common_comm, 41 - call_site, ptr, bytes_req, bytes_alloc, 41 + common_callchain, call_site, ptr, bytes_req, bytes_alloc, 42 42 gfp_flags): 43 43 print_header(event_name, common_cpu, common_secs, common_nsecs, 44 44 common_pid, common_comm)
+1 -1
tools/perf/scripts/python/failed-syscalls-by-pid.py
··· 39 39 40 40 def raw_syscalls__sys_exit(event_name, context, common_cpu, 41 41 common_secs, common_nsecs, common_pid, common_comm, 42 - id, ret): 42 + common_callchain, id, ret): 43 43 if (for_comm and common_comm != for_comm) or \ 44 44 (for_pid and common_pid != for_pid ): 45 45 return
+2 -2
tools/perf/scripts/python/futex-contention.py
··· 21 21 lock_waits = {} # long-lived stats on (tid,lock) blockage elapsed time 22 22 process_names = {} # long-lived pid-to-execname mapping 23 23 24 - def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, 24 + def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, callchain, 25 25 nr, uaddr, op, val, utime, uaddr2, val3): 26 26 cmd = op & FUTEX_CMD_MASK 27 27 if cmd != FUTEX_WAIT: ··· 31 31 thread_thislock[tid] = uaddr 32 32 thread_blocktime[tid] = nsecs(s, ns) 33 33 34 - def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, 34 + def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain, 35 35 nr, ret): 36 36 if thread_blocktime.has_key(tid): 37 37 elapsed = nsecs(s, ns) - thread_blocktime[tid]
+1 -1
tools/perf/scripts/python/net_dropmonitor.py
··· 66 66 print_drop_table() 67 67 68 68 # called from perf, when it finds a correspoinding event 69 - def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, 69 + def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain, 70 70 skbaddr, location, protocol): 71 71 slocation = str(location) 72 72 try:
+13 -13
tools/perf/scripts/python/netdev-times.py
··· 224 224 (len(rx_skb_list), of_count_rx_skb_list) 225 225 226 226 # called from perf, when it finds a correspoinding event 227 - def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, vec): 227 + def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec): 228 228 if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX": 229 229 return 230 230 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec) 231 231 all_event_list.append(event_info) 232 232 233 - def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, vec): 233 + def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, callchain, vec): 234 234 if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX": 235 235 return 236 236 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec) 237 237 all_event_list.append(event_info) 238 238 239 - def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, vec): 239 + def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, callchain, vec): 240 240 if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX": 241 241 return 242 242 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec) 243 243 all_event_list.append(event_info) 244 244 245 245 def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm, 246 - irq, irq_name): 246 + callchain, irq, irq_name): 247 247 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 248 248 irq, irq_name) 249 249 all_event_list.append(event_info) 250 250 251 - def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, irq, ret): 251 + def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, irq, ret): 252 252 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret) 253 253 all_event_list.append(event_info) 254 254 255 - def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, napi, dev_name): 255 + def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, dev_name): 256 256 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 257 257 napi, dev_name) 258 258 all_event_list.append(event_info) 259 259 260 - def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr, 260 + def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr, 261 261 skblen, dev_name): 262 262 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 263 263 skbaddr, skblen, dev_name) 264 264 all_event_list.append(event_info) 265 265 266 - def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, skbaddr, 266 + def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr, 267 267 skblen, dev_name): 268 268 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 269 269 skbaddr, skblen, dev_name) 270 270 all_event_list.append(event_info) 271 271 272 - def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm, 272 + def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm, callchain, 273 273 skbaddr, skblen, dev_name): 274 274 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 275 275 skbaddr, skblen, dev_name) 276 276 all_event_list.append(event_info) 277 277 278 - def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm, 278 + def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm, callchain, 279 279 skbaddr, skblen, rc, dev_name): 280 280 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 281 281 skbaddr, skblen, rc ,dev_name) 282 282 all_event_list.append(event_info) 283 283 284 - def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, 284 + def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain, 285 285 skbaddr, protocol, location): 286 286 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 287 287 skbaddr, protocol, location) 288 288 all_event_list.append(event_info) 289 289 290 - def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr): 290 + def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr): 291 291 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 292 292 skbaddr) 293 293 all_event_list.append(event_info) 294 294 295 - def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm, 295 + def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm, callchain, 296 296 skbaddr, skblen): 297 297 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 298 298 skbaddr, skblen)
+20 -21
tools/perf/scripts/python/sched-migration.py
··· 369 369 370 370 def sched__sched_stat_runtime(event_name, context, common_cpu, 371 371 common_secs, common_nsecs, common_pid, common_comm, 372 - comm, pid, runtime, vruntime): 372 + common_callchain, comm, pid, runtime, vruntime): 373 373 pass 374 374 375 375 def sched__sched_stat_iowait(event_name, context, common_cpu, 376 376 common_secs, common_nsecs, common_pid, common_comm, 377 - comm, pid, delay): 377 + common_callchain, comm, pid, delay): 378 378 pass 379 379 380 380 def sched__sched_stat_sleep(event_name, context, common_cpu, 381 381 common_secs, common_nsecs, common_pid, common_comm, 382 - comm, pid, delay): 382 + common_callchain, comm, pid, delay): 383 383 pass 384 384 385 385 def sched__sched_stat_wait(event_name, context, common_cpu, 386 386 common_secs, common_nsecs, common_pid, common_comm, 387 - comm, pid, delay): 387 + common_callchain, comm, pid, delay): 388 388 pass 389 389 390 390 def sched__sched_process_fork(event_name, context, common_cpu, 391 391 common_secs, common_nsecs, common_pid, common_comm, 392 - parent_comm, parent_pid, child_comm, child_pid): 392 + common_callchain, parent_comm, parent_pid, child_comm, child_pid): 393 393 pass 394 394 395 395 def sched__sched_process_wait(event_name, context, common_cpu, 396 396 common_secs, common_nsecs, common_pid, common_comm, 397 - comm, pid, prio): 397 + common_callchain, comm, pid, prio): 398 398 pass 399 399 400 400 def sched__sched_process_exit(event_name, context, common_cpu, 401 401 common_secs, common_nsecs, common_pid, common_comm, 402 - comm, pid, prio): 402 + common_callchain, comm, pid, prio): 403 403 pass 404 404 405 405 def sched__sched_process_free(event_name, context, common_cpu, 406 406 common_secs, common_nsecs, common_pid, common_comm, 407 - comm, pid, prio): 407 + common_callchain, comm, pid, prio): 408 408 pass 409 409 410 410 def sched__sched_migrate_task(event_name, context, common_cpu, 411 411 common_secs, common_nsecs, common_pid, common_comm, 412 - comm, pid, prio, orig_cpu, 412 + common_callchain, comm, pid, prio, orig_cpu, 413 413 dest_cpu): 414 414 headers = EventHeaders(common_cpu, common_secs, common_nsecs, 415 - common_pid, common_comm) 415 + common_pid, common_comm, common_callchain) 416 416 parser.migrate(headers, pid, prio, orig_cpu, dest_cpu) 417 417 418 418 def sched__sched_switch(event_name, context, common_cpu, 419 - common_secs, common_nsecs, common_pid, common_comm, 419 + common_secs, common_nsecs, common_pid, common_comm, common_callchain, 420 420 prev_comm, prev_pid, prev_prio, prev_state, 421 421 next_comm, next_pid, next_prio): 422 422 423 423 headers = EventHeaders(common_cpu, common_secs, common_nsecs, 424 - common_pid, common_comm) 424 + common_pid, common_comm, common_callchain) 425 425 parser.sched_switch(headers, prev_comm, prev_pid, prev_prio, prev_state, 426 426 next_comm, next_pid, next_prio) 427 427 428 428 def sched__sched_wakeup_new(event_name, context, common_cpu, 429 429 common_secs, common_nsecs, common_pid, common_comm, 430 - comm, pid, prio, success, 430 + common_callchain, comm, pid, prio, success, 431 431 target_cpu): 432 432 headers = EventHeaders(common_cpu, common_secs, common_nsecs, 433 - common_pid, common_comm) 433 + common_pid, common_comm, common_callchain) 434 434 parser.wake_up(headers, comm, pid, success, target_cpu, 1) 435 435 436 436 def sched__sched_wakeup(event_name, context, common_cpu, 437 437 common_secs, common_nsecs, common_pid, common_comm, 438 - comm, pid, prio, success, 438 + common_callchain, comm, pid, prio, success, 439 439 target_cpu): 440 440 headers = EventHeaders(common_cpu, common_secs, common_nsecs, 441 - common_pid, common_comm) 441 + common_pid, common_comm, common_callchain) 442 442 parser.wake_up(headers, comm, pid, success, target_cpu, 0) 443 443 444 444 def sched__sched_wait_task(event_name, context, common_cpu, 445 445 common_secs, common_nsecs, common_pid, common_comm, 446 - comm, pid, prio): 446 + common_callchain, comm, pid, prio): 447 447 pass 448 448 449 449 def sched__sched_kthread_stop_ret(event_name, context, common_cpu, 450 450 common_secs, common_nsecs, common_pid, common_comm, 451 - ret): 451 + common_callchain, ret): 452 452 pass 453 453 454 454 def sched__sched_kthread_stop(event_name, context, common_cpu, 455 455 common_secs, common_nsecs, common_pid, common_comm, 456 - comm, pid): 456 + common_callchain, comm, pid): 457 457 pass 458 458 459 - def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs, 460 - common_pid, common_comm): 459 + def trace_unhandled(event_name, context, event_fields_dict): 461 460 pass
+1 -1
tools/perf/scripts/python/sctop.py
··· 44 44 45 45 def raw_syscalls__sys_enter(event_name, context, common_cpu, 46 46 common_secs, common_nsecs, common_pid, common_comm, 47 - id, args): 47 + common_callchain, id, args): 48 48 if for_comm is not None: 49 49 if common_comm != for_comm: 50 50 return
+1 -1
tools/perf/scripts/python/syscall-counts-by-pid.py
··· 38 38 39 39 def raw_syscalls__sys_enter(event_name, context, common_cpu, 40 40 common_secs, common_nsecs, common_pid, common_comm, 41 - id, args): 41 + common_callchain, id, args): 42 42 43 43 if (for_comm and common_comm != for_comm) or \ 44 44 (for_pid and common_pid != for_pid ):
+1 -1
tools/perf/scripts/python/syscall-counts.py
··· 35 35 36 36 def raw_syscalls__sys_enter(event_name, context, common_cpu, 37 37 common_secs, common_nsecs, common_pid, common_comm, 38 - id, args): 38 + common_callchain, id, args): 39 39 if for_comm is not None: 40 40 if common_comm != for_comm: 41 41 return
+1
tools/perf/tests/dso-data.c
··· 10 10 #include "machine.h" 11 11 #include "symbol.h" 12 12 #include "tests.h" 13 + #include "debug.h" 13 14 14 15 static char *test_file(int size) 15 16 {
+1
tools/perf/tests/evsel-roundtrip-name.c
··· 2 2 #include "evsel.h" 3 3 #include "parse-events.h" 4 4 #include "tests.h" 5 + #include "debug.h" 5 6 6 7 static int perf_evsel__roundtrip_cache_name_test(void) 7 8 {
+1
tools/perf/tests/evsel-tp-sched.c
··· 1 1 #include <traceevent/event-parse.h> 2 2 #include "evsel.h" 3 3 #include "tests.h" 4 + #include "debug.h" 4 5 5 6 static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, 6 7 int size, bool should_be_signed)
+1
tools/perf/tests/open-syscall-tp-fields.c
··· 3 3 #include "evsel.h" 4 4 #include "thread_map.h" 5 5 #include "tests.h" 6 + #include "debug.h" 6 7 7 8 int test__syscall_open_tp_fields(void) 8 9 {
+1
tools/perf/tests/parse-events.c
··· 5 5 #include <api/fs/fs.h> 6 6 #include <api/fs/debugfs.h> 7 7 #include "tests.h" 8 + #include "debug.h" 8 9 #include <linux/hw_breakpoint.h> 9 10 10 11 #define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \
+1
tools/perf/tests/parse-no-sample-id-all.c
··· 7 7 #include "evlist.h" 8 8 #include "header.h" 9 9 #include "util.h" 10 + #include "debug.h" 10 11 11 12 static int process_event(struct perf_evlist **pevlist, union perf_event *event) 12 13 {
+1 -2
tools/perf/tests/perf-time-to-tsc.c
··· 8 8 #include "evsel.h" 9 9 #include "thread_map.h" 10 10 #include "cpumap.h" 11 + #include "tsc.h" 11 12 #include "tests.h" 12 - 13 - #include "../arch/x86/util/tsc.h" 14 13 15 14 #define CHECK__(x) { \ 16 15 while ((x) < 0) { \
+1
tools/perf/tests/sample-parsing.c
··· 4 4 #include "util.h" 5 5 #include "event.h" 6 6 #include "evsel.h" 7 + #include "debug.h" 7 8 8 9 #include "tests.h" 9 10
+1
tools/perf/tests/thread-mg-share.c
··· 2 2 #include "machine.h" 3 3 #include "thread.h" 4 4 #include "map.h" 5 + #include "debug.h" 5 6 6 7 int test__thread_mg_share(void) 7 8 {
+1 -1
tools/perf/ui/stdio/hist.c
··· 479 479 480 480 if (h->ms.map == NULL && verbose > 1) { 481 481 __map_groups__fprintf_maps(h->thread->mg, 482 - MAP__FUNCTION, verbose, fp); 482 + MAP__FUNCTION, fp); 483 483 fprintf(fp, "%.10s end\n", graph_dotted_line); 484 484 } 485 485 }
+1 -1
tools/perf/util/callchain.c
··· 626 626 627 627 int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample) 628 628 { 629 - if (!symbol_conf.use_callchain) 629 + if (!symbol_conf.use_callchain || sample->callchain == NULL) 630 630 return 0; 631 631 return callchain_append(he->callchain, &callchain_cursor, sample->period); 632 632 }
+1
tools/perf/util/data.c
··· 7 7 8 8 #include "data.h" 9 9 #include "util.h" 10 + #include "debug.h" 10 11 11 12 static bool check_pipe(struct perf_data_file *file) 12 13 {
+50 -6
tools/perf/util/debug.c
··· 16 16 int verbose; 17 17 bool dump_trace = false, quiet = false; 18 18 19 - static int _eprintf(int level, const char *fmt, va_list args) 19 + static int _eprintf(int level, int var, const char *fmt, va_list args) 20 20 { 21 21 int ret = 0; 22 22 23 - if (verbose >= level) { 23 + if (var >= level) { 24 24 if (use_browser >= 1) 25 25 ui_helpline__vshow(fmt, args); 26 26 else ··· 30 30 return ret; 31 31 } 32 32 33 - int eprintf(int level, const char *fmt, ...) 33 + int eprintf(int level, int var, const char *fmt, ...) 34 34 { 35 35 va_list args; 36 36 int ret; 37 37 38 38 va_start(args, fmt); 39 - ret = _eprintf(level, fmt, args); 39 + ret = _eprintf(level, var, fmt, args); 40 40 va_end(args); 41 41 42 42 return ret; ··· 51 51 va_list args; 52 52 53 53 va_start(args, fmt); 54 - _eprintf(1, fmt, args); 54 + _eprintf(1, verbose, fmt, args); 55 55 va_end(args); 56 - eprintf(1, "\n"); 56 + eprintf(1, verbose, "\n"); 57 57 } 58 58 59 59 int dump_printf(const char *fmt, ...) ··· 104 104 } 105 105 } 106 106 printf(".\n"); 107 + } 108 + 109 + static struct debug_variable { 110 + const char *name; 111 + int *ptr; 112 + } debug_variables[] = { 113 + { .name = "verbose", .ptr = &verbose }, 114 + { .name = NULL, } 115 + }; 116 + 117 + int perf_debug_option(const char *str) 118 + { 119 + struct debug_variable *var = &debug_variables[0]; 120 + char *vstr, *s = strdup(str); 121 + int v = 1; 122 + 123 + vstr = strchr(s, '='); 124 + if (vstr) 125 + *vstr++ = 0; 126 + 127 + while (var->name) { 128 + if (!strcmp(s, var->name)) 129 + break; 130 + var++; 131 + } 132 + 133 + if (!var->name) { 134 + pr_err("Unknown debug variable name '%s'\n", s); 135 + free(s); 136 + return -1; 137 + } 138 + 139 + if (vstr) { 140 + v = atoi(vstr); 141 + /* 142 + * Allow only values in range (0, 10), 143 + * otherwise set 0. 144 + */ 145 + v = (v < 0) || (v > 10) ? 0 : v; 146 + } 147 + 148 + *var->ptr = v; 149 + free(s); 150 + return 0; 107 151 }
+22
tools/perf/util/debug.h
··· 11 11 extern int verbose; 12 12 extern bool quiet, dump_trace; 13 13 14 + #ifndef pr_fmt 15 + #define pr_fmt(fmt) fmt 16 + #endif 17 + 18 + #define pr_err(fmt, ...) \ 19 + eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__) 20 + #define pr_warning(fmt, ...) \ 21 + eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__) 22 + #define pr_info(fmt, ...) \ 23 + eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__) 24 + #define pr_debug(fmt, ...) \ 25 + eprintf(1, verbose, pr_fmt(fmt), ##__VA_ARGS__) 26 + #define pr_debugN(n, fmt, ...) \ 27 + eprintf(n, verbose, pr_fmt(fmt), ##__VA_ARGS__) 28 + #define pr_debug2(fmt, ...) pr_debugN(2, pr_fmt(fmt), ##__VA_ARGS__) 29 + #define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) 30 + #define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) 31 + 14 32 int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 15 33 void trace_event(union perf_event *event); 16 34 ··· 36 18 int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); 37 19 38 20 void pr_stat(const char *fmt, ...); 21 + 22 + int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4))); 23 + 24 + int perf_debug_option(const char *str); 39 25 40 26 #endif /* __PERF_DEBUG_H */
+1
tools/perf/util/dso.c
··· 703 703 dso->data.fd = -1; 704 704 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND; 705 705 dso->binary_type = DSO_BINARY_TYPE__NOT_FOUND; 706 + dso->is_64_bit = (sizeof(void *) == 8); 706 707 dso->loaded = 0; 707 708 dso->rel = 0; 708 709 dso->sorted_by_name = 0;
+1
tools/perf/util/dso.h
··· 90 90 u8 annotate_warned:1; 91 91 u8 short_name_allocated:1; 92 92 u8 long_name_allocated:1; 93 + u8 is_64_bit:1; 93 94 u8 sorted_by_name; 94 95 u8 loaded; 95 96 u8 rel;
+9 -1
tools/perf/util/event.c
··· 603 603 604 604 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp) 605 605 { 606 - return fprintf(fp, ": %s:%d\n", event->comm.comm, event->comm.tid); 606 + const char *s; 607 + 608 + if (event->header.misc & PERF_RECORD_MISC_COMM_EXEC) 609 + s = " exec"; 610 + else 611 + s = ""; 612 + 613 + return fprintf(fp, "%s: %s:%d\n", s, event->comm.comm, event->comm.tid); 607 614 } 608 615 609 616 int perf_event__process_comm(struct perf_tool *tool __maybe_unused, ··· 788 781 cpumode == PERF_RECORD_MISC_USER && 789 782 machine && mg != &machine->kmaps) { 790 783 mg = &machine->kmaps; 784 + load_map = true; 791 785 goto try_again; 792 786 } 793 787 } else {
+26 -20
tools/perf/util/evlist.c
··· 606 606 return evlist->mmap != NULL ? 0 : -ENOMEM; 607 607 } 608 608 609 - static int __perf_evlist__mmap(struct perf_evlist *evlist, 610 - int idx, int prot, int mask, int fd) 609 + struct mmap_params { 610 + int prot; 611 + int mask; 612 + }; 613 + 614 + static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, 615 + struct mmap_params *mp, int fd) 611 616 { 612 617 evlist->mmap[idx].prev = 0; 613 - evlist->mmap[idx].mask = mask; 614 - evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, 618 + evlist->mmap[idx].mask = mp->mask; 619 + evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot, 615 620 MAP_SHARED, fd, 0); 616 621 if (evlist->mmap[idx].base == MAP_FAILED) { 617 622 pr_debug2("failed to mmap perf event ring buffer, error %d\n", ··· 630 625 } 631 626 632 627 static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, 633 - int prot, int mask, int cpu, int thread, 634 - int *output) 628 + struct mmap_params *mp, int cpu, 629 + int thread, int *output) 635 630 { 636 631 struct perf_evsel *evsel; 637 632 ··· 640 635 641 636 if (*output == -1) { 642 637 *output = fd; 643 - if (__perf_evlist__mmap(evlist, idx, prot, mask, 644 - *output) < 0) 638 + if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0) 645 639 return -1; 646 640 } else { 647 641 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) ··· 655 651 return 0; 656 652 } 657 653 658 - static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, 659 - int mask) 654 + static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, 655 + struct mmap_params *mp) 660 656 { 661 657 int cpu, thread; 662 658 int nr_cpus = cpu_map__nr(evlist->cpus); ··· 667 663 int output = -1; 668 664 669 665 for (thread = 0; thread < nr_threads; thread++) { 670 - if (perf_evlist__mmap_per_evsel(evlist, cpu, prot, mask, 671 - cpu, thread, &output)) 666 + if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu, 667 + thread, &output)) 672 668 goto out_unmap; 673 669 } 674 670 } ··· 681 677 return -1; 682 678 } 683 679 684 - static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, 685 - int mask) 680 + static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, 681 + struct mmap_params *mp) 686 682 { 687 683 int thread; 688 684 int nr_threads = thread_map__nr(evlist->threads); ··· 691 687 for (thread = 0; thread < nr_threads; thread++) { 692 688 int output = -1; 693 689 694 - if (perf_evlist__mmap_per_evsel(evlist, thread, prot, mask, 0, 695 - thread, &output)) 690 + if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread, 691 + &output)) 696 692 goto out_unmap; 697 693 } 698 694 ··· 797 793 struct perf_evsel *evsel; 798 794 const struct cpu_map *cpus = evlist->cpus; 799 795 const struct thread_map *threads = evlist->threads; 800 - int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask; 796 + struct mmap_params mp = { 797 + .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), 798 + }; 801 799 802 800 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 803 801 return -ENOMEM; ··· 810 804 evlist->overwrite = overwrite; 811 805 evlist->mmap_len = perf_evlist__mmap_size(pages); 812 806 pr_debug("mmap size %zuB\n", evlist->mmap_len); 813 - mask = evlist->mmap_len - page_size - 1; 807 + mp.mask = evlist->mmap_len - page_size - 1; 814 808 815 809 evlist__for_each(evlist, evsel) { 816 810 if ((evsel->attr.read_format & PERF_FORMAT_ID) && ··· 820 814 } 821 815 822 816 if (cpu_map__empty(cpus)) 823 - return perf_evlist__mmap_per_thread(evlist, prot, mask); 817 + return perf_evlist__mmap_per_thread(evlist, &mp); 824 818 825 - return perf_evlist__mmap_per_cpu(evlist, prot, mask); 819 + return perf_evlist__mmap_per_cpu(evlist, &mp); 826 820 } 827 821 828 822 int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
+10 -4
tools/perf/util/evsel.c
··· 623 623 attr->mmap_data = track; 624 624 } 625 625 626 - if (opts->call_graph_enabled) 626 + if (opts->call_graph_enabled && !evsel->no_aux_samples) 627 627 perf_evsel__config_callgraph(evsel, opts); 628 628 629 629 if (target__has_cpu(&opts->target)) ··· 637 637 target__has_cpu(&opts->target) || per_cpu)) 638 638 perf_evsel__set_sample_bit(evsel, TIME); 639 639 640 - if (opts->raw_samples) { 640 + if (opts->raw_samples && !evsel->no_aux_samples) { 641 641 perf_evsel__set_sample_bit(evsel, TIME); 642 642 perf_evsel__set_sample_bit(evsel, RAW); 643 643 perf_evsel__set_sample_bit(evsel, CPU); ··· 650 650 attr->watermark = 0; 651 651 attr->wakeup_events = 1; 652 652 } 653 - if (opts->branch_stack) { 653 + if (opts->branch_stack && !evsel->no_aux_samples) { 654 654 perf_evsel__set_sample_bit(evsel, BRANCH_STACK); 655 655 attr->branch_sample_type = opts->branch_stack; 656 656 } ··· 681 681 if (target__none(&opts->target) && perf_evsel__is_group_leader(evsel) && 682 682 !opts->initial_delay) 683 683 attr->enable_on_exec = 1; 684 + 685 + if (evsel->immediate) { 686 + attr->disabled = 0; 687 + attr->enable_on_exec = 0; 688 + } 684 689 } 685 690 686 691 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) ··· 965 960 ret += PRINT_ATTR2(exclude_user, exclude_kernel); 966 961 ret += PRINT_ATTR2(exclude_hv, exclude_idle); 967 962 ret += PRINT_ATTR2(mmap, comm); 963 + ret += PRINT_ATTR2(mmap2, comm_exec); 968 964 ret += PRINT_ATTR2(freq, inherit_stat); 969 965 ret += PRINT_ATTR2(enable_on_exec, task); 970 966 ret += PRINT_ATTR2(watermark, precise_ip); ··· 973 967 ret += PRINT_ATTR2(exclude_host, exclude_guest); 974 968 ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel, 975 969 "excl.callchain_user", exclude_callchain_user); 976 - ret += PRINT_ATTR_U32(mmap2); 977 970 978 971 ret += PRINT_ATTR_U32(wakeup_events); 979 972 ret += PRINT_ATTR_U32(wakeup_watermark); ··· 1945 1940 if_print(mmap); 1946 1941 if_print(mmap2); 1947 1942 if_print(comm); 1943 + if_print(comm_exec); 1948 1944 if_print(freq); 1949 1945 if_print(inherit_stat); 1950 1946 if_print(enable_on_exec);
+2
tools/perf/util/evsel.h
··· 83 83 int is_pos; 84 84 bool supported; 85 85 bool needs_swap; 86 + bool no_aux_samples; 87 + bool immediate; 86 88 /* parse modifier helper */ 87 89 int exclude_GH; 88 90 int nr_members;
-21
tools/perf/util/include/linux/kernel.h
··· 94 94 return (i >= ssize) ? (ssize - 1) : i; 95 95 } 96 96 97 - int eprintf(int level, 98 - const char *fmt, ...) __attribute__((format(printf, 2, 3))); 99 - 100 - #ifndef pr_fmt 101 - #define pr_fmt(fmt) fmt 102 - #endif 103 - 104 - #define pr_err(fmt, ...) \ 105 - eprintf(0, pr_fmt(fmt), ##__VA_ARGS__) 106 - #define pr_warning(fmt, ...) \ 107 - eprintf(0, pr_fmt(fmt), ##__VA_ARGS__) 108 - #define pr_info(fmt, ...) \ 109 - eprintf(0, pr_fmt(fmt), ##__VA_ARGS__) 110 - #define pr_debug(fmt, ...) \ 111 - eprintf(1, pr_fmt(fmt), ##__VA_ARGS__) 112 - #define pr_debugN(n, fmt, ...) \ 113 - eprintf(n, pr_fmt(fmt), ##__VA_ARGS__) 114 - #define pr_debug2(fmt, ...) pr_debugN(2, pr_fmt(fmt), ##__VA_ARGS__) 115 - #define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) 116 - #define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) 117 - 118 97 /* 119 98 * This looks more complex than it should be. But we need to 120 99 * get the type for the ~ right in round_down (it needs to be
+140
tools/perf/util/kvm-stat.h
··· 1 + #ifndef __PERF_KVM_STAT_H 2 + #define __PERF_KVM_STAT_H 3 + 4 + #include "../perf.h" 5 + #include "evsel.h" 6 + #include "evlist.h" 7 + #include "session.h" 8 + #include "tool.h" 9 + #include "stat.h" 10 + 11 + struct event_key { 12 + #define INVALID_KEY (~0ULL) 13 + u64 key; 14 + int info; 15 + struct exit_reasons_table *exit_reasons; 16 + }; 17 + 18 + struct kvm_event_stats { 19 + u64 time; 20 + struct stats stats; 21 + }; 22 + 23 + struct kvm_event { 24 + struct list_head hash_entry; 25 + struct rb_node rb; 26 + 27 + struct event_key key; 28 + 29 + struct kvm_event_stats total; 30 + 31 + #define DEFAULT_VCPU_NUM 8 32 + int max_vcpu; 33 + struct kvm_event_stats *vcpu; 34 + }; 35 + 36 + typedef int (*key_cmp_fun)(struct kvm_event*, struct kvm_event*, int); 37 + 38 + struct kvm_event_key { 39 + const char *name; 40 + key_cmp_fun key; 41 + }; 42 + 43 + struct perf_kvm_stat; 44 + 45 + struct child_event_ops { 46 + void (*get_key)(struct perf_evsel *evsel, 47 + struct perf_sample *sample, 48 + struct event_key *key); 49 + const char *name; 50 + }; 51 + 52 + struct kvm_events_ops { 53 + bool (*is_begin_event)(struct perf_evsel *evsel, 54 + struct perf_sample *sample, 55 + struct event_key *key); 56 + bool (*is_end_event)(struct perf_evsel *evsel, 57 + struct perf_sample *sample, struct event_key *key); 58 + struct child_event_ops *child_ops; 59 + void (*decode_key)(struct perf_kvm_stat *kvm, struct event_key *key, 60 + char *decode); 61 + const char *name; 62 + }; 63 + 64 + struct exit_reasons_table { 65 + unsigned long exit_code; 66 + const char *reason; 67 + }; 68 + 69 + #define EVENTS_BITS 12 70 + #define EVENTS_CACHE_SIZE (1UL << EVENTS_BITS) 71 + 72 + struct perf_kvm_stat { 73 + struct perf_tool tool; 74 + struct record_opts opts; 75 + struct perf_evlist *evlist; 76 + struct perf_session *session; 77 + 78 + const char *file_name; 79 + const char *report_event; 80 + const char *sort_key; 81 + int trace_vcpu; 82 + 83 + struct exit_reasons_table *exit_reasons; 84 + const char *exit_reasons_isa; 85 + 86 + struct kvm_events_ops *events_ops; 87 + key_cmp_fun compare; 88 + struct list_head kvm_events_cache[EVENTS_CACHE_SIZE]; 89 + 90 + u64 total_time; 91 + u64 total_count; 92 + u64 lost_events; 93 + u64 duration; 94 + 95 + const char *pid_str; 96 + struct intlist *pid_list; 97 + 98 + struct rb_root result; 99 + 100 + int timerfd; 101 + unsigned int display_time; 102 + bool live; 103 + }; 104 + 105 + struct kvm_reg_events_ops { 106 + const char *name; 107 + struct kvm_events_ops *ops; 108 + }; 109 + 110 + void exit_event_get_key(struct perf_evsel *evsel, 111 + struct perf_sample *sample, 112 + struct event_key *key); 113 + bool exit_event_begin(struct perf_evsel *evsel, 114 + struct perf_sample *sample, 115 + struct event_key *key); 116 + bool exit_event_end(struct perf_evsel *evsel, 117 + struct perf_sample *sample, 118 + struct event_key *key); 119 + void exit_event_decode_key(struct perf_kvm_stat *kvm, 120 + struct event_key *key, 121 + char *decode); 122 + 123 + bool kvm_exit_event(struct perf_evsel *evsel); 124 + bool kvm_entry_event(struct perf_evsel *evsel); 125 + 126 + #define define_exit_reasons_table(name, symbols) \ 127 + static struct exit_reasons_table name[] = { \ 128 + symbols, { -1, NULL } \ 129 + } 130 + 131 + /* 132 + * arch specific callbacks and data structures 133 + */ 134 + int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid); 135 + 136 + extern const char * const kvm_events_tp[]; 137 + extern struct kvm_reg_events_ops kvm_reg_events_ops[]; 138 + extern const char * const kvm_skip_events[]; 139 + 140 + #endif /* __PERF_KVM_STAT_H */
+55 -8
tools/perf/util/machine.c
··· 34 34 return -ENOMEM; 35 35 36 36 if (pid != HOST_KERNEL_ID) { 37 - struct thread *thread = machine__findnew_thread(machine, 0, 37 + struct thread *thread = machine__findnew_thread(machine, -1, 38 38 pid); 39 39 char comm[64]; 40 40 ··· 272 272 return; 273 273 } 274 274 275 + static void machine__update_thread_pid(struct machine *machine, 276 + struct thread *th, pid_t pid) 277 + { 278 + struct thread *leader; 279 + 280 + if (pid == th->pid_ || pid == -1 || th->pid_ != -1) 281 + return; 282 + 283 + th->pid_ = pid; 284 + 285 + if (th->pid_ == th->tid) 286 + return; 287 + 288 + leader = machine__findnew_thread(machine, th->pid_, th->pid_); 289 + if (!leader) 290 + goto out_err; 291 + 292 + if (!leader->mg) 293 + leader->mg = map_groups__new(); 294 + 295 + if (!leader->mg) 296 + goto out_err; 297 + 298 + if (th->mg == leader->mg) 299 + return; 300 + 301 + if (th->mg) { 302 + /* 303 + * Maps are created from MMAP events which provide the pid and 304 + * tid. Consequently there never should be any maps on a thread 305 + * with an unknown pid. Just print an error if there are. 306 + */ 307 + if (!map_groups__empty(th->mg)) 308 + pr_err("Discarding thread maps for %d:%d\n", 309 + th->pid_, th->tid); 310 + map_groups__delete(th->mg); 311 + } 312 + 313 + th->mg = map_groups__get(leader->mg); 314 + 315 + return; 316 + 317 + out_err: 318 + pr_err("Failed to join map groups for %d:%d\n", th->pid_, th->tid); 319 + } 320 + 275 321 static struct thread *__machine__findnew_thread(struct machine *machine, 276 322 pid_t pid, pid_t tid, 277 323 bool create) ··· 331 285 * so most of the time we dont have to look up 332 286 * the full rbtree: 333 287 */ 334 - if (machine->last_match && machine->last_match->tid == tid) { 335 - if (pid && pid != machine->last_match->pid_) 336 - machine->last_match->pid_ = pid; 337 - return machine->last_match; 288 + th = machine->last_match; 289 + if (th && th->tid == tid) { 290 + machine__update_thread_pid(machine, th, pid); 291 + return th; 338 292 } 339 293 340 294 while (*p != NULL) { ··· 343 297 344 298 if (th->tid == tid) { 345 299 machine->last_match = th; 346 - if (pid && pid != th->pid_) 347 - th->pid_ = pid; 300 + machine__update_thread_pid(machine, th, pid); 348 301 return th; 349 302 } 350 303 ··· 370 325 * within thread__init_map_groups to find the thread 371 326 * leader and that would screwed the rb tree. 372 327 */ 373 - if (thread__init_map_groups(th, machine)) 328 + if (thread__init_map_groups(th, machine)) { 329 + thread__delete(th); 374 330 return NULL; 331 + } 375 332 } 376 333 377 334 return th;
+26 -12
tools/perf/util/map.c
··· 12 12 #include "vdso.h" 13 13 #include "build-id.h" 14 14 #include "util.h" 15 + #include "debug.h" 15 16 #include <linux/string.h> 16 17 17 18 const char *map_type__name[MAP__NR_TYPES] = { ··· 455 454 } 456 455 } 457 456 457 + bool map_groups__empty(struct map_groups *mg) 458 + { 459 + int i; 460 + 461 + for (i = 0; i < MAP__NR_TYPES; ++i) { 462 + if (maps__first(&mg->maps[i])) 463 + return false; 464 + if (!list_empty(&mg->removed_maps[i])) 465 + return false; 466 + } 467 + 468 + return true; 469 + } 470 + 458 471 struct map_groups *map_groups__new(void) 459 472 { 460 473 struct map_groups *mg = malloc(sizeof(*mg)); ··· 569 554 return ams->sym ? 0 : -1; 570 555 } 571 556 572 - size_t __map_groups__fprintf_maps(struct map_groups *mg, 573 - enum map_type type, int verbose, FILE *fp) 557 + size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type, 558 + FILE *fp) 574 559 { 575 560 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); 576 561 struct rb_node *nd; ··· 588 573 return printed; 589 574 } 590 575 591 - size_t map_groups__fprintf_maps(struct map_groups *mg, int verbose, FILE *fp) 576 + static size_t map_groups__fprintf_maps(struct map_groups *mg, FILE *fp) 592 577 { 593 578 size_t printed = 0, i; 594 579 for (i = 0; i < MAP__NR_TYPES; ++i) 595 - printed += __map_groups__fprintf_maps(mg, i, verbose, fp); 580 + printed += __map_groups__fprintf_maps(mg, i, fp); 596 581 return printed; 597 582 } 598 583 599 584 static size_t __map_groups__fprintf_removed_maps(struct map_groups *mg, 600 - enum map_type type, 601 - int verbose, FILE *fp) 585 + enum map_type type, FILE *fp) 602 586 { 603 587 struct map *pos; 604 588 size_t printed = 0; ··· 614 600 } 615 601 616 602 static size_t map_groups__fprintf_removed_maps(struct map_groups *mg, 617 - int verbose, FILE *fp) 603 + FILE *fp) 618 604 { 619 605 size_t printed = 0, i; 620 606 for (i = 0; i < MAP__NR_TYPES; ++i) 621 - printed += __map_groups__fprintf_removed_maps(mg, i, verbose, fp); 607 + printed += __map_groups__fprintf_removed_maps(mg, i, fp); 622 608 return printed; 623 609 } 624 610 625 - size_t map_groups__fprintf(struct map_groups *mg, int verbose, FILE *fp) 611 + size_t map_groups__fprintf(struct map_groups *mg, FILE *fp) 626 612 { 627 - size_t printed = map_groups__fprintf_maps(mg, verbose, fp); 613 + size_t printed = map_groups__fprintf_maps(mg, fp); 628 614 printed += fprintf(fp, "Removed maps:\n"); 629 - return printed + map_groups__fprintf_removed_maps(mg, verbose, fp); 615 + return printed + map_groups__fprintf_removed_maps(mg, fp); 630 616 } 631 617 632 618 int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, 633 - int verbose, FILE *fp) 619 + FILE *fp) 634 620 { 635 621 struct rb_root *root = &mg->maps[map->type]; 636 622 struct rb_node *next = rb_first(root);
+5 -5
tools/perf/util/map.h
··· 66 66 67 67 struct map_groups *map_groups__new(void); 68 68 void map_groups__delete(struct map_groups *mg); 69 + bool map_groups__empty(struct map_groups *mg); 69 70 70 71 static inline struct map_groups *map_groups__get(struct map_groups *mg) 71 72 { ··· 142 141 143 142 void map__reloc_vmlinux(struct map *map); 144 143 145 - size_t __map_groups__fprintf_maps(struct map_groups *mg, 146 - enum map_type type, int verbose, FILE *fp); 144 + size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type, 145 + FILE *fp); 147 146 void maps__insert(struct rb_root *maps, struct map *map); 148 147 void maps__remove(struct rb_root *maps, struct map *map); 149 148 struct map *maps__find(struct rb_root *maps, u64 addr); ··· 153 152 void map_groups__exit(struct map_groups *mg); 154 153 int map_groups__clone(struct map_groups *mg, 155 154 struct map_groups *parent, enum map_type type); 156 - size_t map_groups__fprintf(struct map_groups *mg, int verbose, FILE *fp); 157 - size_t map_groups__fprintf_maps(struct map_groups *mg, int verbose, FILE *fp); 155 + size_t map_groups__fprintf(struct map_groups *mg, FILE *fp); 158 156 159 157 int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name, 160 158 u64 addr); ··· 210 210 } 211 211 212 212 int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, 213 - int verbose, FILE *fp); 213 + FILE *fp); 214 214 215 215 struct map *map_groups__find_by_name(struct map_groups *mg, 216 216 enum map_type type, const char *name);
+5
tools/perf/util/parse-options.h
··· 98 98 parse_opt_cb *callback; 99 99 intptr_t defval; 100 100 bool *set; 101 + void *data; 101 102 }; 102 103 103 104 #define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v ) ··· 132 131 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\ 133 132 .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\ 134 133 .flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG} 134 + #define OPT_CALLBACK_OPTARG(s, l, v, d, a, h, f) \ 135 + { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \ 136 + .value = (v), (a), .help = (h), .callback = (f), \ 137 + .flags = PARSE_OPT_OPTARG, .data = (d) } 135 138 136 139 /* parse_options() will filter out the processed options and leave the 137 140 * non-option argments in argv[].
-1
tools/perf/util/probe-finder.c
··· 26 26 #include <errno.h> 27 27 #include <stdio.h> 28 28 #include <unistd.h> 29 - #include <getopt.h> 30 29 #include <stdlib.h> 31 30 #include <string.h> 32 31 #include <stdarg.h>
+1
tools/perf/util/pstack.c
··· 6 6 7 7 #include "util.h" 8 8 #include "pstack.h" 9 + #include "debug.h" 9 10 #include <linux/kernel.h> 10 11 #include <stdlib.h> 11 12
+2 -2
tools/perf/util/python.c
··· 14 14 */ 15 15 int verbose; 16 16 17 - int eprintf(int level, const char *fmt, ...) 17 + int eprintf(int level, int var, const char *fmt, ...) 18 18 { 19 19 va_list args; 20 20 int ret = 0; 21 21 22 - if (verbose >= level) { 22 + if (var >= level) { 23 23 va_start(args, fmt); 24 24 ret = vfprintf(stderr, fmt, args); 25 25 va_end(args);
+17 -1
tools/perf/util/record.c
··· 69 69 evsel->attr.sample_type |= PERF_SAMPLE_IDENTIFIER; 70 70 } 71 71 72 + static void perf_probe_comm_exec(struct perf_evsel *evsel) 73 + { 74 + evsel->attr.comm_exec = 1; 75 + } 76 + 72 77 bool perf_can_sample_identifier(void) 73 78 { 74 79 return perf_probe_api(perf_probe_sample_identifier); 80 + } 81 + 82 + static bool perf_can_comm_exec(void) 83 + { 84 + return perf_probe_api(perf_probe_comm_exec); 75 85 } 76 86 77 87 void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) 78 88 { 79 89 struct perf_evsel *evsel; 80 90 bool use_sample_identifier = false; 91 + bool use_comm_exec; 81 92 82 93 /* 83 94 * Set the evsel leader links before we configure attributes, ··· 100 89 if (evlist->cpus->map[0] < 0) 101 90 opts->no_inherit = true; 102 91 103 - evlist__for_each(evlist, evsel) 92 + use_comm_exec = perf_can_comm_exec(); 93 + 94 + evlist__for_each(evlist, evsel) { 104 95 perf_evsel__config(evsel, opts); 96 + if (!evsel->idx && use_comm_exec) 97 + evsel->attr.comm_exec = 1; 98 + } 105 99 106 100 if (evlist->nr_entries > 1) { 107 101 struct perf_evsel *first = perf_evlist__first(evlist);
+1
tools/perf/util/scripting-engines/trace-event-perl.c
··· 34 34 #include "../event.h" 35 35 #include "../trace-event.h" 36 36 #include "../evsel.h" 37 + #include "../debug.h" 37 38 38 39 void boot_Perf__Trace__Context(pTHX_ CV *cv); 39 40 void boot_DynaLoader(pTHX_ CV *cv);
+132 -8
tools/perf/util/scripting-engines/trace-event-python.c
··· 27 27 #include <errno.h> 28 28 29 29 #include "../../perf.h" 30 + #include "../debug.h" 30 31 #include "../evsel.h" 31 32 #include "../util.h" 32 33 #include "../event.h" 33 34 #include "../thread.h" 34 35 #include "../trace-event.h" 36 + #include "../machine.h" 35 37 36 38 PyMODINIT_FUNC initperf_trace_context(void); 37 39 ··· 52 50 53 51 static PyObject *main_module, *main_dict; 54 52 53 + static void handler_call_die(const char *handler_name) NORETURN; 55 54 static void handler_call_die(const char *handler_name) 56 55 { 57 56 PyErr_Print(); 58 57 Py_FatalError("problem in Python trace event handler"); 58 + // Py_FatalError does not return 59 + // but we have to make the compiler happy 60 + abort(); 59 61 } 60 62 61 63 /* ··· 103 97 retval = PyObject_CallObject(handler, t); 104 98 if (retval == NULL) 105 99 handler_call_die(handler_name); 100 + Py_DECREF(retval); 106 101 } 107 102 108 103 Py_DECREF(t); ··· 150 143 retval = PyObject_CallObject(handler, t); 151 144 if (retval == NULL) 152 145 handler_call_die(handler_name); 146 + Py_DECREF(retval); 153 147 } 154 148 155 149 Py_DECREF(t); ··· 280 272 return obj; 281 273 } 282 274 275 + 276 + static PyObject *python_process_callchain(struct perf_sample *sample, 277 + struct perf_evsel *evsel, 278 + struct addr_location *al) 279 + { 280 + PyObject *pylist; 281 + 282 + pylist = PyList_New(0); 283 + if (!pylist) 284 + Py_FatalError("couldn't create Python list"); 285 + 286 + if (!symbol_conf.use_callchain || !sample->callchain) 287 + goto exit; 288 + 289 + if (machine__resolve_callchain(al->machine, evsel, al->thread, 290 + sample, NULL, NULL, 291 + PERF_MAX_STACK_DEPTH) != 0) { 292 + pr_err("Failed to resolve callchain. Skipping\n"); 293 + goto exit; 294 + } 295 + callchain_cursor_commit(&callchain_cursor); 296 + 297 + 298 + while (1) { 299 + PyObject *pyelem; 300 + struct callchain_cursor_node *node; 301 + node = callchain_cursor_current(&callchain_cursor); 302 + if (!node) 303 + break; 304 + 305 + pyelem = PyDict_New(); 306 + if (!pyelem) 307 + Py_FatalError("couldn't create Python dictionary"); 308 + 309 + 310 + pydict_set_item_string_decref(pyelem, "ip", 311 + PyLong_FromUnsignedLongLong(node->ip)); 312 + 313 + if (node->sym) { 314 + PyObject *pysym = PyDict_New(); 315 + if (!pysym) 316 + Py_FatalError("couldn't create Python dictionary"); 317 + pydict_set_item_string_decref(pysym, "start", 318 + PyLong_FromUnsignedLongLong(node->sym->start)); 319 + pydict_set_item_string_decref(pysym, "end", 320 + PyLong_FromUnsignedLongLong(node->sym->end)); 321 + pydict_set_item_string_decref(pysym, "binding", 322 + PyInt_FromLong(node->sym->binding)); 323 + pydict_set_item_string_decref(pysym, "name", 324 + PyString_FromStringAndSize(node->sym->name, 325 + node->sym->namelen)); 326 + pydict_set_item_string_decref(pyelem, "sym", pysym); 327 + } 328 + 329 + if (node->map) { 330 + struct map *map = node->map; 331 + const char *dsoname = "[unknown]"; 332 + if (map && map->dso && (map->dso->name || map->dso->long_name)) { 333 + if (symbol_conf.show_kernel_path && map->dso->long_name) 334 + dsoname = map->dso->long_name; 335 + else if (map->dso->name) 336 + dsoname = map->dso->name; 337 + } 338 + pydict_set_item_string_decref(pyelem, "dso", 339 + PyString_FromString(dsoname)); 340 + } 341 + 342 + callchain_cursor_advance(&callchain_cursor); 343 + PyList_Append(pylist, pyelem); 344 + Py_DECREF(pyelem); 345 + } 346 + 347 + exit: 348 + return pylist; 349 + } 350 + 351 + 283 352 static void python_process_tracepoint(struct perf_sample *sample, 284 353 struct perf_evsel *evsel, 285 354 struct thread *thread, 286 355 struct addr_location *al) 287 356 { 288 - PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; 357 + PyObject *handler, *retval, *context, *t, *obj, *callchain; 358 + PyObject *dict = NULL; 289 359 static char handler_name[256]; 290 360 struct format_field *field; 291 361 unsigned long s, ns; ··· 406 320 PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); 407 321 PyTuple_SetItem(t, n++, context); 408 322 323 + /* ip unwinding */ 324 + callchain = python_process_callchain(sample, evsel, al); 325 + 409 326 if (handler) { 410 327 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 411 328 PyTuple_SetItem(t, n++, PyInt_FromLong(s)); 412 329 PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); 413 330 PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); 414 331 PyTuple_SetItem(t, n++, PyString_FromString(comm)); 332 + PyTuple_SetItem(t, n++, callchain); 415 333 } else { 416 334 pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); 417 335 pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); 418 336 pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); 419 337 pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); 420 338 pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); 339 + pydict_set_item_string_decref(dict, "common_callchain", callchain); 421 340 } 422 341 for (field = event->format.fields; field; field = field->next) { 423 342 if (field->flags & FIELD_IS_STRING) { ··· 442 351 pydict_set_item_string_decref(dict, field->name, obj); 443 352 444 353 } 354 + 445 355 if (!handler) 446 356 PyTuple_SetItem(t, n++, dict); 447 357 ··· 453 361 retval = PyObject_CallObject(handler, t); 454 362 if (retval == NULL) 455 363 handler_call_die(handler_name); 364 + Py_DECREF(retval); 456 365 } else { 457 366 handler = PyDict_GetItemString(main_dict, "trace_unhandled"); 458 367 if (handler && PyCallable_Check(handler)) { ··· 461 368 retval = PyObject_CallObject(handler, t); 462 369 if (retval == NULL) 463 370 handler_call_die("trace_unhandled"); 371 + Py_DECREF(retval); 464 372 } 465 373 Py_DECREF(dict); 466 374 } ··· 474 380 struct thread *thread, 475 381 struct addr_location *al) 476 382 { 477 - PyObject *handler, *retval, *t, *dict; 383 + PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample; 478 384 static char handler_name[64]; 479 385 unsigned n = 0; 480 386 ··· 490 396 if (!dict) 491 397 Py_FatalError("couldn't create Python dictionary"); 492 398 399 + dict_sample = PyDict_New(); 400 + if (!dict_sample) 401 + Py_FatalError("couldn't create Python dictionary"); 402 + 493 403 snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); 494 404 495 405 handler = PyDict_GetItemString(main_dict, handler_name); ··· 503 405 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); 504 406 pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( 505 407 (const char *)&evsel->attr, sizeof(evsel->attr))); 506 - pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize( 507 - (const char *)sample, sizeof(*sample))); 408 + 409 + pydict_set_item_string_decref(dict_sample, "pid", 410 + PyInt_FromLong(sample->pid)); 411 + pydict_set_item_string_decref(dict_sample, "tid", 412 + PyInt_FromLong(sample->tid)); 413 + pydict_set_item_string_decref(dict_sample, "cpu", 414 + PyInt_FromLong(sample->cpu)); 415 + pydict_set_item_string_decref(dict_sample, "ip", 416 + PyLong_FromUnsignedLongLong(sample->ip)); 417 + pydict_set_item_string_decref(dict_sample, "time", 418 + PyLong_FromUnsignedLongLong(sample->time)); 419 + pydict_set_item_string_decref(dict_sample, "period", 420 + PyLong_FromUnsignedLongLong(sample->period)); 421 + pydict_set_item_string_decref(dict, "sample", dict_sample); 422 + 508 423 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( 509 424 (const char *)sample->raw_data, sample->raw_size)); 510 425 pydict_set_item_string_decref(dict, "comm", ··· 531 420 PyString_FromString(al->sym->name)); 532 421 } 533 422 423 + /* ip unwinding */ 424 + callchain = python_process_callchain(sample, evsel, al); 425 + pydict_set_item_string_decref(dict, "callchain", callchain); 426 + 534 427 PyTuple_SetItem(t, n++, dict); 535 428 if (_PyTuple_Resize(&t, n) == -1) 536 429 Py_FatalError("error resizing Python tuple"); ··· 542 427 retval = PyObject_CallObject(handler, t); 543 428 if (retval == NULL) 544 429 handler_call_die(handler_name); 430 + Py_DECREF(retval); 545 431 exit: 546 432 Py_DECREF(dict); 547 433 Py_DECREF(t); ··· 664 548 retval = PyObject_CallObject(handler, NULL); 665 549 if (retval == NULL) 666 550 handler_call_die("trace_end"); 667 - else 668 - Py_DECREF(retval); 551 + Py_DECREF(retval); 669 552 out: 670 553 Py_XDECREF(main_dict); 671 554 Py_XDECREF(main_module); ··· 731 616 fprintf(ofp, "common_nsecs, "); 732 617 fprintf(ofp, "common_pid, "); 733 618 fprintf(ofp, "common_comm,\n\t"); 619 + fprintf(ofp, "common_callchain, "); 734 620 735 621 not_first = 0; 736 622 count = 0; ··· 775 659 fprintf(ofp, "%%u"); 776 660 } 777 661 778 - fprintf(ofp, "\\n\" %% \\\n\t\t("); 662 + fprintf(ofp, "\" %% \\\n\t\t("); 779 663 780 664 not_first = 0; 781 665 count = 0; ··· 811 695 fprintf(ofp, "%s", f->name); 812 696 } 813 697 814 - fprintf(ofp, "),\n\n"); 698 + fprintf(ofp, ")\n\n"); 699 + 700 + fprintf(ofp, "\t\tfor node in common_callchain:"); 701 + fprintf(ofp, "\n\t\t\tif 'sym' in node:"); 702 + fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])"); 703 + fprintf(ofp, "\n\t\t\telse:"); 704 + fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n"); 705 + fprintf(ofp, "\t\tprint \"\\n\"\n\n"); 706 + 815 707 } 816 708 817 709 fprintf(ofp, "def trace_unhandled(event_name, context, "
+11 -3
tools/perf/util/session.c
··· 1083 1083 1084 1084 struct thread *perf_session__findnew(struct perf_session *session, pid_t pid) 1085 1085 { 1086 - return machine__findnew_thread(&session->machines.host, 0, pid); 1086 + return machine__findnew_thread(&session->machines.host, -1, pid); 1087 1087 } 1088 1088 1089 1089 static struct thread *perf_session__register_idle_thread(struct perf_session *session) 1090 1090 { 1091 - struct thread *thread = perf_session__findnew(session, 0); 1091 + struct thread *thread; 1092 1092 1093 + thread = machine__findnew_thread(&session->machines.host, 0, 0); 1093 1094 if (thread == NULL || thread__set_comm(thread, "swapper", 0)) { 1094 1095 pr_err("problem inserting idle task.\n"); 1095 1096 thread = NULL; ··· 1297 1296 ui_progress__init(&prog, file_size, "Processing events..."); 1298 1297 1299 1298 mmap_size = MMAP_SIZE; 1300 - if (mmap_size > file_size) 1299 + if (mmap_size > file_size) { 1301 1300 mmap_size = file_size; 1301 + session->one_mmap = true; 1302 + } 1302 1303 1303 1304 memset(mmaps, 0, sizeof(mmaps)); 1304 1305 ··· 1322 1319 mmaps[map_idx] = buf; 1323 1320 map_idx = (map_idx + 1) & (ARRAY_SIZE(mmaps) - 1); 1324 1321 file_pos = file_offset + head; 1322 + if (session->one_mmap) { 1323 + session->one_mmap_addr = buf; 1324 + session->one_mmap_offset = file_offset; 1325 + } 1325 1326 1326 1327 more: 1327 1328 event = fetch_mmaped_event(session, head, mmap_size, buf); ··· 1371 1364 ui_progress__finish(); 1372 1365 perf_session__warn_about_errors(session, tool); 1373 1366 perf_session_free_sample_buffers(session); 1367 + session->one_mmap = false; 1374 1368 return err; 1375 1369 } 1376 1370
+3
tools/perf/util/session.h
··· 36 36 struct trace_event tevent; 37 37 struct events_stats stats; 38 38 bool repipe; 39 + bool one_mmap; 40 + void *one_mmap_addr; 41 + u64 one_mmap_offset; 39 42 struct ordered_samples ordered_samples; 40 43 struct perf_data_file *file; 41 44 };
+5 -1
tools/perf/util/symbol-elf.c
··· 49 49 50 50 static inline int elf_sym__is_function(const GElf_Sym *sym) 51 51 { 52 - return elf_sym__type(sym) == STT_FUNC && 52 + return (elf_sym__type(sym) == STT_FUNC || 53 + elf_sym__type(sym) == STT_GNU_IFUNC) && 53 54 sym->st_name != 0 && 54 55 sym->st_shndx != SHN_UNDEF; 55 56 } ··· 599 598 goto out_elf_end; 600 599 } 601 600 601 + ss->is_64_bit = (gelf_getclass(elf) == ELFCLASS64); 602 + 602 603 ss->symtab = elf_section_by_name(elf, &ehdr, &ss->symshdr, ".symtab", 603 604 NULL); 604 605 if (ss->symshdr.sh_type != SHT_SYMTAB) ··· 701 698 bool remap_kernel = false, adjust_kernel_syms = false; 702 699 703 700 dso->symtab_type = syms_ss->type; 701 + dso->is_64_bit = syms_ss->is_64_bit; 704 702 dso->rel = syms_ss->ehdr.e_type == ET_REL; 705 703 706 704 /*
+22
tools/perf/util/symbol-minimal.c
··· 288 288 return 0; 289 289 } 290 290 291 + static int fd__is_64_bit(int fd) 292 + { 293 + u8 e_ident[EI_NIDENT]; 294 + 295 + if (lseek(fd, 0, SEEK_SET)) 296 + return -1; 297 + 298 + if (readn(fd, e_ident, sizeof(e_ident)) != sizeof(e_ident)) 299 + return -1; 300 + 301 + if (memcmp(e_ident, ELFMAG, SELFMAG) || 302 + e_ident[EI_VERSION] != EV_CURRENT) 303 + return -1; 304 + 305 + return e_ident[EI_CLASS] == ELFCLASS64; 306 + } 307 + 291 308 int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, 292 309 struct symsrc *ss, 293 310 struct symsrc *runtime_ss __maybe_unused, ··· 312 295 int kmodule __maybe_unused) 313 296 { 314 297 unsigned char *build_id[BUILD_ID_SIZE]; 298 + int ret; 299 + 300 + ret = fd__is_64_bit(ss->fd); 301 + if (ret >= 0) 302 + dso->is_64_bit = ret; 315 303 316 304 if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) { 317 305 dso__set_build_id(dso, build_id);
+19 -1
tools/perf/util/symbol.c
··· 342 342 return NULL; 343 343 } 344 344 345 + static struct symbol *symbols__next(struct symbol *sym) 346 + { 347 + struct rb_node *n = rb_next(&sym->rb_node); 348 + 349 + if (n) 350 + return rb_entry(n, struct symbol, rb_node); 351 + 352 + return NULL; 353 + } 354 + 345 355 struct symbol_name_rb_node { 346 356 struct rb_node rb_node; 347 357 struct symbol sym; ··· 422 412 return symbols__find(&dso->symbols[type], addr); 423 413 } 424 414 425 - static struct symbol *dso__first_symbol(struct dso *dso, enum map_type type) 415 + struct symbol *dso__first_symbol(struct dso *dso, enum map_type type) 426 416 { 427 417 return symbols__first(&dso->symbols[type]); 418 + } 419 + 420 + struct symbol *dso__next_symbol(struct symbol *sym) 421 + { 422 + return symbols__next(sym); 428 423 } 429 424 430 425 struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, ··· 1080 1065 &is_64_bit); 1081 1066 if (err) 1082 1067 goto out_err; 1068 + dso->is_64_bit = is_64_bit; 1083 1069 1084 1070 if (list_empty(&md.maps)) { 1085 1071 err = -EINVAL; ··· 1679 1663 free(kallsyms_allocated_filename); 1680 1664 1681 1665 if (err > 0 && !dso__is_kcore(dso)) { 1666 + dso->binary_type = DSO_BINARY_TYPE__KALLSYMS; 1682 1667 dso__set_long_name(dso, "[kernel.kallsyms]", false); 1683 1668 map__fixup_start(map); 1684 1669 map__fixup_end(map); ··· 1727 1710 if (err > 0) 1728 1711 pr_debug("Using %s for symbols\n", kallsyms_filename); 1729 1712 if (err > 0 && !dso__is_kcore(dso)) { 1713 + dso->binary_type = DSO_BINARY_TYPE__GUEST_KALLSYMS; 1730 1714 machine__mmap_name(machine, path, sizeof(path)); 1731 1715 dso__set_long_name(dso, strdup(path), true); 1732 1716 map__fixup_start(map);
+4
tools/perf/util/symbol.h
··· 216 216 GElf_Shdr dynshdr; 217 217 218 218 bool adjust_symbols; 219 + bool is_64_bit; 219 220 #endif 220 221 }; 221 222 ··· 239 238 u64 addr); 240 239 struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 241 240 const char *name); 241 + 242 + struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); 243 + struct symbol *dso__next_symbol(struct symbol *sym); 242 244 243 245 int filename__read_build_id(const char *filename, void *bf, size_t size); 244 246 int sysfs__read_build_id(const char *filename, void *bf, size_t size);
+7 -5
tools/perf/util/thread.c
··· 13 13 struct thread *leader; 14 14 pid_t pid = thread->pid_; 15 15 16 - if (pid == thread->tid) { 16 + if (pid == thread->tid || pid == -1) { 17 17 thread->mg = map_groups__new(); 18 18 } else { 19 19 leader = machine__findnew_thread(machine, pid, pid); ··· 60 60 { 61 61 struct comm *comm, *tmp; 62 62 63 - map_groups__put(thread->mg); 64 - thread->mg = NULL; 63 + if (thread->mg) { 64 + map_groups__put(thread->mg); 65 + thread->mg = NULL; 66 + } 65 67 list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) { 66 68 list_del(&comm->list); 67 69 comm__free(comm); ··· 129 127 size_t thread__fprintf(struct thread *thread, FILE *fp) 130 128 { 131 129 return fprintf(fp, "Thread %d %s\n", thread->tid, thread__comm_str(thread)) + 132 - map_groups__fprintf(thread->mg, verbose, fp); 130 + map_groups__fprintf(thread->mg, fp); 133 131 } 134 132 135 133 void thread__insert_map(struct thread *thread, struct map *map) 136 134 { 137 - map_groups__fixup_overlappings(thread->mg, map, verbose, stderr); 135 + map_groups__fixup_overlappings(thread->mg, map, stderr); 138 136 map_groups__insert(thread->mg, map); 139 137 } 140 138
+1
tools/perf/util/trace-event-info.c
··· 40 40 #include "trace-event.h" 41 41 #include <api/fs/debugfs.h> 42 42 #include "evsel.h" 43 + #include "debug.h" 43 44 44 45 #define VERSION "0.5" 45 46
+1 -1
tools/perf/util/trace-event-read.c
··· 22 22 #include <stdio.h> 23 23 #include <stdlib.h> 24 24 #include <string.h> 25 - #include <getopt.h> 26 25 #include <stdarg.h> 27 26 #include <sys/types.h> 28 27 #include <sys/stat.h> ··· 35 36 #include "../perf.h" 36 37 #include "util.h" 37 38 #include "trace-event.h" 39 + #include "debug.h" 38 40 39 41 static int input_fd; 40 42
+25
tools/perf/util/tsc.c
··· 1 + #include <linux/compiler.h> 2 + #include <linux/types.h> 3 + 4 + #include "tsc.h" 5 + 6 + u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc) 7 + { 8 + u64 t, quot, rem; 9 + 10 + t = ns - tc->time_zero; 11 + quot = t / tc->time_mult; 12 + rem = t % tc->time_mult; 13 + return (quot << tc->time_shift) + 14 + (rem << tc->time_shift) / tc->time_mult; 15 + } 16 + 17 + u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc) 18 + { 19 + u64 quot, rem; 20 + 21 + quot = cyc >> tc->time_shift; 22 + rem = cyc & ((1 << tc->time_shift) - 1); 23 + return tc->time_zero + quot * tc->time_mult + 24 + ((rem * tc->time_mult) >> tc->time_shift); 25 + }
+11
tools/perf/util/tsc.h
··· 1 + #ifndef __PERF_TSC_H 2 + #define __PERF_TSC_H 3 + 4 + #include <linux/types.h> 5 + 6 + #include "../arch/x86/util/tsc.h" 7 + 8 + u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc); 9 + u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc); 10 + 11 + #endif
+1
tools/perf/util/unwind-libdw.c
··· 3 3 #include <elfutils/libdwfl.h> 4 4 #include <inttypes.h> 5 5 #include <errno.h> 6 + #include "debug.h" 6 7 #include "unwind.h" 7 8 #include "unwind-libdw.h" 8 9 #include "machine.h"
+1
tools/perf/util/unwind-libunwind.c
··· 30 30 #include "unwind.h" 31 31 #include "symbol.h" 32 32 #include "util.h" 33 + #include "debug.h" 33 34 34 35 extern int 35 36 UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
+1
tools/perf/util/util.c
··· 1 1 #include "../perf.h" 2 2 #include "util.h" 3 + #include "debug.h" 3 4 #include <api/fs/fs.h> 4 5 #include <sys/mman.h> 5 6 #ifdef HAVE_BACKTRACE_SUPPORT
+1
tools/perf/util/vdso.c
··· 12 12 #include "util.h" 13 13 #include "symbol.h" 14 14 #include "linux/string.h" 15 + #include "debug.h" 15 16 16 17 static bool vdso_found; 17 18 static char vdso_file[] = "/tmp/perf-vdso.so-XXXXXX";